diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index d77b8b620d..0000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,62 +0,0 @@ -version: 2 - -jobs: - inspect: - environment: - - BOOST_LIBRARY=math - - CXX_STANDARD=gnu++11 - docker: - - image: gcc:9 - steps: - - checkout - - run: - name: Setting up Environment - command: | - echo 'export BOOST="$HOME/boost-local"' >> $BASH_ENV - if [ $CIRCLE_BRANCH = "master" ]; then - echo 'export BOOST_BRANCH="master"' >> $BASH_ENV; - else - echo 'export BOOST_BRANCH="develop"' >> $BASH_ENV; - fi - echo 'export BOOST_REMOVE="$BOOST/boost/libs/$BOOST_LIBRARY"' >> $BASH_ENV - HOME_SED_=$(echo $HOME | sed -e 's/\//\\\//g') - echo 'export HOME_SED=$HOME_SED_' >> $BASH_ENV - - run: - name: install pre dependencies - command: | - apt-get update -yqq - apt-get install git xsltproc docbook-xsl docbook-xml -y - - run: - name: Initializing git repo for boost - command: | - echo BOOST=$BOOST BOOST_REMOVE=$BOOST_REMOVE BOOST_LIBRARY=$BOOST_LIBRARY BOOST_BRANCH=$BOOST_BRANCH PWD=$PWD - mkdir $BOOST - cd $BOOST - git clone --single-branch --branch $BOOST_BRANCH https://github.com/boostorg/boost.git - cd boost - git submodule update --init --merge - rm -rf $BOOST_REMOVE - mv $HOME/project $BOOST_REMOVE - - run: - name: Bootstrapping boost-build - command: | - cd $BOOST/boost && ./bootstrap.sh && ./b2 headers - echo "using xsltproc ;" | tee $HOME/user-config.jam - echo "using boostbook : /usr/share/xml/docbook/stylesheet/docbook-xsl : /usr/share/sgml/docbook/dtd/xml/4.2 ;" | tee -a $HOME/user-config.jam - - run: - name: Building inspect - command: | - cd $BOOST/boost/tools/inspect/build && ../../../b2 -j2 address-model=64 architecture=x86 toolset=gcc cxxflags="-std=gnu++14" release dist-bin - - run: - name: Building docs - command: | - cd $BOOST_REMOVE/doc && rm -rf html/boost_math && ../../../b2 -j2 address-model=64 architecture=x86 toolset=gcc cxxflags="-std=gnu++14" release - - run: - name: Running Inspect - command: | - cd $BOOST_REMOVE && ../../dist/bin/inspect -text -workflows: - version: 2 - build_and_test: - jobs: - - inspect diff --git a/.drone.star b/.drone.star index 17b2006d7a..16b3f41d71 100644 --- a/.drone.star +++ b/.drone.star @@ -19,12 +19,10 @@ def main(ctx): gcc13_things_to_test = [ "special_fun", "distribution_tests", "mp", "misc", "interpolators", "quadrature", "autodiff", "long-running-tests", "float128_tests", "concepts", "new_floats" ] sanitizer_test = [ "special_fun", "distribution_tests", "misc", "interpolators", "quadrature", "float128_tests" ] reverse_mode_autodiff_test = [ "test_reverse_mode_autodiff", "autodiff-long-running-tests", "gradient_based_optimizers" ] - gnu_5_stds = [ "gnu++14", "c++14" ] - gnu_6_stds = [ "gnu++14", "c++14", "gnu++17", "c++17" ] - clang_6_stds = [ "c++14", "c++17" ] - gnu_9_stds = [ "gnu++14", "c++14", "gnu++17", "c++17", "gnu++2a", "c++2a" ] - clang_10_stds = [ "c++14", "c++17", "c++2a" ] - gnu_non_native = [ "gnu++17" ] + cxx17_stds = [ "c++17" ] + gnu_cxx17_stds = [ "gnu++17" ] + non_native_stds = [ "c++17" ] + s390x_things_to_test = [ "special_fun", "distribution_tests" ] gcc13_stds = [ "c++23" ] result = [] @@ -35,43 +33,30 @@ def main(ctx): # result.append(linux_cxx("Ubuntu Clang-18 C++20 ASAN" + " " + suite, "clang++-18", packages="clang-18", privileged=True, buildtype="boost", image="cppalliance/droneubuntu2404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-18', 'CXXSTD': 'gnu++20', 'TEST_SUITE': suite, 'OPTIONS': '-fsanitize=address -fsanitize=address -DBOOST_CI_SANITIZER_BUILD' }, globalenv=globalenv)) result.append(linux_cxx("Ubuntu Clang-18 C++20 USAN" + " " + suite, "clang++-18", packages="clang-18", privileged=True, buildtype="boost", image="cppalliance/droneubuntu2404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-18', 'CXXSTD': 'gnu++20', 'TEST_SUITE': suite, 'OPTIONS': '-fsanitize=undefined -fsanitize=undefined -DBOOST_CI_SANITIZER_BUILD' }, globalenv=globalenv)) - result.append(linux_cxx("Ubuntu Clang-18 C++20 TSAN" + " " + suite, "clang++-18", packages="clang-18", privileged=True, buildtype="boost", image="cppalliance/droneubuntu2404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-18', 'CXXSTD': 'gnu++20', 'TEST_SUITE': suite, 'OPTIONS': '-fsanitize=thread -fsanitize=thread -DBOOST_CI_SANITIZER_BUILD' }, globalenv=globalenv)) - result.append(linux_cxx("Ubuntu Clang-18 C++20 ISAN" + " " + suite, "clang++-18", packages="clang-18", privileged=True, buildtype="boost", image="cppalliance/droneubuntu2404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-18', 'CXXSTD': 'gnu++20', 'TEST_SUITE': suite, 'OPTIONS': '-fsanitize=integer -fsanitize=integer' }, globalenv=globalenv)) for suite in things_to_test: - for cxx in gnu_5_stds: - result.append(linux_cxx("Ubuntu g++-5 " + cxx + " " + suite, "g++-5", packages="g++-5", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-5', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - for cxx in gnu_6_stds: - result.append(linux_cxx("Ubuntu g++-6 " + cxx + " " + suite, "g++-6", packages="g++-6", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-6', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - result.append(linux_cxx("Ubuntu g++-7 " + cxx + " " + suite, "g++-7", packages="g++-7", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-7', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - result.append(linux_cxx("Ubuntu g++-8 " + cxx + " " + suite, "g++-8", packages="g++-8", buildtype="boost", image="cppalliance/droneubuntu2004:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-8', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) + # Minimum supported C++17 compilers. + for cxx in cxx17_stds: result.append(linux_cxx("Ubuntu g++-9 " + cxx + " " + suite, "g++-9", packages="g++-9", buildtype="boost", image="cppalliance/droneubuntu2004:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-9', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - for cxx in clang_6_stds: - result.append(linux_cxx("Ubuntu clang++-6 " + cxx + " " + suite, "clang++-6.0", packages="clang-6.0", llvm_os="bionic", llvm_ver="6.0", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-6.0', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) result.append(linux_cxx("Ubuntu clang++-7 " + cxx + " " + suite, "clang++-7", packages="clang-7", llvm_os="bionic", llvm_ver="7", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-7', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - result.append(linux_cxx("Ubuntu clang++-8 " + cxx + " " + suite, "clang++-8", packages="clang-8", llvm_os="bionic", llvm_ver="8", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-8', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - result.append(linux_cxx("Ubuntu clang++-9 " + cxx + " " + suite, "clang++-9", packages="clang-9", llvm_os="focal", llvm_ver="9", buildtype="boost", image="cppalliance/droneubuntu2004:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-9', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - for cxx in gnu_9_stds: - result.append(linux_cxx("Ubuntu g++-10 " + cxx + " " + suite, "g++-10", packages="g++-10", buildtype="boost", image="cppalliance/droneubuntu2204:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-10', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - result.append(linux_cxx("Ubuntu g++-11 " + cxx + " " + suite, "g++-11", packages="g++-11", buildtype="boost", image="cppalliance/droneubuntu2204:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-11', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) + + # Keep one GNU-mode GCC configuration across the full suite. This + # exercises GNU extensions used by the __float128/libquadmath path. + for cxx in gnu_cxx17_stds: result.append(linux_cxx("Ubuntu g++-12 " + cxx + " " + suite, "g++-12", packages="g++-12", buildtype="boost", image="cppalliance/droneubuntu2204:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-12', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - result.append(linux_cxx("Ubuntu clang++-14 " + cxx + " " + suite, "clang++-14", packages="clang-14", llvm_os="jammy", llvm_ver="14", buildtype="boost", image="cppalliance/droneubuntu2204:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-14', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - result.append(linux_cxx("Ubuntu clang++-15 " + cxx + " " + suite, "clang++-15", packages="clang-15", llvm_os="jammy", llvm_ver="15", buildtype="boost", image="cppalliance/droneubuntu2204:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-15', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - for cxx in clang_10_stds: - result.append(linux_cxx("Ubuntu clang++-10 " + cxx + " " + suite, "clang++-10", packages="clang-10", llvm_os="xenial", llvm_ver="10", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-10', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - for cxx in gnu_non_native: - result.append(linux_cxx("Ubuntu g++ s390s " + cxx + " " + suite, "g++", packages="g++", buildtype="boost", image="cppalliance/droneubuntu2404:multiarch", arch="s390x", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - for cxx in gnu_non_native: + + # Keep architecture coverage, but do it once in the minimum language mode. + for cxx in non_native_stds: + # The s390x runners are few and shared with all of Boost, so their queue sets the length of the + # whole build: test only the suites that big-endian and IEEE quad long double matter most for. + if suite in s390x_things_to_test: + result.append(linux_cxx("Ubuntu g++ s390s " + cxx + " " + suite, "g++", packages="g++", buildtype="boost", image="cppalliance/droneubuntu2404:multiarch", arch="s390x", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) result.append(linux_cxx("Ubuntu g++ ARM64" + cxx + " " + suite, "g++", packages="g++", buildtype="boost", image="cppalliance/droneubuntu2404:multiarch", arch="arm64", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) - for cxx in gnu_non_native: - result.append(osx_cxx("M1 Clang " + cxx + " " + suite, "clang++", buildscript="drone", buildtype="boost", xcode_version="14.1", environment={'TOOLSET': 'clang', 'CXXSTD': cxx, 'TEST_SUITE': suite, 'DEFINE': 'BOOST_MATH_NO_REAL_CONCEPT_TESTS,BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS,BOOST_MATH_MULTI_ARCH_CI_RUN', }, globalenv=globalenv)) for suite in gcc13_things_to_test: for cxx in gcc13_stds: - result.append(linux_cxx("Ubuntu g++-13 " + cxx + " " + suite, "g++-13", packages="g++-13", buildtype="boost", image="cppalliance/droneubuntu2404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-13', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) result.append(linux_cxx("Ubuntu g++-14 " + cxx + " " + suite, "g++-14", packages="g++-14", buildtype="boost", image="cppalliance/droneubuntu2404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-14', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) for suite in reverse_mode_autodiff_test: for cxx in gcc13_stds: - result.append(linux_cxx("Ubuntu g++-13 " + cxx + " " + suite, "g++-13", packages="g++-13", buildtype="boost", image="cppalliance/droneubuntu2404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-13', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) result.append(linux_cxx("Ubuntu g++-14 " + cxx + " " + suite, "g++-14", packages="g++-14", buildtype="boost", image="cppalliance/droneubuntu2404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-14', 'CXXSTD': cxx, 'TEST_SUITE': suite, }, globalenv=globalenv)) return result diff --git a/.drone/boost.sh b/.drone/boost.sh index baa747311f..6ce784622a 100755 --- a/.drone/boost.sh +++ b/.drone/boost.sh @@ -41,7 +41,7 @@ echo '==================================> SCRIPT' echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD $OPTIONS ;" > ~/user-config.jam (cd libs/config/test && ../../../b2 print_config_info print_math_info toolset=$TOOLSET) -(cd libs/math/test && ../../../b2 -j3 toolset=$TOOLSET $TEST_SUITE) +(cd libs/math/test && ../../../b2 -d0 -j3 toolset=$TOOLSET $TEST_SUITE) echo '==================================> AFTER_SUCCESS' diff --git a/.drone/drone.sh b/.drone/drone.sh index 7fc9d61b11..b7b67a34ef 100644 --- a/.drone/drone.sh +++ b/.drone/drone.sh @@ -50,9 +50,18 @@ echo '==================================> BEFORE_SCRIPT' echo '==================================> SCRIPT' -echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD $OPTIONS ;" > ~/user-config.jam +# Contract a*b + c into fused multiply-add, across expressions, as every CI job does: gcc's ISO +# -std=c++NN modes otherwise mean -ffp-contract=off. -O2 rather than b2's default of -O0: it is what +# users build with, and gcc does not fuse below it. FMA is in the base aarch64 and s390x instruction +# sets; x86 needs it switched on, where the CPU has it. The x86 runners without it (kh1 and kh2) +# have no FMA instruction to contract into, so they build without fused operations. +FMA_FLAGS="-ffp-contract=fast -O2" +if [ "$(uname -m)" = x86_64 ] && grep -qw fma /proc/cpuinfo; then FMA_FLAGS="-mfma $FMA_FLAGS"; fi +echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD $OPTIONS $FMA_FLAGS ;" > ~/user-config.jam (cd libs/config/test && ../../../b2 print_config_info print_math_info toolset=$TOOLSET) -(cd libs/math/test && ../../../b2 -j3 toolset=$TOOLSET $TEST_SUITE) +# inlining=on: b2's debug variant adds -fno-inline, which is not how users optimize, and clang +# needs over 6 GB for one multiprecision test that way. +(cd libs/math/test && ../../../b2 -d0 -j3 toolset=$TOOLSET inlining=on $TEST_SUITE) echo '==================================> AFTER_SUCCESS' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a6bbcf460..18dda3c6ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,19 +14,43 @@ on: release: types: [published, created, edited] +# A new push to a branch (develop, or a PR's) cancels that branch's older runs of this workflow: concurrency: - group: ${{ github.head_ref || github.run_id }} + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} cancel-in-progress: true +# Every job builds with the same floating-point contraction: fused multiply-add, contracted across +# expressions. gcc and clang get -ffp-contract=fast, since gcc's ISO -std=c++NN modes otherwise +# mean off and clang's default only fuses within one expression; x86 also needs -mfma (arm64 has +# FMA in its base instruction set, so macOS drops it). MSVC and clang-cl get /fp:contract (or +# -ffp-contract=fast) with /arch:AVX2. -O2 rather than b2's default of -O0 because it is what +# users build with and gcc does not fuse below it, and inlining=on because b2's debug variant +# otherwise adds -fno-inline. The CMake jobs get the same flags through CXXFLAGS. +env: + FMA_B2: cxxflags=-mfma cxxflags=-ffp-contract=fast cxxflags=-O2 inlining=on + +# b2 -l is no use as a hang detector: on POSIX it is a CPU-time rlimit that kills multithreaded +# tests, and on Windows it misfires at launch. So the test jobs have a job-level timeout instead. jobs: ubuntu-noble: runs-on: ubuntu-24.04 + # Reads the repository only; the simulator's action uses no token or secrets. + permissions: + contents: read + timeout-minutes: 120 strategy: fail-fast: false matrix: - compiler: [ g++-14, clang++-16, clang++-17, clang++-18 ] + compiler: [ g++-14, clang++-18 ] standard: [ c++20 ] suite: [ github_ci_block_1, github_ci_block_2 ] + include: + # C++14 is no longer tested elsewhere, but downstream libraries (e.g. Multiprecision) + # still include our headers in C++14 mode. Keep one job so that breaking C++14 is a + # deliberate, announced decision rather than something that slips in unnoticed. + - compiler: g++-14 + standard: c++14 + suite: github_ci_block_1 steps: - uses: actions/checkout@v6 with: @@ -48,7 +72,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt-get install -y g++-13 g++-14 clang-16 clang-17 clang-18 libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt-get install -y g++-14 clang-18 libgmp-dev libmpfr-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep @@ -76,15 +100,16 @@ jobs: run: ./config_info_travis working-directory: ../boost-root/libs/config/test - name: Test - run: ../../../b2 toolset=$TOOLSET ${{ matrix.suite }} define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER define=BOOST_MATH_RUN_MP_TESTS + run: ../../../b2 -d0 toolset=$TOOLSET ${{ matrix.suite }} define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER define=BOOST_MATH_RUN_MP_TESTS $FMA_B2 working-directory: ../boost-root/libs/math/test ubuntu-focal-no-eh: runs-on: ubuntu-24.04 + timeout-minutes: 120 strategy: fail-fast: false matrix: compiler: [ g++-13, clang++-19 ] - standard: [ c++14, c++17, c++20, c++23 ] + standard: [ c++17, c++20, c++23 ] steps: - uses: actions/checkout@v6 with: @@ -106,7 +131,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt-get install -y g++-13 clang-19 libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt-get install -y g++-13 clang-19 libgmp-dev libmpfr-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep @@ -134,15 +159,18 @@ jobs: run: ./config_info_travis working-directory: ../boost-root/libs/config/test - name: Test - run: ../../../b2 toolset=$TOOLSET no_eh_tests exception-handling=off rtti=off define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER + run: ../../../b2 -d0 toolset=$TOOLSET no_eh_tests exception-handling=off rtti=off define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER $FMA_B2 working-directory: ../boost-root/libs/math/test macos: runs-on: macos-latest + timeout-minutes: 120 + env: + FMA_B2: cxxflags=-ffp-contract=fast cxxflags=-O2 inlining=on strategy: fail-fast: false matrix: toolset: [ clang ] - standard: [ 14, 17, 20 ] + standard: [ 20 ] suite: [ github_ci_block_1, github_ci_block_2 ] steps: - uses: actions/checkout@v6 @@ -172,20 +200,24 @@ jobs: run: ./config_info_travis working-directory: ../boost-root/libs/config/test - name: Test - run: ../../../b2 toolset=${{ matrix.toolset }} cxxstd=${{ matrix.standard }} ${{ matrix.suite }} define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER + run: ../../../b2 -d0 toolset=${{ matrix.toolset }} cxxstd=${{ matrix.standard }} ${{ matrix.suite }} define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER $FMA_B2 working-directory: ../boost-root/libs/math/test windows_gcc: runs-on: windows-2025 + timeout-minutes: 120 defaults: run: shell: cmd env: ARGS: toolset=${{ matrix.toolset }} address-model=64 cxxstd=${{ matrix.standard }} + # -mfma brings in AVX. Win64 only aligns the stack to 16 bytes, but gcc emits aligned 32-byte + # AVX moves for stack objects, which crash (gcc bug 54412). Have the assembler unalign them. + FMA_B2: cxxflags=-mfma cxxflags=-ffp-contract=fast cxxflags=-O2 inlining=on cxxflags=-Wa,-muse-unaligned-vector-move strategy: fail-fast: false matrix: toolset: [ gcc ] - standard: [ 14 ] + standard: [ 17 ] suite: [ github_ci_block_1, github_ci_block_2 ] steps: - uses: actions/checkout@v6 @@ -215,21 +247,36 @@ jobs: run: config_info_travis working-directory: ../boost-root/libs/config/test - name: Test - run: ..\..\..\b2 --hash %ARGS% define=CI_SUPPRESS_KNOWN_ISSUES ${{ matrix.suite }} + # On Windows -d0 hides the output of failing tests, so rerun the failures verbosely. + run: ..\..\..\b2 -d0 --hash %ARGS% define=CI_SUPPRESS_KNOWN_ISSUES ${{ matrix.suite }} %FMA_B2% || ..\..\..\b2 -d1 --hash %ARGS% define=CI_SUPPRESS_KNOWN_ISSUES ${{ matrix.suite }} %FMA_B2% working-directory: ../boost-root/libs/math/test MSVC2022: runs-on: windows-2022 + timeout-minutes: 120 defaults: run: shell: cmd env: - ARGS: address-model=64 cxxstd=${{ matrix.standard }} + ARGS: toolset=${{ matrix.toolset }} address-model=64 cxxstd=${{ matrix.standard }} + # Optimize like the other jobs (/O2): b2's debug default of /Od makes the tests slow to run. + OPT_B2: optimization=speed inlining=on ${{ matrix.contract }} strategy: fail-fast: false matrix: toolset: [ msvc-14.3, clang-win ] - standard: [ 14, 17, latest ] + standard: [ 17, latest ] suite: [ github_ci_block_1, github_ci_block_2 ] + exclude: + - toolset: clang-win + standard: 17 + include: + # cl only fuses with /fp:contract, and only into the FMA instructions of /arch:AVX2. + # clang-cl's /fp:contract would mean -ffp-contract=on, so it is given fast directly; + # its /arch:AVX2 targets Haswell, which has FMA. + - toolset: msvc-14.3 + contract: cxxflags=/fp:contract cxxflags=/arch:AVX2 + - toolset: clang-win + contract: cxxflags=/clang:-ffp-contract=fast cxxflags=/arch:AVX2 steps: - uses: actions/checkout@v6 with: @@ -258,52 +305,17 @@ jobs: run: config_info_travis working-directory: ../boost-root/libs/config/test - name: Test - run: ..\..\..\b2 --hash %ARGS% define=CI_SUPPRESS_KNOWN_ISSUES ${{ matrix.suite }} pch=off + # On Windows -d0 hides the output of failing tests, so rerun the failures verbosely. + run: ..\..\..\b2 -d0 --hash %ARGS% define=CI_SUPPRESS_KNOWN_ISSUES ${{ matrix.suite }} pch=off %OPT_B2% || ..\..\..\b2 -d1 --hash %ARGS% define=CI_SUPPRESS_KNOWN_ISSUES ${{ matrix.suite }} pch=off %OPT_B2% working-directory: ../boost-root/libs/math/test - cygwin: - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - compiler: [ g++-11 ] - standard: [ c++17 ] - suite: [ github_ci_block_1, github_ci_block_2 ] - env: - TOOLSET: gcc - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: '0' - - name: Install Cygwin - run: choco install -y cygwin - - name: Install Package Manager - run: choco install -y cyg-get - - name: Install Packages - run: cyg-get git gcc-core gcc-g++ python39 libgmp-devel libmpfr-devel libfftw3-devel - - name: Checkout main boost - run: C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root' - - name: Update tools/boostdep - run: C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE")/../boost-root && git submodule update --init tools/boostdep' - - name: Copy files - run: C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && cp -r * ../boost-root/libs/math' - - name: Install deps - run: C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE")/../boost-root && python tools/boostdep/depinst/depinst.py math -C -I example -I tools' - - name: Bootstrap - run: C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE")/../boost-root && ./bootstrap.sh' - - name: Generate headers - run: C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE")/../boost-root && ./b2 headers' - - name: Config info install - run: C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE")/../boost-root/libs/config/test && ../../../b2 config_info_travis_install toolset=$TOOLSET' - - name: Config info - run: C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE")/../boost-root/libs/config/test && ./config_info_travis' - - name: Test - run: C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE")/../boost-root/libs/math/test && ../../../b2 toolset=$TOOLSET ${{ matrix.suite }} define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER' standalone-compile-tests-gcc: runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: compiler: [ g++-13 ] + env: + CXXFLAGS: -mfma -ffp-contract=fast -O2 steps: - uses: actions/checkout@v6 with: @@ -323,7 +335,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt-get install -y g++-13 libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt-get install -y g++-13 libgmp-dev libmpfr-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep @@ -344,6 +356,8 @@ jobs: fail-fast: false matrix: compiler: [ clang++-19 ] + env: + CXXFLAGS: -mfma -ffp-contract=fast -O2 steps: - uses: actions/checkout@v6 with: @@ -363,7 +377,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt-get install -y clang-19 libgmp-dev libmpfr-dev libfftw3-dev libtbb-dev + run: sudo apt-get install -y clang-19 libgmp-dev libmpfr-dev libtbb-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep @@ -380,11 +394,12 @@ jobs: working-directory: ../boost-root/libs/math standalone-gcc: runs-on: ubuntu-24.04 + timeout-minutes: 120 strategy: fail-fast: false matrix: compiler: [ g++-13 ] - standard: [ c++14, c++17, c++20, c++23 ] + standard: [ c++17 ] suite: [ github_ci_block_1, github_ci_block_2 ] steps: - uses: actions/checkout@v6 @@ -407,7 +422,7 @@ jobs: if: steps.retry1.outcome=='failure' run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - name: Install packages - run: sudo apt-get install -y g++-13 libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt-get install -y g++-13 libgmp-dev libmpfr-dev - name: Checkout main boost run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root - name: Update tools/boostdep @@ -435,7 +450,7 @@ jobs: run: ./config_info_travis working-directory: ../boost-root/libs/config/test - name: Test - run: ../../../b2 toolset=$TOOLSET ${{ matrix.suite }} define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER define=BOOST_MATH_STANDALONE define=BOOST_MP_STANDALONE + run: ../../../b2 -d0 toolset=$TOOLSET ${{ matrix.suite }} define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER define=BOOST_MATH_STANDALONE define=BOOST_MP_STANDALONE $FMA_B2 working-directory: ../boost-root/libs/math/test posix-cmake-test: @@ -447,12 +462,15 @@ jobs: runs-on: ${{matrix.os}} + env: + CXXFLAGS: -mfma -ffp-contract=fast -O2 + steps: - uses: actions/checkout@v6 - name: Install packages if: matrix.install - run: sudo apt install ${{matrix.install}} libgmp-dev libmpfr-dev libfftw3-dev + run: sudo apt install ${{matrix.install}} libgmp-dev libmpfr-dev - name: Setup Boost run: | @@ -492,11 +510,17 @@ jobs: matrix: include: - os: ubuntu-22.04 + cxxflags: -mfma -ffp-contract=fast -O2 - os: ubuntu-24.04 + cxxflags: -mfma -ffp-contract=fast -O2 - os: macos-15 + cxxflags: -ffp-contract=fast -O2 runs-on: ${{matrix.os}} + env: + CXXFLAGS: ${{matrix.cxxflags}} + steps: - uses: actions/checkout@v6 @@ -508,17 +532,77 @@ jobs: cmake --build . ctest --output-on-failure --no-tests=error + cmake-namespace-test: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-24.04 + compiler: g++-14 + cxxstd: 14 + cxxflags: -mfma -ffp-contract=fast + - os: ubuntu-24.04 + compiler: g++-14 + cxxstd: 20 + cxxflags: -mfma -ffp-contract=fast + - os: ubuntu-24.04 + compiler: clang++-18 + cxxstd: 17 + cxxflags: -mfma -ffp-contract=fast + - os: macos-15 + compiler: clang++ + cxxstd: 17 + cxxflags: -ffp-contract=fast + - os: windows-2022 + cxxstd: 17 + cxxflags: /fp:contract /arch:AVX2 + + runs-on: ${{matrix.os}} + + # Not optimized: the test looks for the library's symbols in the object files, which inlining + # would remove. + env: + CXXFLAGS: ${{matrix.cxxflags}} + + steps: + - uses: actions/checkout@v6 + + - name: Relocate the library into my_lib::math + if: runner.os != 'Windows' + run: | + cd test/cmake_namespace_test + mkdir __build__ && cd __build__ + cmake -DCMAKE_CXX_COMPILER=${{matrix.compiler}} -DCMAKE_CXX_STANDARD=${{matrix.cxxstd}} .. + cmake --build . -j 4 + ctest --output-on-failure --no-tests=error + + - name: Relocate the library into my_lib::math (MSVC) + if: runner.os == 'Windows' + shell: cmd + run: | + cd test/cmake_namespace_test + mkdir __build__ && cd __build__ + cmake -DCMAKE_CXX_STANDARD=${{matrix.cxxstd}} -DBOOST_MATH_NAMESPACE_TEST_HEADERS=OFF .. + cmake --build . --config Debug + ctest --output-on-failure --no-tests=error -C Debug + posix-cmake-subdir-legacy: strategy: fail-fast: false matrix: include: - os: ubuntu-22.04 + cxxflags: -mfma -ffp-contract=fast -O2 - os: ubuntu-24.04 + cxxflags: -mfma -ffp-contract=fast -O2 - os: macos-15 + cxxflags: -ffp-contract=fast -O2 runs-on: ${{matrix.os}} + env: + CXXFLAGS: ${{matrix.cxxflags}} + steps: - uses: actions/checkout@v6 @@ -560,6 +644,9 @@ jobs: runs-on: ${{matrix.os}} + env: + CXXFLAGS: -ffp-contract=fast -O2 + steps: - uses: actions/checkout@v6 @@ -612,6 +699,9 @@ jobs: runs-on: ${{matrix.os}} + env: + CXXFLAGS: -ffp-contract=fast -O2 + steps: - uses: actions/checkout@v6 @@ -664,6 +754,9 @@ jobs: runs-on: ${{matrix.os}} + env: + CXXFLAGS: -ffp-contract=fast -O2 + steps: - uses: actions/checkout@v6 @@ -713,6 +806,9 @@ jobs: runs-on: ubuntu-latest + env: + CXXFLAGS: -mfma -ffp-contract=fast -O2 + steps: - name: Intel Apt repository timeout-minutes: 1 @@ -775,22 +871,31 @@ jobs: cuda-cmake-test: strategy: fail-fast: false + matrix: + # Building all the CUDA tests takes over 45 minutes on one runner, more than any other job, + # so each shard builds and runs every third test: + shard: [ 0, 1, 2 ] runs-on: ubuntu-24.04 + env: + CXXFLAGS: -mfma -ffp-contract=fast -O2 + CUDAFLAGS: -Xcompiler=-mfma,-ffp-contract=fast,-O2 + steps: - - uses: Jimver/cuda-toolkit@v0.2.25 - id: cuda-toolkit + # CUDA 12.8 and a simulated GPU (PantheonSim): the runner has none, so + # the simulator runs the tests' kernels on its CPU. It checks results, + # not performance. + - name: Set up CUDA 12.8 and a simulated T4 + uses: pantheongpu/setup-pantheonsim@06648b8c0cb091584196678593215db2e16bd7eb # v0.1.2 with: - cuda: '12.8.0' - method: 'network' - sub-packages: '["nvcc"]' + gpu: nvidia/t4 + cuda-toolkit: '12.8' - name: Output CUDA information run: | - echo "Installed cuda version is: ${{steps.cuda-toolkit.outputs.cuda}}"+ - echo "Cuda install location: ${{steps.cuda-toolkit.outputs.CUDA_PATH}}" nvcc -V + nvidia-smi -L - uses: actions/checkout@v6 - name: Install Packages @@ -820,13 +925,245 @@ jobs: run: | cd ../boost-root mkdir __build__ && cd __build__ - cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc -DBOOST_MATH_ENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES="75;86" -DCMAKE_CUDA_STANDARD=17 .. + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON -DCMAKE_CUDA_COMPILER=/usr/local/cuda-12.8/bin/nvcc -DBOOST_MATH_ENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES="75;86" -DCMAKE_CUDA_STANDARD=17 -DCMAKE_CUDA_RUNTIME_LIBRARY=Shared .. - name: Build tests run: | cd ../boost-root/__build__ - cmake --build . --target tests -j $(nproc) - # Will leave this commented out for now. GHA does not install graphics cards by default - #- name: Run tests - # run: | - # cd ../boost-root/__build__ - # ctest --output-on-failure --no-tests=error + # This shard's tests; a run test named run-X runs the executable target X, which is built here: + ctest -N | sed -n 's/^ *Test *#[0-9]*: //p' | awk 'NR % 3 == ${{ matrix.shard }}' > shard_tests.txt + echo "$(wc -l < shard_tests.txt) tests in this shard" + cmake --build . -j $(nproc) --target $(sed -n 's/^run-//p' shard_tests.txt) + - name: Run tests + run: | + cd ../boost-root/__build__ + # Left out: inverse_gaussian_quan_float/double and lgamma_p_double fail the same + # way on a real GPU (RTX 3080 Ti), and prime_sieve_cuda takes over 25 minutes + # on a simulated one (39 s on the card). + ctest --output-on-failure --no-tests=error -j $(nproc) -R "^($(paste -sd '|' shard_tests.txt))\$" -E 'inverse_gaussian_quan|lgamma_p_double|prime_sieve_cuda' + + cmake-module-test: + strategy: + fail-fast: false + + runs-on: ubuntu-24.04 + + env: + # clang/libc++ version used to build the module. Needs a libc++ new enough to + # mix `import std` with textual libc++ includes (18 and 19 have std-module bugs). + LLVM_VERSION: "20" + # Pinned so the experimental `import std` feature UUID below stays valid. + CMAKE_VERSION: 4.4.0 + # CMake gates `import std` behind this UUID; it is specific to the CMake version. + IMPORT_STD_UUID: f35a9ac6-8463-4d38-8eec-5d6008153e7d + + steps: + - uses: actions/checkout@v6 + + - name: Install toolchain + run: | + # A recent clang + libc++ (for `import std`), clang-scan-deps (module + # dependency scanning), Ninja (required for C++ modules) and a pinned CMake. + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh $LLVM_VERSION + sudo apt-get install -y clang-tools-$LLVM_VERSION libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev ninja-build + wget -q https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-linux-x86_64.tar.gz + sudo tar -xzf cmake-$CMAKE_VERSION-linux-x86_64.tar.gz -C /opt + echo "/opt/cmake-$CMAKE_VERSION-linux-x86_64/bin" >> "$GITHUB_PATH" + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -G Ninja \ + -DBOOST_INCLUDE_LIBRARIES=$LIBRARY \ + -DBUILD_TESTING=ON \ + -DBOOST_MATH_BUILD_MODULE=ON \ + -DCMAKE_CXX_COMPILER=clang++-$LLVM_VERSION \ + -DCMAKE_CXX_FLAGS="-stdlib=libc++ -Wno-reserved-module-identifier -mfma -ffp-contract=fast -O2" \ + -DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD=$IMPORT_STD_UUID \ + -DCMAKE_CXX_STDLIB_MODULES_JSON=/usr/lib/llvm-$LLVM_VERSION/lib/libc++.modules.json \ + .. + + # Kept as a separate step so the boost.math module build time is visible on its own. + - name: Build the Boost.Math module + run: | + cd ../boost-root/__build__ + cmake --build . --target boost_math_module + + - name: Build and run the tests + run: | + cd ../boost-root/__build__ + cmake --build . --target tests + ctest --output-on-failure --no-tests=error + + cmake-module-test-gcc: + strategy: + fail-fast: false + + runs-on: ubuntu-latest + + # GCC 15 (the first release with import std support and + # libstdc++.modules.json) is not packaged for the runner image, so the job + # runs in a container that ships it. + container: ubuntu:26.04 + + env: + CXXFLAGS: -mfma -ffp-contract=fast -O2 + GCC_VERSION: "15" + # Pinned so the experimental `import std` feature UUID below stays valid. + CMAKE_VERSION: 4.4.0 + # CMake gates `import std` behind this UUID; it is specific to the CMake version. + IMPORT_STD_UUID: f35a9ac6-8463-4d38-8eec-5d6008153e7d + + steps: + - name: Install toolchain + run: | + apt-get update + apt-get install -y g++-$GCC_VERSION gcc-$GCC_VERSION ninja-build wget ca-certificates git python3 + wget -q https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-linux-x86_64.tar.gz + tar -xzf cmake-$CMAKE_VERSION-linux-x86_64.tar.gz -C /opt + echo "/opt/cmake-$CMAKE_VERSION-linux-x86_64/bin" >> "$GITHUB_PATH" + + - uses: actions/checkout@v6 + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -G Ninja \ + -DBOOST_INCLUDE_LIBRARIES=$LIBRARY \ + -DBUILD_TESTING=ON \ + -DBOOST_MATH_BUILD_MODULE=ON \ + -DCMAKE_C_COMPILER=gcc-$GCC_VERSION \ + -DCMAKE_CXX_COMPILER=g++-$GCC_VERSION \ + -DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD=$IMPORT_STD_UUID \ + .. + + # Kept as a separate step so the boost.math module build time is visible on its own. + - name: Build the Boost.Math module + run: | + cd ../boost-root/__build__ + cmake --build . --target boost_math_module + + - name: Build and run the tests + run: | + cd ../boost-root/__build__ + cmake --build . --target tests + ctest --output-on-failure --no-tests=error + + cmake-module-test-msvc: + strategy: + fail-fast: false + + runs-on: windows-2025 + + env: + # Pinned so the experimental import std feature UUID below stays valid. + CMAKE_VERSION: 4.4.0 + # CMake gates import std behind this UUID; it is specific to the CMake version. + IMPORT_STD_UUID: f35a9ac6-8463-4d38-8eec-5d6008153e7d + CXXFLAGS: /fp:contract /arch:AVX2 /O2 + + steps: + - uses: actions/checkout@v6 + + # Puts cl.exe and the MSVC INCLUDE/LIB environment on PATH for the later steps. + - name: Set up the MSVC environment + uses: ilammy/msvc-dev-cmd@v1 + + - name: Install toolchain + shell: pwsh + run: | + # A pinned CMake (the import std UUID is tied to the version) and Ninja + # (required for C++ modules). + curl.exe -L -o cmake.zip "https://github.com/Kitware/CMake/releases/download/v$env:CMAKE_VERSION/cmake-$env:CMAKE_VERSION-windows-x86_64.zip" + Expand-Archive -Path cmake.zip -DestinationPath C:\tools + "C:\tools\cmake-$env:CMAKE_VERSION-windows-x86_64\bin" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8 + choco install ninja -y + + - name: Setup Boost + shell: pwsh + run: | + $LIBRARY = ($env:GITHUB_REPOSITORY -split '/')[-1] + "LIBRARY=$LIBRARY" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + $ref = if ($env:GITHUB_BASE_REF) { $env:GITHUB_BASE_REF } else { $env:GITHUB_REF } + $ref = $ref -replace '^refs/heads/', '' + $branch = if ($ref -eq 'master') { 'master' } else { 'develop' } + cd .. + git clone -b $branch --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + New-Item -ItemType Directory -Force -Path "libs/$LIBRARY" | Out-Null + Copy-Item -Recurse -Force "$env:GITHUB_WORKSPACE/*" "libs/$LIBRARY" + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + shell: pwsh + run: | + cd ../boost-root + New-Item -ItemType Directory -Force -Path __build__ | Out-Null + cd __build__ + cmake -G Ninja ` + -DBOOST_INCLUDE_LIBRARIES="$env:LIBRARY" ` + -DBUILD_TESTING=ON ` + -DBOOST_MATH_BUILD_MODULE=ON ` + -DCMAKE_CXX_COMPILER=cl ` + -DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD="$env:IMPORT_STD_UUID" ` + .. + + # Kept as a separate step so the boost.math module build time is visible on its own. + - name: Build the Boost.Math module + shell: pwsh + run: | + cd ../boost-root/__build__ + cmake --build . --target boost_math_module + + - name: Build and run the tests + shell: pwsh + run: | + cd ../boost-root/__build__ + cmake --build . --target tests + ctest --output-on-failure --no-tests=error diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index f867c38311..226e542d7e 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -10,7 +10,6 @@ name: codecov on: - pull_request: push: branches: - master @@ -20,6 +19,11 @@ on: - fix/** - pr/** +# A new push to a branch (develop, or a PR's) cancels that branch's older runs of this workflow: +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + env: GIT_FETCH_JOBS: 8 NET_RETRY_COUNT: 5 @@ -28,6 +32,9 @@ env: B2_LINK: shared LCOV_BRANCH_COVERAGE: 0 CODECOV_NAME: Github Actions + # The contraction flags of the other CI jobs. Coverage builds are debug (-O0), where gcc does not + # fuse anyway, but this keeps the configuration the same. + B2_CXXFLAGS: -mfma -ffp-contract=fast jobs: posix: @@ -57,7 +64,7 @@ jobs: compiler: gcc-12, cxxstd: '20', os: ubuntu-22.04, install: 'g++-12-multilib', address-model: '64', suite: 'test_reverse_mode_autodiff' } - { name: Collect coverage gradient-optimizers, coverage: yes, compiler: gcc-12, cxxstd: '20', os: ubuntu-22.04, install: 'g++-12-multilib', address-model: '64', suite: 'gradient_based_optimizers' } - timeout-minutes: 360 + timeout-minutes: 180 runs-on: ${{matrix.os}} container: ${{matrix.container}} env: {B2_USE_CCACHE: 0} diff --git a/.gitignore b/.gitignore index 3158eb4a4b..26f2766687 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,10 @@ cmake-build-debug/* build.ninja .ninja* a.out +*.json +*.patch +# Test executables built in place (extensionless), but not the sources or the test_* directories: +/test/test_* +!/test/test_*.* +!/test/test_*/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f53ea49074..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,795 +0,0 @@ -# Copyright 2016, 2017 Peter Dimov -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) - -language: cpp - -sudo: false - -python: "2.7" - -os: - - linux - - osx - -branches: - only: - - master - - develop - -env: - matrix: - - BOGUS_JOB=true - -matrix: - - exclude: - - env: BOGUS_JOB=true - - include: - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=special_fun - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=special_fun - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=special_fun - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=special_fun - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=distribution_tests - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=distribution_tests - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=distribution_tests - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=distribution_tests - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=quadrature - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=quadrature - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=quadrature - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=quadrature - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=quadrature - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=float128_tests - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=float128_tests - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=float128_tests - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=float128_tests - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=float128_tests - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=../example//examples - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03 TEST_SUITE=../tools - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=../example//examples - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11 TEST_SUITE=../tools - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=../example//examples - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14 TEST_SUITE=../tools - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=../example//examples - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=gnu++14 TEST_SUITE=../tools - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=../example//examples - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z TEST_SUITE=../tools - addons: - apt: - packages: - - g++-6 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=special_fun - addons: - apt: - packages: - - g++-5 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=distribution_tests - addons: - apt: - packages: - - g++-5 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=misc - addons: - apt: - packages: - - g++-5 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=quadrature - addons: - apt: - packages: - - g++-5 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=float128_tests - addons: - apt: - packages: - - g++-5 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=../example//examples - addons: - apt: - packages: - - g++-5 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14 TEST_SUITE=../tools - addons: - apt: - packages: - - g++-5 - - libgmp-dev - - libmpfr-dev - - libfftw3-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=special_fun - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=distribution_tests - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=misc - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=quadrature - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=float128_tests - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=../example//examples - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=c++14 TEST_SUITE=../tools - addons: - apt: - packages: - - g++-8 - - libgmp-dev - - libmpfr-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++03 TEST_SUITE=special_fun - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++03 TEST_SUITE=distribution_tests - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++03 TEST_SUITE=misc - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++03 TEST_SUITE=quadrature - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++03 TEST_SUITE=float128_tests - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++03 TEST_SUITE=../example//examples - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++03 TEST_SUITE=../tools - addons: - apt: - packages: - - g++-8 - - libgmp-dev - - libmpfr-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=special_fun - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=distribution_tests - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=quadrature - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=float128_tests - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=../example//examples - addons: - apt: - packages: - - g++-8 - sources: - - ubuntu-toolchain-r-test - - - os: linux - dist: trusty - compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=gnu++17 TEST_SUITE=../tools - addons: - apt: - packages: - - g++-8 - - libgmp-dev - - libmpfr-dev - sources: - - ubuntu-toolchain-r-test - - - os: linux - compiler: clang++-6.0 - env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=c++11 TEST_SUITE=special_fun - addons: - apt: - packages: - - clang-6.0 - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-6.0 - - - os: linux - compiler: clang++-6.0 - env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=c++11 TEST_SUITE=distribution_tests - addons: - apt: - packages: - - clang-6.0 - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-6.0 - - - os: linux - compiler: clang++-6.0 - env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=c++11 TEST_SUITE=misc - addons: - apt: - packages: - - clang-6.0 - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-6.0 - - - os: linux - compiler: clang++-6.0 - env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=c++11 TEST_SUITE=quadrature - addons: - apt: - packages: - - clang-6.0 - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-6.0 - - - os: linux - compiler: clang++-6.0 - env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=c++11 TEST_SUITE=../example//examples - addons: - apt: - packages: - - clang-6.0 - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-6.0 - - - os: linux - compiler: clang++-6.0 - env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=c++11 TEST_SUITE=../tools - addons: - apt: - packages: - - clang-6.0 - - libgmp-dev - - libmpfr-dev - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-6.0 - - - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=special_fun - osx_image: xcode11 - - - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=distribution_tests - osx_image: xcode11 - - - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=misc - osx_image: xcode11 - - - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=quadrature - osx_image: xcode11 - - - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=float128_tests - osx_image: xcode11 - - - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14 TEST_SUITE=../example//examples - osx_image: xcode11 - - -install: - - cd .. - - git clone -b $TRAVIS_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root - - cd boost-root - - git submodule update --init tools/build - - git submodule update --init tools/boost_install - - git submodule update --init libs/headers - - git submodule update --init libs/config - - git submodule update --init libs/format - - git submodule update --init libs/numeric - - git submodule update --init libs/type_traits - - git submodule update --init libs/timer - - git submodule update --init tools/boostdep - - cp -r $TRAVIS_BUILD_DIR/* libs/math - - python tools/boostdep/depinst/depinst.py math - - ./bootstrap.sh - - ./b2 headers - -script: - - |- - echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD ;" > ~/user-config.jam - - (cd libs/config/test && ../../../b2 config_info_travis_install toolset=$TOOLSET && ./config_info_travis) - - (cd libs/math/test && travis_wait 60 ../../../b2 -j3 toolset=$TOOLSET $TEST_SUITE define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER) - -notifications: - email: - on_success: always diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000000..718a19defb --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,49 @@ +cff-version: 1.2.0 +message: "If you use Boost.Math in your work, please cite it using the metadata below." +title: "Boost.Math" +type: software +license: BSL-1.0 +repository-code: "https://github.com/boostorg/math" +url: "https://www.boost.org/libs/math/" + +authors: + - given-names: Nikhar + family-names: Agrawal + - given-names: Anton + family-names: Bikineev + - given-names: Matthew + family-names: Borland + - given-names: Paul A. + family-names: Bristow + - given-names: Hubert + family-names: Holin + - given-names: Marco + family-names: Guazzone + - given-names: Christopher + family-names: Kormanyos + - given-names: Bruno + family-names: Lalande + - given-names: John + family-names: Maddock + - given-names: Evan + family-names: Miller + - given-names: Jeremy W. + family-names: Murphy + - given-names: Matthew + family-names: Pulver + - given-names: Johan + family-names: Råde + - given-names: Benjamin + family-names: Sobotta + - given-names: Gautam + family-names: Sewani + - given-names: Nicholas + family-names: Thompson + - given-names: Thijs + family-names: van den Berg + - given-names: Daryle + family-names: Walker + - given-names: Xiaogang + family-names: Zhang + - given-names: Maksym + family-names: Zhelyeznyakov diff --git a/CMakeLists.txt b/CMakeLists.txt index 616c21e27f..f3ff209674 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.8...3.16) -project(boost_math VERSION 1.92.0 LANGUAGES CXX) +project(boost_math VERSION 1.93.0 LANGUAGES CXX) add_library(boost_math INTERFACE) diff --git a/README.md b/README.md index b44755ec55..28ab3f117c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Boost Math Library ============================ ->ANNOUNCEMENT: This library requires a compliant C++14 compiler. +>ANNOUNCEMENT: This library requires a compliant C++17 compiler. | | Master | Develop | @@ -54,7 +54,7 @@ along with the incomplete gamma and beta functions (four variants of each) and all the possible inverses of these, plus the digamma, various factorial functions, Bessel functions, elliptic integrals, hypergeometrics, sinus cardinals (along with their hyperbolic variants), inverse hyperbolic functions, -Legrendre/Laguerre/Hermite/Chebyshev polynomials +Legendre/Laguerre/Hermite/Chebyshev polynomials and various special power and logarithmic functions. All the implementations are fully generic and support the use of arbitrary "real-number" types, @@ -109,11 +109,11 @@ be used with the rest of boost, and may result in compiler errors. ## Supported Compilers The following compilers are tested with the CI system, and are known to work. -Currently a compiler that is fully compliant with C++14 is required to use Boost.Math. +Currently a compiler that is fully compliant with C++17 is required to use Boost.Math. -* g++ 5 or later -* clang++ 5 or later -* Visual Studio 2015 (14.0) or later +* g++ 9 or later +* clang++ 7 or later +* Visual Studio 2019 (16.0) or later ## Support, bugs and feature requests @@ -155,7 +155,7 @@ Then move to `libs/math/test`. You can either run all the tests listed in The default action for a PR or commit to a PR is for CI to run the full complement of tests. The following can be appended to the end of a commit message to modify behavior: * [ci skip] to skip all tests - * [linux] to test using GCC Versions 5-12 and Clang Versions 5-14 on Ubuntu LTS versions 18.04-22.04. + * [linux] to run the Linux compiler and architecture matrix. * [apple] to test Apple Clang on the latest version of MacOS. * [windows] to test MSVC-14.0, MSVC-14.2, MSVC-14.3, CYGWIN, and mingw on the latest version of Windows. * [standalone] to run standalone mode compile tests @@ -182,3 +182,8 @@ using doxygen ; using quickbook ; libs/math/doc$ ../../../b2 ``` + +## Citation + +If you use Boost.Math in academic work, please cite the library using the +citation metadata in [`CITATION.cff`](CITATION.cff). diff --git a/config/Jamfile.v2 b/config/Jamfile.v2 index e7fec8ee9e..28e43f1e7a 100644 --- a/config/Jamfile.v2 +++ b/config/Jamfile.v2 @@ -10,10 +10,6 @@ local ntl-path = [ modules.peek : NTL_PATH ] ; local gmp_path = [ modules.peek : GMP_PATH ] ; searched-lib quadmath ; -searched-lib fftw3 ; -searched-lib fftw3f ; -searched-lib fftw3l ; -searched-lib fftw3q ; obj has_long_double_support : has_long_double_support.cpp ; obj has_mpfr_class : has_mpfr_class.cpp : @@ -26,7 +22,6 @@ obj has_gmpxx : has_gmpxx.cpp : obj has_gcc_visibility : has_gcc_visibility.cpp : gcc:-fvisibility=hidden gcc:-Werror ; exe has_float128 : has_float128.cpp quadmath ; -exe has_fftw3 : has_fftw3.cpp fftw3 fftw3f fftw3l ; exe has_intel_quad : has_intel_quad.cpp : -Qoption,cpp,--extended_float_type ; obj has_128bit_floatmax_t : has_128bit_floatmax_t.cpp ; obj has_mpfr : has_mpfr.cpp : @@ -49,7 +44,6 @@ explicit has_gcc_visibility ; explicit has_float128 ; explicit has_intel_quad ; explicit has_128bit_floatmax_t ; -explicit has_fftw3 ; explicit is_ci_sanitizer_run ; explicit is_ci_standalone_run ; explicit is_cygwin_run ; diff --git a/config/has_fftw3.cpp b/config/has_fftw3.cpp deleted file mode 100644 index 8045685704..0000000000 --- a/config/has_fftw3.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright John Maddock 2017. -// 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) - -#include - -int main() -{ - fftwq_plan plan; // early versions don't have this it seems. - - fftw_cleanup(); - fftwf_cleanup(); - fftwl_cleanup(); - - - return 0; -} - diff --git a/doc/differentiation/autodiff_reverse.qbk b/doc/differentiation/autodiff_reverse.qbk index 55ae6412e0..d438c0e6fb 100644 --- a/doc/differentiation/autodiff_reverse.qbk +++ b/doc/differentiation/autodiff_reverse.qbk @@ -244,127 +244,127 @@ Some key points about reverse mode automatic differentiation: \[/ BEGIN SPECFUN TABLE\] [table [[Function] [compiles with ET ON] [runs with ET ON] [compiles with ET OFF] [runs with ET OFF] [works with multiprecision] [known issues]] -[[tgamma] [True] [True] [True] [False] [False] [derivatives incorrect when argument is an integer]] -[[tgamma1pm1] [False] [N/A] [True] [False] [False] [N/A]] -[[lgamma] [True] [True] [True] [False] [False] [N/A]] -[[digamma] [True] [True] [True] [False] [False] [N/A]] -[[trigamma] [True] [True] [True] [False] [False] [N/A]] -[[polygamma] [False] [N/A] [True] [False] [False] [N/A]] -[[tgamma_ratio] [False] [N/A] [True] [False] [False] [N/A]] -[[tgamma_delta_ratio] [False] [N/A] [True] [False] [False] [N/A]] -[[gamma_p] [False] [N/A] [True] [False] [False] [N/A]] -[[gamma_q] [False] [N/A] [True] [False] [False] [N/A]] -[[tgamma_lower] [False] [N/A] [True] [False] [False] [N/A]] -[[rising_factorial] [False] [N/A] [True] [False] [False] [N/A]] -[[falling_factorial] [False] [N/A] [True] [False] [False] [N/A]] -[[beta] [False] [N/A] [True] [False] [False] [N/A]] -[[ibeta] [False] [N/A] [True] [False] [False] [N/A]] -[[ibetac] [False] [N/A] [True] [False] [False] [N/A]] -[[betac] [False] [N/A] [True] [False] [False] [N/A]] -[[ibeta_inv] [False] [N/A] [True] [False] [False] [N/A]] -[[ibetac_inv] [False] [N/A] [True] [False] [False] [N/A]] -[[ibeta_inva] [False] [N/A] [True] [False] [False] [N/A]] -[[ibetac_inva] [False] [N/A] [True] [False] [False] [N/A]] -[[ibeta_invb] [False] [N/A] [True] [False] [False] [N/A]] -[[ibetac_invb] [False] [N/A] [True] [False] [False] [N/A]] -[[ibeta_derivative] [False] [N/A] [True] [False] [False] [N/A]] -[[legendre_p] [False] [N/A] [True] [False] [False] [N/A]] -[[legendre_p_prime] [True] [True] [True] [False] [False] [N/A]] -[[legendre_q] [False] [N/A] [True] [False] [False] [N/A]] -[[laguerre] [True] [True] [True] [False] [False] [N/A]] -[[hermite] [True] [True] [True] [False] [False] [N/A]] -[[chebyshev_t] [True] [True] [True] [False] [False] [N/A]] -[[chebyshev_u] [True] [True] [True] [False] [False] [N/A]] -[[chebyshev_t_prime] [True] [True] [True] [False] [False] [N/A]] +[[tgamma] [True] [True] [True] [True] [False] [derivatives incorrect when argument is an integer]] +[[tgamma1pm1] [False] [N/A] [True] [True] [False] [N/A]] +[[lgamma] [True] [True] [True] [True] [False] [N/A]] +[[digamma] [True] [True] [True] [True] [False] [N/A]] +[[trigamma] [True] [True] [True] [True] [False] [N/A]] +[[polygamma] [False] [N/A] [True] [True] [False] [N/A]] +[[tgamma_ratio] [False] [N/A] [True] [True] [False] [N/A]] +[[tgamma_delta_ratio] [False] [N/A] [True] [True] [False] [N/A]] +[[gamma_p] [False] [N/A] [True] [True] [False] [N/A]] +[[gamma_q] [False] [N/A] [True] [True] [False] [N/A]] +[[tgamma_lower] [False] [N/A] [True] [True] [False] [N/A]] +[[rising_factorial] [False] [N/A] [True] [True] [False] [N/A]] +[[falling_factorial] [False] [N/A] [True] [True] [False] [N/A]] +[[beta] [False] [N/A] [True] [True] [False] [N/A]] +[[ibeta] [False] [N/A] [True] [True] [False] [N/A]] +[[ibetac] [False] [N/A] [True] [True] [False] [N/A]] +[[betac] [False] [N/A] [True] [True] [False] [N/A]] +[[ibeta_inv] [False] [N/A] [True] [True] [False] [N/A]] +[[ibetac_inv] [False] [N/A] [True] [True] [False] [N/A]] +[[ibeta_inva] [False] [N/A] [True] [True] [False] [N/A]] +[[ibetac_inva] [False] [N/A] [True] [True] [False] [N/A]] +[[ibeta_invb] [False] [N/A] [True] [True] [False] [N/A]] +[[ibetac_invb] [False] [N/A] [True] [True] [False] [N/A]] +[[ibeta_derivative] [False] [N/A] [True] [True] [False] [N/A]] +[[legendre_p] [False] [N/A] [True] [True] [False] [N/A]] +[[legendre_p_prime] [True] [True] [True] [True] [False] [N/A]] +[[legendre_q] [False] [N/A] [True] [True] [False] [N/A]] +[[laguerre] [True] [True] [True] [True] [False] [N/A]] +[[hermite] [True] [True] [True] [True] [False] [N/A]] +[[chebyshev_t] [True] [True] [True] [True] [False] [N/A]] +[[chebyshev_u] [True] [True] [True] [True] [False] [N/A]] +[[chebyshev_t_prime] [True] [True] [True] [True] [False] [N/A]] [[spherical_harmonic] [False] [N/A] [False] [N/A] [False] [N/A]] -[[spherical_harmonic_r] [False] [N/A] [True] [False] [False] [N/A]] -[[spherical_harmonic_i] [False] [N/A] [True] [False] [False] [N/A]] +[[spherical_harmonic_r] [False] [N/A] [True] [True] [False] [N/A]] +[[spherical_harmonic_i] [False] [N/A] [True] [True] [False] [N/A]] [[gegenbauer] [False] [N/A] [False] [N/A] [False] [N/A]] [[gegenbauer_prime] [False] [N/A] [False] [N/A] [False] [N/A]] [[gegenbauer_derivative] [False] [N/A] [False] [N/A] [False] [N/A]] -[[jacobi] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_derivative] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_prime] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_double_prime] [True] [True] [True] [False] [False] [N/A]] -[[cyl_bessel_j] [False] [N/A] [True] [False] [False] [N/A]] -[[cyl_neumann] [False] [N/A] [True] [False] [False] [N/A]] -[[cyl_bessel_i] [False] [N/A] [True] [False] [False] [N/A]] -[[cyl_bessel_k] [False] [N/A] [True] [False] [False] [N/A]] -[[sph_bessel] [False] [N/A] [True] [False] [False] [N/A]] -[[sph_neumann] [False] [N/A] [True] [False] [False] [N/A]] -[[cyl_bessel_j_prime] [False] [N/A] [True] [False] [False] [N/A]] -[[cyl_neumann_prime] [False] [N/A] [True] [False] [False] [N/A]] -[[cyl_bessel_i_prime] [False] [N/A] [True] [False] [False] [N/A]] -[[cyl_bessel_k_prime] [False] [N/A] [True] [False] [False] [N/A]] +[[jacobi] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_derivative] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_prime] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_double_prime] [True] [True] [True] [True] [False] [N/A]] +[[cyl_bessel_j] [False] [N/A] [True] [True] [False] [N/A]] +[[cyl_neumann] [False] [N/A] [True] [True] [False] [N/A]] +[[cyl_bessel_i] [False] [N/A] [True] [True] [False] [N/A]] +[[cyl_bessel_k] [False] [N/A] [True] [True] [False] [N/A]] +[[sph_bessel] [False] [N/A] [True] [True] [False] [N/A]] +[[sph_neumann] [False] [N/A] [True] [True] [False] [N/A]] +[[cyl_bessel_j_prime] [False] [N/A] [True] [True] [False] [N/A]] +[[cyl_neumann_prime] [False] [N/A] [True] [True] [False] [N/A]] +[[cyl_bessel_i_prime] [False] [N/A] [True] [True] [False] [N/A]] +[[cyl_bessel_k_prime] [False] [N/A] [True] [True] [False] [N/A]] [[sph_bessel_prime] [False] [N/A] [False] [N/A] [False] [N/A]] [[sph_neumann_prime] [False] [N/A] [False] [N/A] [False] [N/A]] [[cyl_hankel_1] [False] [N/A] [False] [N/A] [False] [N/A]] [[cyl_hankel_2] [False] [N/A] [False] [N/A] [False] [N/A]] [[sph_hankel_1] [False] [N/A] [False] [N/A] [False] [N/A]] [[sph_hankel_2] [False] [N/A] [False] [N/A] [False] [N/A]] -[[airy_ai] [False] [N/A] [True] [False] [False] [N/A]] -[[airy_bi] [False] [N/A] [True] [False] [False] [N/A]] -[[airy_ai_prime] [False] [N/A] [True] [False] [False] [N/A]] -[[airy_bi_prime] [False] [N/A] [True] [False] [False] [N/A]] -[[ellint_rf] [False] [N/A] [True] [False] [False] [N/A]] -[[ellint_rd] [False] [N/A] [True] [False] [False] [N/A]] -[[ellint_rj] [False] [N/A] [True] [False] [False] [N/A]] -[[ellint_rc] [False] [N/A] [True] [False] [False] [N/A]] -[[ellint_rg] [False] [N/A] [True] [False] [False] [N/A]] -[[ellint_1] [False] [N/A] [True] [False] [False] [N/A]] -[[ellint_2] [False] [N/A] [True] [False] [False] [N/A]] -[[ellint_3] [False] [N/A] [True] [False] [False] [N/A]] -[[ellint_d] [False] [N/A] [True] [False] [False] [N/A]] -[[jacobi_zeta] [False] [N/A] [True] [False] [False] [N/A]] -[[heuman_lambda] [False] [N/A] [True] [False] [False] [N/A]] -[[jacobi_cd] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_cn] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_cs] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_dc] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_dn] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_ds] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_nc] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_nd] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_ns] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_sc] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_sd] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_sn] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta1] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta1tau] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta2] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta1tau] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta3] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta3tau] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta3m1] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta3m1tau] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta4] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta4tau] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta4m1] [True] [True] [True] [False] [False] [N/A]] -[[jacobi_theta4m1tau] [True] [True] [True] [False] [False] [N/A]] +[[airy_ai] [False] [N/A] [True] [True] [False] [N/A]] +[[airy_bi] [False] [N/A] [True] [True] [False] [N/A]] +[[airy_ai_prime] [False] [N/A] [True] [True] [False] [N/A]] +[[airy_bi_prime] [False] [N/A] [True] [True] [False] [N/A]] +[[ellint_rf] [False] [N/A] [True] [True] [False] [N/A]] +[[ellint_rd] [False] [N/A] [True] [True] [False] [N/A]] +[[ellint_rj] [False] [N/A] [True] [True] [False] [N/A]] +[[ellint_rc] [False] [N/A] [True] [True] [False] [N/A]] +[[ellint_rg] [False] [N/A] [True] [True] [False] [N/A]] +[[ellint_1] [False] [N/A] [True] [True] [False] [N/A]] +[[ellint_2] [False] [N/A] [True] [True] [False] [N/A]] +[[ellint_3] [False] [N/A] [True] [True] [False] [N/A]] +[[ellint_d] [False] [N/A] [True] [True] [False] [N/A]] +[[jacobi_zeta] [False] [N/A] [True] [True] [False] [N/A]] +[[heuman_lambda] [False] [N/A] [True] [True] [False] [N/A]] +[[jacobi_cd] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_cn] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_cs] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_dc] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_dn] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_ds] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_nc] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_nd] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_ns] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_sc] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_sd] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_sn] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta1] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta1tau] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta2] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta1tau] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta3] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta3tau] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta3m1] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta3m1tau] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta4] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta4tau] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta4m1] [True] [True] [True] [True] [False] [N/A]] +[[jacobi_theta4m1tau] [True] [True] [True] [True] [False] [N/A]] [[lambert_w0] [False] [N/A] [False] [N/A] [False] [N/A]] [[lambert_wm1] [False] [N/A] [False] [N/A] [False] [N/A]] [[lambert_w0_prime] [False] [N/A] [False] [N/A] [False] [N/A]] [[lambert_wm1_prime] [False] [N/A] [False] [N/A] [False] [N/A]] -[[zeta] [False] [N/A] [True] [False] [False] [N/A]] -[[expint] [False] [N/A] [True] [False] [False] [N/A]] -[[hypergeometric_1F0] [True] [True] [True] [False] [False] [N/A]] -[[hypergeometric_0F1] [False] [N/A] [True] [False] [False] [N/A]] -[[hypergeometric_2F0] [False] [N/A] [True] [False] [False] [N/A]] -[[hypergeometric_1F1] [False] [N/A] [True] [False] [False] [N/A]] -[[sin_pi] [True] [True] [True] [False] [False] [N/A]] -[[cos_pi] [True] [True] [True] [False] [False] [N/A]] -[[log1p] [True] [True] [True] [False] [False] [N/A]] -[[expm1] [True] [True] [True] [False] [False] [N/A]] -[[cbrt] [True] [True] [True] [False] [False] [N/A]] -[[sqrt1pm1] [False] [N/A] [True] [False] [False] [N/A]] -[[powm1] [False] [N/A] [True] [False] [False] [N/A]] -[[hypot] [True] [True] [True] [False] [False] [N/A]] +[[zeta] [False] [N/A] [True] [True] [False] [N/A]] +[[expint] [False] [N/A] [True] [True] [False] [N/A]] +[[hypergeometric_1F0] [True] [True] [True] [True] [True] [N/A]] +[[hypergeometric_0F1] [False] [N/A] [True] [True] [False] [N/A]] +[[hypergeometric_2F0] [False] [N/A] [True] [True] [False] [N/A]] +[[hypergeometric_1F1] [False] [N/A] [True] [True] [False] [N/A]] +[[sin_pi] [True] [True] [True] [True] [False] [N/A]] +[[cos_pi] [True] [True] [True] [True] [False] [N/A]] +[[log1p] [True] [True] [True] [True] [False] [N/A]] +[[expm1] [True] [True] [True] [True] [False] [N/A]] +[[cbrt] [True] [True] [True] [True] [True] [N/A]] +[[sqrt1pm1] [False] [N/A] [True] [True] [False] [N/A]] +[[powm1] [False] [N/A] [True] [True] [False] [N/A]] +[[hypot] [True] [True] [True] [True] [True] [N/A]] [[rsqrt] [False] [N/A] [False] [N/A] [False] [N/A]] [[logaddexp] [False] [N/A] [False] [N/A] [False] [N/A]] [[logsumexp] [False] [N/A] [False] [N/A] [False] [N/A]] -[[sinc_pi] [True] [True] [True] [False] [False] [N/A]] -[[sinhc_pi] [True] [True] [True] [False] [False] [N/A]] -[[owens_t] [False] [N/A] [True] [False] [False] [N/A]] +[[sinc_pi] [True] [True] [True] [True] [True] [N/A]] +[[sinhc_pi] [True] [True] [True] [True] [True] [N/A]] +[[owens_t] [False] [N/A] [True] [True] [False] [N/A]] ] \[/ END SPECFUN TABLE\] [h1:expression_templates Example 1: Linear Regression] diff --git a/doc/distributions/background.qbk b/doc/distributions/background.qbk index a3036cdb80..988752b66a 100644 --- a/doc/distributions/background.qbk +++ b/doc/distributions/background.qbk @@ -52,13 +52,11 @@ integer-valued arguments when applicable. [caution The quantile function of a discrete distribution will by -default return an integer result that has been -/rounded outwards/. That is to say lower quantiles (where the probability is -less than 0.5) are rounded downward, and upper quantiles (where the probability -is greater than 0.5) are rounded upwards. This behaviour -ensures that if an X% quantile is requested, then /at least/ the requested -coverage will be present in the central region, and /no more than/ -the requested coverage will be present in the tails. +default return an integer result: +`quantile(dist, p)` is the smallest integer /k/ with `cdf(dist, k) >= p`, and +`quantile(complement(dist, q))` is the smallest integer /k/ with +`cdf(complement(dist, k)) <= q`. This is the `integer_round_up` policy, and +the definition R, SciPy, Julia and Mathematica use. This behaviour can be changed so that the quantile functions are rounded differently, or even return a real-valued result using diff --git a/doc/distributions/bernoulli.qbk b/doc/distributions/bernoulli.qbk index 719c42cd9e..e2de468dea 100644 --- a/doc/distributions/bernoulli.qbk +++ b/doc/distributions/bernoulli.qbk @@ -97,7 +97,7 @@ the binomial distribution with a single trial should be used, for example: [[cdf][Using the relation: cdf = 1 - p for k = 0, else 1]] [[cdf complement][q = 1 - p]] [[quantile][if x <= (1-p) 0 else 1]] -[[quantile from the complement][if x <= (1-p) 1 else 0]] +[[quantile from the complement][if x >= p 0 else 1]] [[mean][p]] [[variance][p * (1 - p)]] [[mode][if (p < 0.5) 0 else 1]] diff --git a/doc/distributions/dist_reference.qbk b/doc/distributions/dist_reference.qbk index 2dd06bcb8b..de34e51d20 100644 --- a/doc/distributions/dist_reference.qbk +++ b/doc/distributions/dist_reference.qbk @@ -13,6 +13,7 @@ [include empirical_cdf.qbk] [include exponential.qbk] [include extreme_value.qbk] +[include generalized_extreme_value.qbk] [include fisher.qbk] [include gamma.qbk] [include geometric.qbk] @@ -42,6 +43,7 @@ [include students_t.qbk] [include triangular.qbk] [include uniform.qbk] +[include von_mises.qbk] [include weibull.qbk] [endsect] [/section:dists Distributions] diff --git a/doc/distributions/dist_tutorial.qbk b/doc/distributions/dist_tutorial.qbk index 80e8e2e458..62220cfa73 100644 --- a/doc/distributions/dist_tutorial.qbk +++ b/doc/distributions/dist_tutorial.qbk @@ -146,15 +146,32 @@ The logcdf and logpdf functions are minimally calculated with log(cdf(my_dist, x and log(pdf(my_dist, x)) respectively. The following distributions have specialized implementations of the logcdf: +* Beta +* Binomial +* Chi Squared * Exponential * Extreme Value +* Fisher F +* Gamma * Geometric +* Inverse Chi Squared +* Inverse Gamma * Laplace * Logistic +* Negative Binomial * Pareto +* Poisson * Rayleigh +* Students t * Weibull +The specialisations for the distributions built on the incomplete gamma and beta functions (beta, binomial, +chi squared, Fisher F, gamma, inverse chi squared, inverse gamma, negative binomial, Poisson and Students t) +use [link math_toolkit.sf_gamma.igamma lgamma_p and lgamma_q] and +[link math_toolkit.sf_beta.ibeta_function libeta and libetac], so both `logcdf(dist, x)` and +`logcdf(complement(dist, x))` stay finite and accurate far into the tails, where `log(cdf(dist, x))` +underflows to -infinity. + And the following distributions have specialized implementations of logpdf: * Exponential @@ -278,13 +295,11 @@ function. The quantile functions for these distributions are hard to specify in a manner that will satisfy everyone all of the time. The default -behaviour is to return an integer result, that has been rounded -/outwards/: that is to say, lower quantiles - where the probability -is less than 0.5 are rounded down, while upper quantiles - where -the probability is greater than 0.5 - are rounded up. This behaviour -ensures that if an X% quantile is requested, then /at least/ the requested -coverage will be present in the central region, and /no more than/ -the requested coverage will be present in the tails. +behaviour is to return an integer result: +`quantile(dist, p)` is the smallest integer /k/ with `cdf(dist, k) >= p`, and +`quantile(complement(dist, q))` is the smallest integer /k/ with +`cdf(complement(dist, k)) <= q`. This is the `integer_round_up` policy, and +the definition R, SciPy, Julia and Mathematica use. This behaviour can be changed so that the quantile functions are rounded differently, or return a real-valued result using diff --git a/doc/distributions/generalized_extreme_value.qbk b/doc/distributions/generalized_extreme_value.qbk new file mode 100644 index 0000000000..4b6980ae97 --- /dev/null +++ b/doc/distributions/generalized_extreme_value.qbk @@ -0,0 +1,116 @@ +[section:gev_dist Generalized Extreme Value Distribution] + +``#include `` + + template + class generalized_extreme_value_distribution; + + typedef generalized_extreme_value_distribution<> generalized_extreme_value; + + template + class generalized_extreme_value_distribution + { + public: + typedef RealType value_type; + + generalized_extreme_value_distribution(RealType location = 0, RealType scale = 1, RealType shape = 0); + + RealType location()const; + RealType scale()const; + RealType shape()const; + }; + +The [@https://en.wikipedia.org/wiki/Generalized_extreme_value_distribution generalized extreme value distribution] +is the family of limit distributions of the normalized maxima of independent, identically distributed +random variables. With location [mu], scale [sigma] and shape [xi], its CDF is + +[expression F(x) = e[super -t(x)], t(x) = (1 + [xi](x - [mu])/[sigma])[super -1/[xi]]] + +on the support where 1 + [xi](x - [mu])/[sigma] > 0, and its PDF is + +[expression f(x) = t(x)[super [xi]+1] e[super -t(x)] / [sigma]] + +The shape selects the type: + +* [xi] > 0, the Fr[eacute]chet type: heavy tailed to the right, and bounded below at [mu] - [sigma]/[xi]. +* [xi] = 0, the Gumbel type, where t(x) = e[super -(x-[mu])/[sigma]]: this is the __extreme_distrib. +* [xi] < 0, the reversed Weibull type: bounded above at [mu] - [sigma]/[xi]. + +Note that the sign convention for the shape varies: SciPy's `genextreme`, for example, takes c = -[xi]. + +[h4 Member Functions] + + generalized_extreme_value_distribution(RealType location = 0, RealType scale = 1, RealType shape = 0); + +Constructs a generalized extreme value distribution with the specified location, scale and shape. + +Requires that location and shape are finite and that scale is finite and > 0, otherwise calls __domain_error. + + RealType location()const; + RealType scale()const; + RealType shape()const; + +Return the parameters of the distribution. + +[h4 Non-member Accessors] + +All the [link math_toolkit.dist_ref.nmp usual non-member accessor functions] +that are generic to all distributions are supported: __usual_accessors. + +The domain of the random variable is \[-[infin], +[infin]\]: outside the support the PDF is zero +and the CDF is 0 or 1. `support` returns the bounded end for [xi] [ne] 0. + +The mean is infinite for [xi] [ge] 1 and the variance for [xi] [ge] 1/2, and both return +[infin] there. +The skewness is undefined for [xi] [ge] 1/3 and the kurtosis for [xi] [ge] 1/4, where they call __domain_error. The quantile at the unbounded ends calls __overflow_error, +as does the PDF at the upper end point when [xi] < -1, where the density is infinite. + +`logpdf`, `logcdf` and the log of the complement of the CDF are specialized for accuracy deep in the tails. + +[h4 Accuracy] + +Against references computed with mpmath at the double values of the arguments, the PDF, CDF, their +complements and logs, and the quantiles are within a few ulps, except where the function is itself +ill-conditioned: deep in the tails of the CDF, where e[super -t] magnifies the rounding of (x - [mu])/[sigma] +(up to about 30 ulps), and where the quantile is close to zero and [mu] + [sigma] q cancels. +The mean, variance, mode, median and entropy are within a few ulps. Skewness and kurtosis are accurate to +an absolute error of a few tens of epsilon for |[xi]| < 1/4, and of a few hundred for larger |[xi]|, +where they are third and fourth differences of log[Gamma](1 - k[xi]); both change sign +(the skewness near [xi] = -0.28, the excess kurtosis near [xi] = -0.15), so their relative error is unbounded there. + +[h4 Implementation] + +In the following table [mu] is the location, [sigma] the scale, [xi] the shape, z = (x - [mu])/[sigma], +/p/ the probability and /q = 1 - p/; g[sub k] = [Gamma](1 - k[xi]). + +[table +[[Function][Implementation Notes]] +[[pdf][exp(-(1 + [xi])L - t) / [sigma], where L = -log t = log1p([xi]z)/[xi], and t = e[super -L].]] +[[logpdf][-log [sigma] - (1 + [xi])L - t]] +[[cdf][exp(-t)]] +[[logcdf][-t]] +[[cdf complement][-expm1(-t)]] +[[log of the cdf complement][log(-expm1(-t)) for t < log 2, otherwise log1p(-e[super -t])]] +[[quantile][[mu] + [sigma] expm1(-[xi] log y)/[xi] with y = -log p, or [mu] + [sigma](y[super -[xi]] - 1)/[xi] when |[xi] log y| > 1.]] +[[quantile from the complement][As the quantile, with y = -log1p(-q).]] +[[mean][[mu] + [sigma] tgamma1pm1(-[xi])/[xi]]] +[[variance][([sigma]g[sub 1]/[xi])[super 2] expm1(A[sub 2]), with A[sub k] = log g[sub k] - k log g[sub 1]]] +[[skewness][sign([xi]) (g[sub 3] - 3g[sub 1]g[sub 2] + 2g[sub 1][super 3]) / (g[sub 2] - g[sub 1][super 2])[super 3/2], written in terms of the A[sub k] + so that the cancellation at small [xi] is exact: the combinations of the A[sub k] are summed from the Taylor series + log[Gamma](1 - z) = [gamma]z + [sum] [zeta](j) z[super j]/j, in which their low orders vanish identically, while the series converges quickly.]] +[[kurtosis excess][(g[sub 4] - 4g[sub 1]g[sub 3] + 6g[sub 1][super 2]g[sub 2] - 3g[sub 1][super 4]) / (g[sub 2] - g[sub 1][super 2])[super 2] - 3, as for the skewness.]] +[[mode][[mu] + [sigma]((1 + [xi])[super -[xi]] - 1)/[xi], or the upper end point [mu] - [sigma]/[xi] for [xi] [le] -1.]] +[[median][[mu] + [sigma]((log 2)[super -[xi]] - 1)/[xi]]] +[[entropy][log [sigma] + [gamma](1 + [xi]) + 1]] +] + +At [xi] = 0, and for |[xi]| below machine epsilon in the moments, the Gumbel formulas are used. + +[endsect] [/section:gev_dist Generalized Extreme Value] + +[/ generalized_extreme_value.qbk + Copyright 2026 Nick Thompson. + 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). +] diff --git a/doc/distributions/geometric.qbk b/doc/distributions/geometric.qbk index ef23113995..3ffe2f11b0 100644 --- a/doc/distributions/geometric.qbk +++ b/doc/distributions/geometric.qbk @@ -290,16 +290,14 @@ the context of this distribution: ``cdf(complement(geometric(p), k))``]] [[__quantile] - [The [*greatest] number of failures /k/ expected to be observed from /k/ trials - with success fraction /p/, at probability /P/. Note that the value returned - is a real-number, and not an integer. Depending on the use case you may - want to take either the floor or ceiling of the real result. For example: + [The [*smallest] number of failures /k/ with `cdf(geometric(p), k) >= P`. + The result is rounded to an integer as the discrete quantile policy + (__understand_dis_quant) asks: use `discrete_quantile` to get the + real-valued result instead. For example: ``quantile(geometric(p), P)``]] [[__quantile_c] - [The [*smallest] number of failures /k/ expected to be observed from /k/ trials - with success fraction /p/, at probability /P/. Note that the value returned - is a real-number, and not an integer. Depending on the use case you may - want to take either the floor or ceiling of the real result. For example: + [The [*smallest] number of failures /k/ with `cdf(complement(geometric(p), k)) <= P`, + rounded in the same way. For example: ``quantile(complement(geometric(p), P))``]] ] @@ -327,8 +325,9 @@ the expected number of failures using the quantile. [[cdf][cdf = 1 - q[super k=1]]] [[logcdf][log(cdf) = log1p(-exp(log1p(-p) * (k+1)))]] [[cdf complement][exp(log1p(-p) * (k+1))]] -[[quantile][k = log1p(-x) / log1p(-p) -1]] -[[quantile from the complement][k = log(x) / log1p(-p) -1]] +[[quantile][k = log1p(-x) / log1p(-p) -1, then rounded as the policy asks + using the cdf at the nearby integers]] +[[quantile from the complement][k = log(x) / log1p(-p) -1, rounded in the same way]] [[mean][(1-p)/p]] [[variance][(1-p)/p[sup2]]] [[mode][0]] diff --git a/doc/distributions/hyperexponential.qbk b/doc/distributions/hyperexponential.qbk index d2b2a1d48b..bea4efed6f 100644 --- a/doc/distributions/hyperexponential.qbk +++ b/doc/distributions/hyperexponential.qbk @@ -39,10 +39,8 @@ template hyperexponential_distribution(RateRangeT const& rate_range); - #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) // C++11 initializer lists supported. hyperexponential_distribution(std::initializer_list l1, std::initializer_list l2); hyperexponential_distribution(std::initializer_list l1); - #endif // Accessors: std::size_t num_phases() const; diff --git a/doc/distributions/hypergeometric.qbk b/doc/distributions/hypergeometric.qbk index 4175f720c3..53e1dd0e05 100644 --- a/doc/distributions/hypergeometric.qbk +++ b/doc/distributions/hypergeometric.qbk @@ -89,16 +89,16 @@ that are generic to all distributions are supported: __usual_accessors. The domain of the random variable are the 64-bit unsigned integers in the range \[max(0, n + r - N), min(n, r)\]. A __domain_error is raised if the -random variable is outside this range, or is not an integral value. +random variable is outside this range. The CDF and its complement also raise a +__domain_error for a non-integral random variable; the PDF instead returns the +analytic continuation of its formula in terms of binomial coefficients (see Implementation below). [caution -The quantile function will by default return an integer result that has been -/rounded outwards/. That is to say lower quantiles (where the probability is -less than 0.5) are rounded downward, and upper quantiles (where the probability -is greater than 0.5) are rounded upwards. This behaviour -ensures that if an X% quantile is requested, then /at least/ the requested -coverage will be present in the central region, and /no more than/ -the requested coverage will be present in the tails. +The quantile function will by default return an integer result: +`quantile(dist, p)` is the smallest integer /k/ with `cdf(dist, k) >= p`, and +`quantile(complement(dist, q))` is the smallest integer /k/ with +`cdf(complement(dist, k)) <= q`. This is the `integer_round_up` policy, and +the definition R, SciPy, Julia and Mathematica use. This behaviour can be changed so that the quantile functions are rounded differently using @@ -126,17 +126,11 @@ lookup of the results gives an accuracy to a few epsilon. `boost::math::max_factorial::value` is 170 at double or long double precision. -For larger N such that `N < boost::math::prime(boost::math::max_prime)` -then only basic arithmetic is required for the calculation -and the accuracy is typically < 20 epsilon. This takes care of N -up to 104729. - -For `N > boost::math::prime(boost::math::max_prime)` then accuracy quickly -degrades, with 5 or 6 decimal digits being lost for N = 110000. - -In general for very large N, the user should expect to lose log[sub 10]N -decimal digits of precision during the calculation, with the results -becoming meaningless for N >= 10[super 15]. +For larger N the error is typically a few tens of epsilon wherever the PDF exceeds e[super -15] +(about 3 \u00d7 10[super -7]), however large N is, as long as products of the parameters +are exactly representable (below 2[super 53] at double precision). +Further into the tails the error is also a few tens of epsilon for N up to 104729; +beyond that it grows in proportion to |ln f(k)|, reaching around a thousand epsilon where f(k) ~ e[super -700]. [h4 Testing] @@ -202,13 +196,32 @@ calculate the result (indeed there is no shorter method involving only basic arithmetic once the exponents have been found), the method is therefore much more accurate than the alternatives. -For much larger N, we can calculate the PDF from the factorials using -either lgamma, or by directly combining lanczos approximations to avoid -calculating via logarithms. We use the latter method, as it is usually -1 or 2 decimal digits more accurate than computing via logarithms with -lgamma. However, in this area where N > 104729, the user should expect -to lose around log[sub 10]N decimal digits during the calculation in -the worst case. +Prime factorisation is, however, slow, and above the table of primes it is not available at all. +So for N above the table of factorials we use Loader's saddle-point method, as does R's `dhyper`: +the PDF is the ratio of binomial densities + +[expression f(k) = Binom(k; r, p) Binom(n - k; N - r, p) / Binom(n; N, p)] + +in which the powers of /p/ cancel for any /p/; with /p/ = /n/ / /N/ the denominator is at its mode. +Each binomial density is exp of a sum of Stirling-series remainders and deviance terms, all small near +the mode, so near the mode the accuracy does not depend on N. The means of the deviance terms are +ratios of products of the parameters, which we form without rounding, and we use the symmetry +f(k; r, n, N) = f(r - k; r, N - n, N) to keep /p/ <= 1/2, since for /p/ near 1 large powers of 1 - /p/ +would otherwise have to cancel. Because the result is an exponential, its relative error grows like +|ln f(k)| \u00d7 epsilon in the tails, so where the PDF is below e[super -15] and N is within the table +of primes we recompute it by prime factorisation. + +Loader, C. (2000), "Fast and Accurate Computation of Binomial Probabilities". + +For non-integral /k/ the PDF is the analytic continuation of the formula above, with +the binomial coefficients written in terms of gamma functions. It is computed from the +PDF at the integer /j/ = floor(/k/) and the shift /d/ = /k/ - /j/: + +[expression f(k) = f(j) \u00d7 [Gamma](j+1)/[Gamma](j+1+d) \u00d7 [Gamma](N-r-n+j+1)/[Gamma](N-r-n+j+1+d) \u00d7 [Gamma](r-k+1+d)/[Gamma](r-k+1) \u00d7 [Gamma](n-k+1+d)/[Gamma](n-k+1)] + +where each ratio is evaluated with __tgamma_delta_ratio, which is accurate for small /d/ and large arguments. +The result is accurate to a few epsilon beyond the conditioning of the function in /k/, +agrees with the integer values as /d/ \u2192 0, and is log-concave, so it is monotone on either side of the mode. The CDF and its complement is calculated by directly summing the PDFs. We start by deciding whether the CDF, or its complement, is likely to be diff --git a/doc/distributions/kolmogorov_smirnov.qbk b/doc/distributions/kolmogorov_smirnov.qbk index a748ece697..58e3c4a7fd 100644 --- a/doc/distributions/kolmogorov_smirnov.qbk +++ b/doc/distributions/kolmogorov_smirnov.qbk @@ -85,8 +85,11 @@ The CDF of the Kolmogorov-Smirnov distribution is implemented in terms of the fourth [link math_toolkit.jacobi_theta.jacobi_theta_overview Jacobi Theta function]; please refer to the accuracy ULP plots for that function. -The PDF is implemented separately, and the following ULP plot illustrates its -accuracy: +The PDF is implemented separately: each of its two series is evaluated from a +single exponential whose argument is corrected for the rounding of x[super 2]n +(and, for small x, of [pi][super 2]/8 and of the division), so that its error +does not grow with the size of the exponent. The following ULP plot illustrates +its accuracy: [graph kolmogorov_smirnov_pdf_ulp] @@ -95,6 +98,12 @@ above plot is representative for all values of /n/. Note that for present purposes, "accuracy" refers to deviations from the limiting approximation, rather than deviations from the exact distribution. +The quantile is accurate to a few ulps of /x/ over the whole range of /p/, +including small /n/ (where it exceeds unity) and probabilities down to the +smallest normalized number. The mode, median, skewness and kurtosis are +tabulated constants of the standardized distribution, accurate to 100 decimal +digits, and so are exact to within the scaling by /n/. + [h4 Implementation] In the following table, /n/ is the number of observations, /x/ is the random variable, @@ -102,23 +111,43 @@ In the following table, /n/ is the number of observations, /x/ is the random var [table [[Function][Implementation Notes]] -[[cdf][Using the relation: cdf = __jacobi_theta4tau(0, 2*x*x/[pi])]] +[[cdf][ +When 2*x*x*n <= [pi]: __jacobi_theta4tau(0, 2*x*x*n/[pi]) + +When 2*x*x*n > [pi]: 1 + __jacobi_theta4m1(0, q) with the nome q = exp(-2*x*x*n), whose exponent is formed with its rounding error compensated so that the theta function, which raises q to integer powers, does not amplify it]] [[pdf][Using a manual derivative of the CDF]] [[cdf complement][ When x*x*n == 0: 1 When 2*x*x*n <= [pi]: 1 - __jacobi_theta4tau(0, 2*x*x*n/[pi]) -When 2*x*x*n > [pi]: -__jacobi_theta4m1tau(0, 2*x*x*n/[pi])]] -[[quantile][Using a Newton-Raphson iteration]] -[[quantile from the complement][Using a Newton-Raphson iteration]] -[[mode][Using a run-time PDF maximizer]] +When 2*x*x*n > [pi]: -__jacobi_theta4m1(0, q), as for the cdf]] +[[quantile][ +Using a Newton-Raphson iteration on the logarithm of the CDF, or of its +complement, in a variable in which it is nearly linear: + +When p < 0.6: W = [pi][super 2]/(8x[super 2]n), where +ln cdf = ln(4/sqrt([pi])) + ln(W)/2 - W + ln(1 + e[super -8W] + e[super -24W] + ...) + +When p >= 0.6: V = x[super 2]n, where +ln(1 - cdf) = ln(2) - 2V + ln(1 - e[super -6V] + e[super -16V] - ...) + +The starting value inverts the first two terms of the expansion, which is +already exact to working precision in the tails.]] +[[quantile from the complement][As the quantile, with p = 1 - q]] +[[mode][0.735467907916571982... / sqrt(n), a tabulated root of the derivative of the PDF]] +[[median][0.827573555189907690... / sqrt(n), a tabulated root of cdf = 1/2]] [[mean][sqrt([pi]/2) * ln(2) / sqrt(n)]] [[variance][([pi][super 2]/12 - [pi]/2*ln[super 2](2))/n]] -[[skewness][(9/16*sqrt([pi]/2)*[zeta](3)/n[super 3/2] - 3 * mean * variance - mean[super 2] * variance) / (variance[super 3/2])]] -[[kurtosis][(7/720*[pi][super 4]/n[super 2] - 4 * mean * skewness * variance[super 3/2] - 6 * mean[super 2] * variance - mean[super 4]) / (variance[super 2])]] +[[skewness][0.860426137143668255..., a tabulated evaluation of (9/16*sqrt([pi]/2)*[zeta](3) - 3 * mean * variance - mean[super 3]) / (variance[super 3/2]) with n = 1]] +[[kurtosis][3 + 0.881618967910523670..., a tabulated evaluation of (7/720*[pi][super 4] - 4 * mean * skewness * variance[super 3/2] - 6 * mean[super 2] * variance - mean[super 4]) / (variance[super 2]) with n = 1]] ] +The tabulated constants are accurate to 100 decimal digits; for types with more +precision than that, the mode is refined by a Newton-Raphson iteration, the +median is computed from the quantile, and the skewness and kurtosis are +computed from the formulae above. + [endsect] [/section:kolmogorov_smirnov_dist Kolmogorov-Smirnov] [/ diff --git a/doc/distributions/non_members.qbk b/doc/distributions/non_members.qbk index 99728b8700..2c7145f714 100644 --- a/doc/distributions/non_members.qbk +++ b/doc/distributions/non_members.qbk @@ -423,6 +423,13 @@ In the Boost library, we /always/ use the natural logarithm to compute different This choice of log base for entropy is sometimes referred to as "entropy measured in nats". See [@https://doi.org/10.1109/TIT.1978.1055832 On the entropy of continuous probability distributions] for more information. +For discrete distributions, `entropy` returns the Shannon entropy -[sum] /p/[sub k] log(/p/[sub k]), also in nats. +The Poisson, binomial, negative binomial and hypergeometric distributions have no closed form for it: it is summed +from the ratios of successive probabilities, and for large variances by a coarse trapezoidal rule on the +probabilities' continuation through the gamma function, which equals the sum to full precision by the Poisson summation +formula. The skew normal, hyperexponential and Kolmogorov-Smirnov entropies have no closed form either and +use quadrature (a precomputed constant for Kolmogorov-Smirnov). The non-central distributions have no `entropy`. + [endsect] [/section:nmp Non-Member Properties] [/ non_members.qbk diff --git a/doc/distributions/von_mises.qbk b/doc/distributions/von_mises.qbk new file mode 100644 index 0000000000..065de46fe3 --- /dev/null +++ b/doc/distributions/von_mises.qbk @@ -0,0 +1,132 @@ +[/ + Copyright 2022 Matt Borland. + 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). +] + +[section:von_mises_dist Von Mises Distribution] + +``#include `` + + namespace boost{ namespace math{ + template + class von_mises_distribution; + + using von_mises = von_mises_distribution<>; + + template + class von_mises_distribution + { + public: + using value_type = RealType; + using policy_type = Policy; + + explicit von_mises_distribution(RealType mean = 0, RealType concentration = 1); + + RealType mean() const; + RealType concentration() const; + RealType location() const; + RealType scale() const; + }; + + }} // namespaces + +The [@https://en.wikipedia.org/wiki/Von_Mises_distribution von Mises distribution], +also known as the circular normal distribution, is a continuous probability distribution of an angle. +With mean [mu] and concentration [kappa] its probability density function is + +[expression f(x; [mu], [kappa]) = e[super [kappa] cos(x - [mu])] / (2[pi] I[sub 0]([kappa]))] + +for [mu] - [pi] <= x <= [mu] + [pi], where I[sub 0] is the modified Bessel function of the first kind. +With [kappa] = 0 it is the uniform distribution on the circle, +and as [kappa] grows it approaches a normal distribution with variance 1/[kappa]. + +[h4 Member Functions] + + explicit von_mises_distribution(RealType mean = 0, RealType concentration = 1); + +Constructs a von Mises distribution with mean /mean/ and concentration /concentration/. + +Requires that /mean/ is finite and that /concentration/ is finite and non-negative; +otherwise calls __domain_error. + + RealType mean() const; + RealType location() const; + +Return the /mean/ parameter of this distribution. + + RealType concentration() const; + RealType scale() const; + +Return the /concentration/ parameter of this distribution. + +[h4 Non-member Accessors] + +All the [link math_toolkit.dist_ref.nmp usual non-member accessor functions] +that are generic to all distributions are supported: __usual_accessors. + +The support is one turn centred on the mean, [mu] - [pi] <= x <= [mu] + [pi]. +Outside it the pdf is zero and the cdf is 0 or 1. + +The mean, median and mode are all [mu], and the skewness is zero. +The moments are those of circular statistics: +`variance` returns the circular variance 1 - I[sub 1]([kappa])/I[sub 0]([kappa]), +and `standard_deviation` returns the circular standard deviation +[sqrt](-2 ln(I[sub 1]([kappa])/I[sub 0]([kappa]))), +so the standard deviation is not the square root of the variance. +With zero concentration the circular standard deviation is infinite, and `standard_deviation` calls __overflow_error. + +[h4 Accuracy] + +The pdf and cdf have full relative accuracy in both tails, at any precision, +apart from the growth of error inherent in exp([kappa] cos(x - [mu])) when [kappa] is large. +The plots below compare `double` against `cpp_bin_float_50`, +with the condition number of the function drawn as an envelope; +they are generated by reporting/accuracy/von_mises_ulps.cpp. + +*PDF with concentration of 4* + +[$../images/von_mises_ulps_pdf_4d.svg] + +*PDF with concentration of 64* + +[$../images/von_mises_ulps_pdf_64d.svg] + +*CDF with concentration of 4* + +[$../images/von_mises_ulps_cdf_4d.svg] + +*CDF with concentration of 64* + +[$../images/von_mises_ulps_cdf_64d.svg] + +[h4 Implementation] + +The normalization e[super -[kappa]]I[sub 0]([kappa]) is computed from __cyl_bessel_i, +or from its asymptotic series when e[super [kappa]] would overflow. + +For x <= [mu] the cdf is + +[expression F(x) = e[super -2[kappa] sin[super 2](a/2)] / (2[pi] e[super -[kappa]]I[sub 0]([kappa])) [int][sub 0][super [pi]-a] e[super -2[kappa] sin(a + s/2) sin(s/2)] ds] + +with a = [mu] - x. The integrand is positive, so there is no cancellation in the left tail, +and it decays like e[super -[kappa] s sin(a)], so the range is cut where it falls below machine epsilon. +Up to double precision the integral is evaluated with a 30-point Gauss-Legendre rule, and beyond that with +[link math_toolkit.double_exponential.de_tanh_sinh tanh-sinh] quadrature. For x > [mu] the cdf is 1 - F(2[mu] - x), and the complement follows by symmetry. + +The circular variance is computed as e[super -[kappa]](I[sub 0]([kappa]) - I[sub 1]([kappa])) / e[super -[kappa]]I[sub 0]([kappa]), +never as a difference of the Bessel functions: +for moderate [kappa] both are integrals of positive functions over a full period, which the trapezoidal rule evaluates to geometric accuracy, +and for large [kappa] every term of their asymptotic series is positive. + +The quantile is found by Newton iteration on the cdf, starting from the normal approximation. + +[h4 References] + +* [@https://en.wikipedia.org/wiki/Von_Mises_distribution Wikipedia von Mises distribution] +* [@https://mathworld.wolfram.com/vonMisesDistribution.html Weisstein, Eric W. "von Mises Distribution." From MathWorld--A Wolfram Web Resource.] +* K. V. Mardia and P. E. Jupp, ['Directional Statistics], Wiley, 2000. + +[endsect] [/section:von_mises_dist Von Mises] diff --git a/doc/equations/harmonic_oscillator.svg b/doc/equations/harmonic_oscillator.svg new file mode 100644 index 0000000000..7320acb737 --- /dev/null +++ b/doc/equations/harmonic_oscillator.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/equations/polygamma3.mml b/doc/equations/polygamma3.mml index 3568763aa4..08430ae38a 100644 --- a/doc/equations/polygamma3.mml +++ b/doc/equations/polygamma3.mml @@ -86,7 +86,7 @@ π - n + x diff --git a/doc/equations/polygamma3.svg b/doc/equations/polygamma3.svg index 3e05baaefd..c635a04d29 100644 --- a/doc/equations/polygamma3.svg +++ b/doc/equations/polygamma3.svg @@ -1,2 +1,2 @@ -∂ncot(πx)∂xn=πnsinn+1(πx)∑k=0n−1Ck,ncosk(πn) \ No newline at end of file +∂ncot(πx)∂xn=πnsinn+1(πx)∑k=0n−1Ck,ncosk(πx) \ No newline at end of file diff --git a/doc/equations/polygamma7.mml b/doc/equations/polygamma7.mml index d3ea70c853..696abaa9b5 100644 --- a/doc/equations/polygamma7.mml +++ b/doc/equations/polygamma7.mml @@ -13,7 +13,7 @@ ∂ ∂ - x + θ @@ -73,7 +73,7 @@ cos - n + k + 1 @@ -88,7 +88,7 @@ cos - n + k − 1 diff --git a/doc/equations/polygamma7.svg b/doc/equations/polygamma7.svg index 2f83cc0b43..711404dd01 100644 --- a/doc/equations/polygamma7.svg +++ b/doc/equations/polygamma7.svg @@ -1,2 +1,2 @@ -∂∂xcosk(θ)sinn(θ)=1sinn+1(θ)((k−n)cosn+1(θ)−kcosn−1(θ)) \ No newline at end of file +∂∂θcosk(θ)sinn(θ)=1sinn+1(θ)((k−n)cosk+1(θ)−kcosk−1(θ)) \ No newline at end of file diff --git a/doc/fft/fft.qbk b/doc/fft/fft.qbk new file mode 100644 index 0000000000..18445f6918 --- /dev/null +++ b/doc/fft/fft.qbk @@ -0,0 +1,267 @@ +[/ + Copyright Nick Thompson 2026 + 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). +] + +[section:fft Fast Fourier Transform] + +[h4 Synopsis] + + #include + + namespace boost::math::tools { + + template + class fft + { + public: + using value_type = Complex; + using real_type = /* the real type of Complex */; + + explicit fft(std::size_t n); + + std::size_t size() const noexcept; + + // In place. + template + void transform(ContiguousContainer& v); + + template + void inverse_transform(ContiguousContainer& v); + + // Out of place: in is left unchanged. + template + void transform(InputContainer const& in, OutputContainer& out); + + template + void inverse_transform(InputContainer const& in, OutputContainer& out); + }; + + template + class real_fft + { + public: + using value_type = Complex; + using real_type = /* the real type of Complex */; + + explicit real_fft(std::size_t n); + + std::size_t size() const noexcept; + + // Reads n real values, overwrites the n/2 + 1 complex values of output. + template + void transform(RealContainer const& input, ContiguousComplexContainer& output); + }; + + } // namespaces + +[h4 Description] + +`fft` computes the discrete Fourier transform of a fixed length /n/, in place: + + using boost::math::tools::fft; + std::vector> v = ...; // v.size() == n + fft> f(v.size()); // builds the twiddle factors (and, for some n, Bluestein's chirp) + f.transform(v); // v now holds the transform + f.inverse_transform(v); // and now holds the original data again, up to rounding + +The constructor does all the setup, so construct the object once and reuse it for every transform of that length. +It also allocates all the workspace a transform needs, so after construction no transform allocates memory. + +The out-of-place overloads leave their input unchanged and write the transform to a second container of /n/ values, +which must not overlap the input: + + std::vector> X(v.size()); + f.transform(v, X); // X = F(v), v is unchanged + f.inverse_transform(X, v); // v = F^-1(X) + +Any length /n/ > 0 is accepted; /n/ = 0 throws a `std::domain_error`, as does a container whose size is not /n/. + +The template parameter is the complex type, which may be `std::complex`, `std::complex`, `std::complex`, +or a Boost.Multiprecision complex type such as `cpp_complex_50`, `cpp_complex_quad` or `mpc_complex_50`. +Its real type, `real_type`, is the type returned by its `real()` member: `T` for `std::complex`, and the component type for a multiprecision complex number. +(`std::complex` is not supported: the standard leaves `std::complex` of anything but `float`, `double` and `long double` unspecified; +use `cpp_complex_50` instead.) +For a multiprecision complex type, include its header first: ``, `` or ``. +Being generic in the floating point type is the main reason to use this rather than FFTW. + +The data is passed as a container of `Complex` with contiguous storage, a `data()` member and a size, such as `std::vector`, `std::array` or `std::span`. + +`real_fft` transforms /n/ real samples of type `real_type`. The caller supplies the output, which must hold exactly /n/\/2 + 1 values +(rounded down; otherwise a `std::domain_error` is thrown) and receives /X/[sub 0], ..., /X/[sub n/2]; the remaining coefficients are /X/[sub n-k] = conj(/X/[sub k]): + + using boost::math::tools::real_fft; + using boost::multiprecision::cpp_bin_float_50; + using boost::multiprecision::cpp_complex_50; + std::vector x = ...; // x.size() == n + std::vector X(x.size() / 2 + 1); + real_fft r(x.size()); + r.transform(x, X); + +The input may be any container with `operator[]` and a size. Both may be `std::array`s. +For even /n/ the input is packed into a complex FFT of length /n/\/2, so it is about twice as fast as a complex transform of the real data. +For odd /n/ it simply uses a complex FFT of length /n/. + +[h4 Conventions] + +The forward transform uses the negative sign in the exponent and is not normalised: + +[expression X[sub k] = [sum][sub j=0][super n-1] x[sub j] exp(-2[pi]/ijk/n)] + +The inverse uses the positive sign and divides by /n/: + +[expression x[sub j] = (1/n) [sum][sub k=0][super n-1] X[sub k] exp(2[pi]/ijk/n)] + +so that `inverse_transform` undoes `transform`. +This is the same convention as FFTW's `FFTW_FORWARD` (whose backward transform is not normalised), numpy's `fft`/`ifft`, and Matlab's `fft`/`ifft`. + +[h4 Thread safety] + +An `fft` or `real_fft` object holds its own workspace, which every transform writes to, so `transform` and `inverse_transform` are not `const` +and an object must not be used by two threads at once. As with an FFTW plan and its buffers, give each thread its own object; +different objects, even of the same length, are independent. + +[h4 Algorithms and complexity] + +Lengths whose prime factors are all at most 97 use a mixed-radix Cooley--Tukey FFT in Stockham's autosort form, +with radix-4 stages where possible and then one stage for each odd prime factor; it ping-pongs between the data and a scratch buffer of length /n/, +so no digit reversal is needed. Radices 2, 3, 4, 5, 7, 11 and 13 have dedicated butterflies; larger primes /p/ use a generic one, +which costs ['O(p)] per point. The cutoff of 97 is where Bluestein's algorithm (below) starts to win: +in double precision, for /n/ = /p/[times]2[super k] and /p/[times]1000, Bluestein is faster from /p/ = 97 to 127 on, depending on /n/, +and the mixed-radix FFT is also the more accurate up to about the same /p/. +Every other length uses Bluestein's algorithm, which rewrites the length-/n/ DFT as a convolution and evaluates it with two mixed-radix FFTs of length /m/ >= 2/n/ - 1, +where /m/ is the smallest 2[super a]3[super b]5[super c] >= 2/n/ - 1 (or the next power of two, if that is within 20%). +Lengths that are a smooth number times a large prime, such as 2[times]1009, are also done by Bluestein over the whole length: +applying Bluestein only to the large prime factor inside the mixed-radix decomposition would save at most about a factor of 2, at the cost of a second code path. +Both algorithms are ['O(n log n)] in time. +A mixed-radix `fft` stores at most 2/n/ complex twiddle factors and a workspace of /n/ more; +a Bluestein `fft` stores about 6/m/ complex numbers, including a workspace of 2/m/. A `real_fft` of odd length stores another /n/. +A Bluestein transform does two FFTs of length /m/ >= 2/n/, so it is roughly 5 to 10 times slower than a mixed-radix transform of similar length. +If you are free to choose /n/, choose one whose prime factors are 2, 3 and 5, preferably a power of two. + +[h4 Accuracy] + +Every twiddle factor exp(-2[pi]/ik/n) is computed directly, never by a recurrence: the angle is reduced to the first octant in integer arithmetic, +and the sine and cosine of what remains are computed by `sin_pi` and `cos_pi`, so each twiddle is accurate to an ulp or two. +With accurate twiddles, the FFT has normwise relative error ['O([epsilon][radic]log n)] for random data, +and the largest error in any single coefficient is ['O([epsilon] log n)] relative to the root mean square of the coefficients. + +The table below gives errors in units of the type's [epsilon], measured against a reference computed in 50 decimal digits +(an ['O(n[super 2])] DFT up to /n/ = 1031, our FFT in `cpp_complex_50` beyond that) for uniformly random complex data in the unit square +(the rows for /n/ = 17 and 101 are means over 20 random vectors, against a 100-digit DFT). +"rms" is ||/X/ - /X/[sub ref]||[sub 2] / ||/X/[sub ref]||[sub 2] and "max" is the largest |/X/[sub k] - /X/[sub ref,k]| divided by the root mean square of /X/[sub ref]. +FFTW 3 (double, `FFTW_ESTIMATE`) is given for comparison. +On Apple silicon, `long double` is `double`, and gives the same errors. + +[table:fft_accuracy Errors in units of epsilon +[[n][algorithm][float rms][float max][double rms][double max][FFTW double rms][FFTW double max]] +[[12] [mixed radix] [0.46][1.19][0.47][1.77][0.34][1.24]] +[[16] [mixed radix] [0.53][1.71][0.33][0.98][0.30][0.98]] +[[17] [mixed radix] [0.56][1.22][0.55][1.09][0.55][1.09]] +[[27] [mixed radix] [0.72][2.62][0.82][2.25][0.70][2.05]] +[[49] [mixed radix] [0.78][2.58][0.74][1.99][0.70][2.19]] +[[100] [mixed radix] [0.81][2.73][0.76][2.23][0.76][2.72]] +[[101] [Bluestein] [1.41][3.42][1.39][3.25][1.43][3.32]] +[[125] [mixed radix] [0.87][2.70][0.87][2.41][0.89][3.00]] +[[360] [mixed radix] [0.92][3.16][0.96][3.14][0.88][3.01]] +[[1000] [mixed radix] [1.02][4.38][1.00][3.24][1.06][3.59]] +[[1024] [mixed radix] [0.89][3.69][0.84][2.99][0.88][3.62]] +[[1031] [Bluestein] [1.85][5.21][2.14][6.60][2.09][8.55]] +[[2018] [Bluestein] [1.86][6.43][1.86][5.70][2.39][8.17]] +[[3072] [mixed radix] [0.98][4.51][1.00][3.51][0.98][3.63]] +[[3125] [mixed radix] [1.20][4.89][1.17][4.19][1.19][4.14]] +[[4096] [mixed radix] [0.98][3.11][0.93][3.09][1.00][3.82]] +[[4099] [Bluestein] [2.01][6.52][2.25][6.76][2.28][7.89]] +[[10000] [mixed radix] [1.21][4.44][1.18][4.35][1.15][4.49]] +[[12297] [Bluestein] [2.52][8.37][2.34][8.27][2.37][8.32]] +[[65536] [mixed radix] [1.15][4.08][1.12][4.38][1.22][5.54]] +[[65537] [Bluestein] [2.56][8.98][2.96][11.6][2.27][8.35]] +[[100000] [mixed radix] [1.38][6.03][1.34][5.73][1.40][5.99]] +[[117649] [mixed radix] [1.39][5.27][1.38][4.73][1.33][5.30]] +[[1048576] [mixed radix] [1.30][5.76][1.28][5.09][1.38][6.13]] +[[1000003] [Bluestein] [2.39][9.30][2.41][8.76][3.10][12.0]] +] + +For `cpp_complex_50` (against a 100 digit reference), the mixed-radix FFT gives rms errors of 0.4[epsilon] at /n/ = 12, 1.3[epsilon] at /n/ = 100, +1.7[epsilon] at /n/ = 1000 and 4096 and 1.8[epsilon] at /n/ = 3125, +and Bluestein gives 2.9[epsilon] at /n/ = 101, 3.5[epsilon] at /n/ = 2018 and 3.3[epsilon] at /n/ = 4099. + +The mixed-radix FFT is as accurate as FFTW. +Bluestein's algorithm loses a little: its rms and worst errors are about twice those of a mixed-radix FFT of similar length, +and they still grow like [radic]log /n/ and log /n/ respectively. +Prime factors up to 97 are transformed directly by a butterfly, which is as accurate as FFTW (at /n/ = 17 the errors are the same); +for larger primes, where this FFT uses Bluestein's algorithm, the two are comparable. +The round trip `inverse_transform(transform(x))` reproduces /x/ to about the same accuracy as the forward transform. + +These are errors for data whose coefficients all have similar size. +The error bounds are normwise, so coefficients much smaller than the rms coefficient have large relative errors; that is inherent in any FFT. + +[h4 Performance] + +On an Apple M1 Pro core with clang -O2, in double precision (google/benchmark, CPU time medians of 7), against FFTW 3.3.11 with `FFTW_ESTIMATE` plans. +`FFTW_MEASURE` plans are faster to execute, but making one runs and times many candidate transforms, which costs far more than the transforms it saves, +unless the same plan is reused very many times; `FFTW_ESTIMATE` is the planner that, like this FFT's constructor, does no measurement. +The FFTW is Homebrew's arm64 build, which is configured without NEON, so it runs FFTW's scalar codelets; +an FFTW built with SIMD would be noticeably faster than the figures below. +Each comparison is like for like: in place against an in-place plan, out of place against an out-of-place plan, and neither allocates during a transform. + +[table:fft_performance Time of one complex transform, in microseconds +[[n][in place][FFTW in place][ratio][out of place][FFTW out of place][ratio]] +[[16] [0.0284] [0.0174] [1.64] [0.0288] [0.0173] [1.66]] +[[64] [0.171] [0.144] [1.19] [0.16] [0.108] [1.48]] +[[256] [0.742] [0.69] [1.07] [0.732] [0.581] [1.26]] +[[1024] [3.63] [3.44] [1.06] [3.44] [3.06] [1.12]] +[[4096] [16.5] [17] [0.97] [16.7] [15.3] [1.09]] +[[16384] [82.9] [168] [0.49] [78.1] [157] [0.50]] +[[65536] [358] [427] [0.84] [361] [758] [0.48]] +[[262144] [1768] [3428] [0.52] [1740] [3340] [0.52]] +[[1048576] [8169] [15790] [0.52] [8256] [19936] [0.41]] +[[12] [0.0247] [0.0125] [1.98] [0.0253] [0.0117] [2.16]] +[[100] [0.306] [0.261] [1.17] [0.287] [0.215] [1.33]] +[[360] [1.37] [1.39] [0.99] [1.3] [1.09] [1.19]] +[[1000] [4.15] [4.77] [0.87] [3.98] [3.92] [1.02]] +[[10000] [51.9] [55.8] [0.93] [51.6] [48.9] [1.06]] +[[100000] [658] [811] [0.81] [662] [687] [0.96]] +[[786432 = 3[times]2[super 18]] [5916] [12280] [0.48] [6018] [14294] [0.42]] +[[531441 = 3[super 12]] [4793] [5082] [0.94] [4779] [5743] [0.83]] +[[390625 = 5[super 8]] [3058] [3695] [0.83] [3075] [3992] [0.77]] +[[117649 = 7[super 6]] [1265] [1806] [0.70] [1285] [806] [1.60]] +[[1001 = 7[times]11[times]13] [5.68] [5.37] [1.06] [5.53] [4.62] [1.20]] +[[6208 = 97[times]2[super 6]] [155] [92.8] [1.67] [155] [88.2] [1.75]] +[[6464 = 101[times]2[super 6]] [158] [101] [1.57] [157] [96.9] [1.62]] +[[2018 = 2[times]1009] [37.6] [50.6] [0.74] [37.6] [49.4] [0.76]] +[[4099 (prime)] [104] [110] [0.95] [104] [110] [0.94]] +[[65537 (prime)] [2118] [2172] [0.98] [2103] [2174] [0.97]] +[[1000003 (prime)] [42672] [52931] [0.81] [42672] [53199] [0.80]] +] + +[table:real_fft_performance Time of one real transform (/n/ real values to /n/\/2 + 1 complex values), in microseconds +[[n][`real_fft`][FFTW r2c][ratio]] +[[64] [0.134] [0.0479] [2.80]] +[[1024] [2.32] [1.45] [1.60]] +[[16384] [52.5] [39.1] [1.34]] +[[1048576] [4725] [7445] [0.63]] +[[1000] [2.4] [1.68] [1.43]] +[[1001 = 7[times]11[times]13] [6.06] [2.69] [2.25]] +[[100000] [381] [395] [0.96]] +[[2018 = 2[times]1009] [18.9] [24.7] [0.76]] +[[4099 (prime)] [105] [96.4] [1.09]] +[[65537 (prime)] [2148] [2332] [0.92]] +] + +For lengths below about 10[super 4] this FFT takes about the same time as `FFTW_ESTIMATE` up to about 1.5 times as long (up to 2 times for the shortest complex lengths, and 2.8 times for a real transform of length 64), +and for longer lengths it is usually faster, by up to a factor of 2. +Lengths with a large prime factor below the cutoff of 97, such as 97[times]2[super 6], take about 1.7 times as long as FFTW, +and a real transform of odd length, which is done as a complex transform of the same length, takes 2 to 3 times as long when the length is short. +The aim of this implementation is a generic `Real`, no external dependency, and accuracy; for the fastest double-precision transforms, use a SIMD build of FFTW. + +[h4 References] + +* J. W. Cooley and J. W. Tukey, ['An algorithm for the machine calculation of complex Fourier series], Math. Comp. 19 (1965), 297--301. +* L. I. Bluestein, ['A linear filtering approach to the computation of the discrete Fourier transform], IEEE Trans. Audio Electroacoust. 18 (1970), 451--455. +* N. J. Higham, ['Accuracy and Stability of Numerical Algorithms], 2nd ed., SIAM 2002, section 24.1. +* J. C. Schatzman, ['Accuracy of the discrete Fourier transform and the fast Fourier transform], SIAM J. Sci. Comput. 17 (1996), 1150--1166. + +[endsect] [/section:fft Fast Fourier Transform] diff --git a/doc/fp_utilities/fp_facets.qbk b/doc/fp_utilities/fp_facets.qbk index c4025a8242..7e37157e37 100644 --- a/doc/fp_utilities/fp_facets.qbk +++ b/doc/fp_utilities/fp_facets.qbk @@ -453,45 +453,6 @@ and crucially, [*require `scientific` format], not `fixed` or automatic (default s >> input_value; -[h4 Use with serialization archives] - -It is vital that the same locale is used -when an archive is saved and when it is loaded. -Otherwise, loading the archive may fail. -By default, archives are saved and loaded with a classic C locale -with a `boost::archive::codecvt_null` facet added. -Normally you do not have to worry about that. - -The constructors for the archive classes, as a side-effect, -imbue the stream with such a locale. -However, if you want to use the -facets `nonfinite_num_put` and `nonfinite_num_get` with archives, -then you have to manage the locale manually. -That is done by calling the archive constructor with the flag -`boost::archive::no_codecvt`, thereby ensuring that the archive constructor -will [*not imbue the stream with a new locale]. - -The following code shows how to use `nonfinite_num_put` with a `text_oarchive`. - - locale default_locale(locale::classic(), new boost::archive::codecvt_null); - locale my_locale(default_locale, new nonfinite_num_put); - - ofstream ofs("test.txt"); - ofs.imbue(my_locale); - - boost::archive::text_oarchive oa(ofs, no_codecvt); - - double x = numeric_limits::infinity(); - oa & x; - -The same method works with `nonfinite_num_get` and `text_iarchive`. - -If you use the `nonfinite_num_put` with `trap_infinity` -and/or `trap_nan` flag with a serialization archive, -then you must set the exception mask of the stream. -Serialization archives do not check the stream state. - - [h5 Other examples] [@../../example/nonfinite_facet_simple.cpp nonfinite_facet_simple.cpp] @@ -517,12 +478,6 @@ of various finite and nonfinite values. A simple example of trapping nonfinite output is at [@../../example/nonfinite_num_facet_trap.cpp nonfinite_num_facet_trap.cpp]. -A very basic example of using Boost.Archive is at -[@../../example/nonfinite_serialization_archives.cpp]. - -A full demonstration of serialization by Francois Mauger is at -[@../../example/nonfinite_num_facet_serialization.cpp] - [endsect] [/section:examples Examples] [section:portability Portability] diff --git a/doc/fp_utilities/ulps_plots.qbk b/doc/fp_utilities/ulps_plots.qbk index 3a6eca5bda..5152cfe733 100644 --- a/doc/fp_utilities/ulps_plots.qbk +++ b/doc/fp_utilities/ulps_plots.qbk @@ -16,11 +16,13 @@ template class ulps_plot { public: + // samples: 4/5 of them on a uniform grid in the plotted coordinate, the rest random probes (see below). + // With log_abscissas, the x axis is logarithmic and the grid uniform in log(x); requires 0 < a. ulps_plot(F hi_acc_impl, CoarseReal a, CoarseReal b, - size_t samples = 10000, bool perturb_abscissas = false, int random_seed = -1); + size_t samples = 1000, bool perturb_abscissas = false, int random_seed = -1, bool log_abscissas = false); // // Set a clip value to restrict the range of ULP's shown, values outside [-clip,clip] - // will be shown at the clip boundary and in a different color (red by default): + // will be shown at the clip boundary as crosses, in the color of their function by default: // ulps_plot& clip(PreciseReal clip); // @@ -44,11 +46,22 @@ // ulps_plot& font_color(std::string const & font_color); // - // Sets the color of points which are cropped, or set to an empty - // string to hide them completely (default is "red"): + // Sets one color for all points which are cropped, or set to an empty + // string to hide them completely (default is the color of each point's function): // ulps_plot& crop_color(std::string const & font_color); // + // Draw the function itself (the high-accuracy ordinates) in a second plot below the ulps plot, + // on the same x axis (off by default). With log_function, the y axis is logarithmic if f is positive everywhere sampled: + // + ulps_plot& show_function(bool show_function); + ulps_plot& log_function(bool log_function); + ulps_plot& function_color(std::string const & color); + // + // Counts of samples by outcome (ok, undefined, overflow/underflow handled, NaN or domain error, spurious overflow, mishandled), and the worst errors: + // + std::string summary() const; + // // Set's the color of points where one of the functions returned a NaN, // or set to an empty string to hide completely (the default): // @@ -68,6 +81,11 @@ template ulps_plot& add_fn(G g, std::string const & color = "steelblue"); // + // Encodes 8-bit RGB pixels (row-major, top row first) as a PNG; lodepng by default if requested (see below). + // With nullptr, or no encoder, the plot is pure SVG: + // + ulps_plot& png_encoder(std::function(std::vector const & rgb, size_t width, size_t height)> encoder); + // // Write to stream or file: // friend std::ostream& operator<<(std::ostream& fs, ulps_plot const & plot) @@ -127,12 +145,110 @@ For example: Note that the graph is written as an SVG. We use `firefox foo.svg` or `open -a Firefox foo.svg` to display these files. +Thousands of points and curve segments make a heavy SVG that some viewers draw slowly or mangle, +so the data (the points, the markers, the envelope and the curve of `show_function`) is drawn into PNG images embedded in the SVG, +antialiased by 4x4 supersampling at the plot's pixel size, while the axes and text stay vector. +Each color is a grayscale mask that the SVG fills with that color, so colors are given as CSS strings, as before, +and the masks are painted in the order the shapes were drawn. +To encode the images with [@https://github.com/lvandeve/lodepng lodepng], define `BOOST_MATH_USE_LODEPNG` (or include `lodepng.h` first) +before including the header, and link `lodepng.cpp`; or pass an encoder to `png_encoder`. +lodepng is not used just because `lodepng.h` happens to be on the include path, so that programs which don't link it still link. +Without an encoder, or with `png_encoder(nullptr)`, the whole plot is drawn as SVG elements. + +[h4 Sampling and the envelope] + +The abscissas are a uniform grid in the plotted coordinate (/x/, or log /x/ on a logarithmic axis), at the centres of equal cells spanning \[/a/, /b/\], +plus random probes, a quarter as many as the grid points, uniform in the same coordinate. +The grid gives most of the points and the envelope; the probes find errors between the grid points, +for example at the integers and half-integers that a grid can hit or miss and that often take their own code paths. + +The condition number |/x f'(x)/f(x)/| comes from finite differences of the reference values on the grid, +so it costs no evaluations of /f/ beyond the ones that are plotted. +/f'/ at each grid point is the derivative of the quartic through five neighbouring grid values: centred, or one-sided at the edges and next to undefined values. +Where it disagrees with the three-point estimate by more than a few percent of the scale that matters for the condition number, +/f/ is not smooth on the scale of the grid (a pole, a kink, a narrow feature), and /f'/ is computed instead from a central difference with a small step. +The same happens where the stencil is wider than |/x/|/2, since many functions vary on the scale of /x/ itself: +on a logarithmic axis with fewer than about 20 points per decade, and on a linear one within a few grid steps of 0. +At a probe, /f'/ is the cubic interpolant of the four nearest grid derivatives, divided by the exact /f/ at the probe. +At a simple zero of /f/, /f'/ is smooth and /f/ is not, so the condition number is computed exactly there: +interpolating the condition number itself would smear its narrow spike. +If the cubic through the grid values of /f/ doesn't predict /f/ at the probe, there is something between the grid points, and the probe gets a local difference too. There is a subtle issue about the "correct" value. Note that if the function evaluated in `PreciseReal` is not accurate, the plot is worthless. But just how accurate it needs to be is more difficult to determine. We recommend starting with at least `long double` to test `float` precision, and `boost::multiprecision::float128` to test `double` precision values. +[h4 Functions of two variables] + + #include + + namespace boost::math::tools { + + template + class ulps_heatmap { + public: + // Samples f(x, y) at the pixel centres of a width x height grid; a logarithmic axis needs a positive minimum. + // The reference is evaluated on threads (0 means all cores), so hi_acc_impl must be thread safe: + // There are also probe_density*width*height random probes, and each pixel shows the worst of its samples: + ulps_heatmap(F hi_acc_impl, CoarseReal x_min, CoarseReal x_max, CoarseReal y_min, CoarseReal y_max, + size_t width = 800, size_t height = 500, bool log_x = false, bool log_y = false, unsigned threads = 0, + double probe_density = 0.25); + // Add an implementation to test; each is drawn as a panel, side by side on the same scale: + template + ulps_heatmap& add_fn(G g, std::string const & label = ""); + // Saturate the color scale at clip. By default it is chosen from all panels' values: + // the maximum on a log scale, the 99th percentile on a linear one. + ulps_heatmap& clip(double clip); + ulps_heatmap& log_scale(bool log_scale); + // Maps [0, 1] to sRGB in [0, 1]^3; inferno by default: + ulps_heatmap& color_map(std::function(double)> color_map); + // Encodes 8-bit RGB pixels (row-major, top row first) as a PNG; lodepng by default if lodepng.h is found: + ulps_heatmap& png_encoder(std::function(std::vector const & rgb, size_t width, size_t height)> encoder); + ulps_heatmap& title(std::string const & title); + ulps_heatmap& x_label(std::string const & label); + ulps_heatmap& y_label(std::string const & label); + ulps_heatmap& background_color(std::string const & color); + ulps_heatmap& font_color(std::string const & color); + // Draw the reference function as a heatmap below each error panel, with its own colorbar (off by default). + // f is colored linearly from min(f) to max(f) (viridis); if f has both signs, symmetrically about zero with a dark-centered diverging map. + // If f > 0 everywhere and spans three or more decades, log10(f) is used; log_function forces or disables this: + ulps_heatmap& show_function(bool show_function); + // The caption of the function panels (default: the title): + ulps_heatmap& function_label(std::string const & label); + ulps_heatmap& log_function(bool log_function); + // Write max(1/2, |ulps|), or |ulps| over the envelope, as an SVG: + void write_ulps(std::string const & filename) const; + void write_ulps_envelope(std::string const & filename) const; + // For each panel, counts of points outside 1/2 ulp and outside the envelope, and the worst points: + std::string summary() const; + }; + + } // namespaces + +For a function of two variables, the condition number of evaluation is the sum of the condition numbers in each argument, +/|x f[sub x]/f| + |y f[sub y]/f|/, since both arguments are rounded. +`ulps_heatmap` evaluates the error at the pixel centres, and at random probes (a quarter as many by default, with a fixed seed), and writes two heatmaps. +Each pixel shows the worst of the samples in it. As in one dimension, the condition numbers come from finite differences on the grid, +along the rows and the columns, and at the probes from the bicubic interpolant of the gradient. +`write_ulps` shows max(½, |ulps|), which is ½ wherever the result is correctly rounded. +`write_ulps_envelope` divides |ulps| by the envelope max(½, cond/2) and shows max(1, ratio), so that anything brighter than the floor is error that rounding the arguments does not explain. +The implementation is evaluated everywhere, including where the true value is out of range, and each pixel is classified: +green means NaN or a domain error where the true value is a finite double; cyan means a spurious overflow +(`std::overflow_error` or an infinity where the true value is a finite double); both are bugs. +Dark gray means the result was handled correctly: the true value is undefined, or it overflows and the implementation raised `std::overflow_error` or returned an infinity, +or it underflows and the implementation returned zero or a subnormal. +An out-of-range true value for which the implementation returned an ordinary number (or NaN, or the wrong sign) is counted as the maximal error and shown at the top of the color scale. +`ulps_plot` draws the same classes as markers on the edges of the plot, with a legend, and `summary()` reports the counts. + +Calling `add_fn` more than once compares implementations: each gets a panel, and the panels share the axes and the color scale, +so that, for example, the code before and after a change can be compared directly. + +The heatmap is a PNG embedded in the SVG. +If `BOOST_MATH_USE_LODEPNG` is defined (or `lodepng.h` is included first), [@https://github.com/lvandeve/lodepng lodepng] encodes it (link `lodepng.cpp`); +otherwise, pass your own encoder to `png_encoder`, or the `write` functions throw `std::logic_error`. +An example is given [@../../reporting/accuracy/ligamma_ulps_heatmap.cpp here]. + [heading References] * Cleve Moler. ['Ulps Plots Reveal Math Function Accuracy], https://blogs.mathworks.com/cleve/2017/01/23/ulps-plots-reveal-math-function-accurary/ diff --git a/doc/graphs/jacobi_theta1_float.svg b/doc/graphs/jacobi_theta1_float.svg index e1b87a2c1f..b08f0a03ff 100644 --- a/doc/graphs/jacobi_theta1_float.svg +++ b/doc/graphs/jacobi_theta1_float.svg @@ -6,23 +6,27 @@ svg { background-color:black; } jacobi_theta1(x, 0.5) ULP plot at float precision - - --75 - --50 - --25 - -0 - -25 - -50 - -75 - -100 + + +-2.5 + +-2 + +-1.5 + +-1 + +-0.5 + +0.5 + +1 + +1.5 + +2 + +2.5 0.6283 @@ -43,2498 +47,2511 @@ svg { background-color:black; } 5.655 6.283 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/jacobi_theta1q_float.svg b/doc/graphs/jacobi_theta1q_float.svg index 63dcb428df..41402c7561 100644 --- a/doc/graphs/jacobi_theta1q_float.svg +++ b/doc/graphs/jacobi_theta1q_float.svg @@ -6,23 +6,23 @@ svg { background-color:black; } jacobi_theta1(5.0, q) ULP plot at float precision - + --87.28 +-14.75 --74.57 +-9.682 --61.85 +-4.611 --49.13 +0.4611 --36.42 +5.533 --23.7 +10.6 --10.98 +15.68 -1.733 +20.75 0.1 @@ -43,2486 +43,2509 @@ svg { background-color:black; } 0.9 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/jacobi_theta2_float.svg b/doc/graphs/jacobi_theta2_float.svg index 0d6f4b748f..ff27cf0d52 100644 --- a/doc/graphs/jacobi_theta2_float.svg +++ b/doc/graphs/jacobi_theta2_float.svg @@ -6,21 +6,21 @@ svg { background-color:black; } jacobi_theta2(x, 0.5) ULP plot at float precision - + --75 +-12.81 --50 +3.307 --25 +19.42 -0 +35.54 -25 +51.65 -50 +67.77 -75 +83.88 100 @@ -43,2495 +43,2511 @@ svg { background-color:black; } 5.655 6.283 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/jacobi_theta2q_float.svg b/doc/graphs/jacobi_theta2q_float.svg index 367d85e5b2..4d576aec55 100644 --- a/doc/graphs/jacobi_theta2q_float.svg +++ b/doc/graphs/jacobi_theta2q_float.svg @@ -6,23 +6,23 @@ svg { background-color:black; } jacobi_theta2(0.4, q) ULP plot at float precision - + --85.25 +-47.88 --70.49 +-40.64 --55.74 +-33.4 --40.99 +-26.16 --26.24 +-18.92 --11.48 +-11.68 -3.27 +-4.439 -18.02 +2.802 0.1 @@ -43,2508 +43,2509 @@ svg { background-color:black; } 0.9 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/jacobi_theta3_float.svg b/doc/graphs/jacobi_theta3_float.svg index 0490844afb..4587497615 100644 --- a/doc/graphs/jacobi_theta3_float.svg +++ b/doc/graphs/jacobi_theta3_float.svg @@ -43,2474 +43,2515 @@ svg { background-color:black; } 5.655 6.283 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/jacobi_theta3q_float.svg b/doc/graphs/jacobi_theta3q_float.svg index a9753c0ff2..cc1e145bf8 100644 --- a/doc/graphs/jacobi_theta3q_float.svg +++ b/doc/graphs/jacobi_theta3q_float.svg @@ -6,23 +6,23 @@ svg { background-color:black; } jacobi_theta3(0.4, q) ULP plot at float precision - + --87.17 +-28.75 --74.35 +-23.4 --61.52 +-18.06 --48.69 +-12.71 --35.87 +-7.364 --23.04 +-2.018 --10.21 +3.328 -2.613 +8.674 0.1 @@ -43,2508 +43,2509 @@ svg { background-color:black; } 0.9 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/jacobi_theta4_float.svg b/doc/graphs/jacobi_theta4_float.svg index 4b25f89eed..fb170075b0 100644 --- a/doc/graphs/jacobi_theta4_float.svg +++ b/doc/graphs/jacobi_theta4_float.svg @@ -43,2481 +43,2515 @@ svg { background-color:black; } 5.655 6.283 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/jacobi_theta4q_float.svg b/doc/graphs/jacobi_theta4q_float.svg index 2910ee71e3..3a2e759d1b 100644 --- a/doc/graphs/jacobi_theta4q_float.svg +++ b/doc/graphs/jacobi_theta4q_float.svg @@ -6,23 +6,23 @@ svg { background-color:black; } jacobi_theta4(5.0, q) ULP plot at float precision - + -10.99 +-7.544 -23.71 +-3.926 -36.42 +-0.307 -49.14 +3.312 -61.85 +6.93 -74.57 +10.55 -87.28 +14.17 -100 +17.79 0.1 @@ -43,2486 +43,2509 @@ svg { background-color:black; } 0.9 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/kolmogorov_smirnov_pdf_ulp.svg b/doc/graphs/kolmogorov_smirnov_pdf_ulp.svg index f1adef5dc2..3af522200c 100644 --- a/doc/graphs/kolmogorov_smirnov_pdf_ulp.svg +++ b/doc/graphs/kolmogorov_smirnov_pdf_ulp.svg @@ -6,23 +6,23 @@ svg { background-color:black; } Kolmogorov-Smirnov PDF (N=10) ULP plot at float precision - + --75 +-5.582 --50 +-4.109 --25 +-2.637 -0 +-1.164 -25 +0.3087 -50 +1.781 -75 +3.254 -100 +4.727 0.1 @@ -43,2509 +43,2511 @@ svg { background-color:black; } 0.9 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/pow1p_ulps_y1000.svg b/doc/graphs/pow1p_ulps_y1000.svg new file mode 100644 index 0000000000..dd96db14b5 --- /dev/null +++ b/doc/graphs/pow1p_ulps_y1000.svg @@ -0,0 +1,4043 @@ + + + +pow1p(x, 1000) vs pow(1 + x, 1000), double + + + + +-75 + +-50 + +-25 + +0 + +25 + +50 + +75 + +100 + +-0.3333 + +-0.1667 + +0 + +0.1667 + +0.3333 + +0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/graphs/pow1p_ulps_y2e20.svg b/doc/graphs/pow1p_ulps_y2e20.svg new file mode 100644 index 0000000000..b9e1fe8cca --- /dev/null +++ b/doc/graphs/pow1p_ulps_y2e20.svg @@ -0,0 +1,4041 @@ + + + +pow1p(x, 2^20) vs pow(1 + x, 2^20), double + + + + +-75 + +-50 + +-25 + +0 + +25 + +50 + +75 + +100 + +-6.667e-05 + +-3.333e-05 + +0 + +3.333e-05 + +6.667e-05 + +0.0001 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/html/dist.html b/doc/html/dist.html index ae3f75ed7c..9f77e4ae90 100644 --- a/doc/html/dist.html +++ b/doc/html/dist.html @@ -206,6 +206,8 @@
Triangular Distribution
Uniform Distribution
+
Von Mises + Distribution
Weibull Distribution
Distribution Algorithms
diff --git a/doc/html/indexes/s01.html b/doc/html/indexes/s01.html index 493ce79f1e..71339eb9b6 100644 --- a/doc/html/indexes/s01.html +++ b/doc/html/indexes/s01.html @@ -25,27 +25,52 @@

-Function Index

+Function Index

1 2 4 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _

1
-
2
@@ -89,6 +114,7 @@

abscissa

  • +

    integrals

    + +
  • +
  • integrate

  • @@ -2301,10 +2397,7 @@
  • kurtosis_excess

    - +
  • @@ -2485,6 +2578,14 @@
  • +

    lgamma_p

    + +
  • +
  • +

    lgamma_q

    + +
  • +
  • ljung_box

  • @@ -2542,6 +2643,7 @@
  • ln

    @@ -2561,8 +2663,9 @@
  • Logistic Distribution

  • Map-Airy Distribution

  • Normal (Gaussian) Distribution

  • -
  • Skew Normal Distribution

  • SαS Point5 Distribution

  • +
  • Skew Normal Distribution

  • +
  • Von Mises Distribution

  • @@ -2786,6 +2889,7 @@
  • Poisson Distribution

  • Uniform Distribution

  • Univariate Statistics

  • +
  • Von Mises Distribution

  • @@ -2815,7 +2919,10 @@
  • min

    - +
  • mode

    @@ -2859,6 +2966,10 @@
  • +

    namespace

    + +
  • +
  • nan

  • -

    one

    - -
  • -
  • operator

  • @@ -3163,6 +3272,13 @@
  • +

    place

    + +
  • +
  • plasma

  • @@ -3186,13 +3302,8 @@

    pow

    -
  • -

    powm1

    - -
  • +
  • pow1p

  • +
  • powm1

  • prime

  • @@ -3490,6 +3602,10 @@
  • +

    run

    + +
  • +
  • runs_above_and_below_median

  • @@ -3587,8 +3703,9 @@
  • Map-Airy Distribution

  • Normal (Gaussian) Distribution

  • Pareto Distribution

  • -
  • Skew Normal Distribution

  • SαS Point5 Distribution

  • +
  • Skew Normal Distribution

  • +
  • Von Mises Distribution

  • Weibull Distribution

  • @@ -3597,6 +3714,13 @@
  • +

    segment

    + +
  • +
  • semipolar

  • @@ -3657,6 +3781,7 @@
  • Additional Implementation Notes

  • Calculating confidence intervals on the mean with the Students-t distribution

  • Catmull-Rom Splines

  • +
  • Chatterjee Correlation (M nearest neighbours)

  • Differential Evolution

  • Estrin's method for polynomial evaluation

  • Graphing, Profiling, and Generating Test Data for Special Functions

  • @@ -3669,7 +3794,6 @@
    U @@ -4040,6 +4196,10 @@
  • +

    undefined

    + +
  • +
  • unif01

    +

    A B C D E F G H I K L M N O P Q R S T U V W

    A @@ -66,6 +66,10 @@
  • binomial_distribution

  • +

    block

    + +
  • +
  • box_constraints

  • @@ -124,10 +128,6 @@
  • chi_squared_distribution

  • -

    cma_es_parameters

    - -
  • -
  • combined_convergence_policy

  • @@ -168,14 +168,6 @@
  • -

    default_policy

    - -
  • -
  • -

    differential_evolution_parameters

    - -
  • -
  • discrete_lanczos_derivative

  • @@ -262,6 +254,10 @@
  • +

    gauss_hermite

    + +
  • +
  • gauss_kronrod

  • @@ -296,13 +292,6 @@
    -J -
    -
    -
    K
    @@ -487,10 +476,6 @@

    -Typedef Index

    +Typedef Index

    A B C D E F G H I K L M N P R S T U V W

    @@ -392,10 +392,10 @@
  • Quaternion Member Typedefs

  • Quaternion Specializations

  • Rayleigh Distribution

  • +
  • SαS Point5 Distribution

  • sinh_sinh

  • Skew Normal Distribution

  • Students t Distribution

  • -
  • SαS Point5 Distribution

  • tanh_sinh

  • Template Class octonion

  • Template Class quaternion

  • diff --git a/doc/html/indexes/s04.html b/doc/html/indexes/s04.html index 3323692dae..5607276b05 100644 --- a/doc/html/indexes/s04.html +++ b/doc/html/indexes/s04.html @@ -25,7 +25,7 @@

    -Macro Index

    +Macro Index

    B F

    @@ -92,7 +92,7 @@
  • BOOST_FPU_EXCEPTION_GUARD

  • @@ -122,7 +122,7 @@
  • BOOST_MATH_CONTROL_FP

    - +
  • BOOST_MATH_CUDA_ENABLED

    @@ -134,8 +134,10 @@
  • BOOST_MATH_DECLARE_DISTRIBUTIONS

  • @@ -143,8 +145,10 @@

    BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS

    @@ -153,12 +157,24 @@
  • +

    BOOST_MATH_DETAIL_NAMESPACE

    + +
  • +
  • +

    BOOST_MATH_DETAIL_NAMESPACE_BEGIN

    + +
  • +
  • +

    BOOST_MATH_DETAIL_NAMESPACE_END

    + +
  • +
  • BOOST_MATH_DIGITS10_POLICY

  • BOOST_MATH_DISABLE_FLOAT128

    - +
  • BOOST_MATH_DISCRETE_QUANTILE_POLICY

    @@ -175,10 +191,18 @@
  • Additional Implementation Notes

  • Changing the Policy Defaults

  • Error Handling Example

  • +
  • Support for C++20 Modules

  • Using Macros to Change the Policy Defaults

  • +

    BOOST_MATH_ENABLE_CUDA

    + +
  • +
  • BOOST_MATH_EVALUATION_ERROR_POLICY

  • @@ -187,6 +211,10 @@
  • +

    BOOST_MATH_EXPORT

    + +
  • +
  • BOOST_MATH_GPU_ENABLED

  • +

    BOOST_MATH_HAS_CUDA_PRIME_SIEVE

    + +
  • +
  • BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY

  • BOOST_MATH_INSTRUMENT_CODE

    - +
  • BOOST_MATH_INSTRUMENT_FPU

    - +
  • BOOST_MATH_INSTRUMENT_VARIABLE

    - +
  • BOOST_MATH_INT_TABLE_TYPE

  • BOOST_MATH_INT_VALUE_SUFFIX

    - +
  • BOOST_MATH_MAX_POLY_ORDER

  • @@ -312,28 +348,62 @@
  • +

    BOOST_MATH_NAMESPACE

    + +
  • +
  • +

    BOOST_MATH_NAMESPACE_BEGIN

    + +
  • +
  • +

    BOOST_MATH_NAMESPACE_COMPONENTS

    + +
  • +
  • +

    BOOST_MATH_NAMESPACE_END

    + +
  • +
  • +

    BOOST_MATH_NAMESPACE_LEVELS

    + +
  • +
  • BOOST_MATH_NO_ATOMIC_INT

  • BOOST_MATH_NO_DEDUCED_FUNCTION_POINTERS

  • BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS

  • BOOST_MATH_NO_REAL_CONCEPT_TESTS

  • @@ -355,7 +425,7 @@
  • BOOST_MATH_POLY_METHOD

  • @@ -370,7 +440,7 @@
  • BOOST_MATH_RATIONAL_METHOD

  • @@ -384,7 +454,7 @@
  • BOOST_MATH_SMALL_CONSTANT

    - +
  • BOOST_MATH_STANDALONE

    @@ -398,7 +468,7 @@
  • BOOST_MATH_STD_USING

    @@ -420,11 +490,14 @@
  • BOOST_MATH_USE_C99

    - +
  • BOOST_MATH_USE_FLOAT128

    - +
  • diff --git a/doc/html/indexes/s05.html b/doc/html/indexes/s05.html index db583578ad..c4834c83c1 100644 --- a/doc/html/indexes/s05.html +++ b/doc/html/indexes/s05.html @@ -24,7 +24,7 @@

    -Index

    +Index

    1 2 4 5 7 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _

    @@ -32,11 +32,35 @@
    @@ -770,6 +799,7 @@
  • Bernoulli Distribution

  • @@ -802,6 +832,7 @@
  • Bessel Functions of the First and Second Kinds

  • +

    BOOST_MATH_ENABLE_CUDA

    + +
  • +
  • BOOST_MATH_EVALUATION_ERROR_POLICY

  • @@ -1207,6 +1268,10 @@
  • +

    BOOST_MATH_EXPORT

    + +
  • +
  • BOOST_MATH_GPU_ENABLED

  • +

    BOOST_MATH_HAS_CUDA_PRIME_SIEVE

    + +
  • +
  • BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY

  • BOOST_MATH_INSTRUMENT_CODE

    - +
  • BOOST_MATH_INSTRUMENT_FPU

    - +
  • BOOST_MATH_INSTRUMENT_VARIABLE

    - +
  • BOOST_MATH_INT_TABLE_TYPE

  • BOOST_MATH_INT_VALUE_SUFFIX

    - +
  • BOOST_MATH_MAX_POLY_ORDER

  • @@ -1332,28 +1405,62 @@
  • +

    BOOST_MATH_NAMESPACE

    + +
  • +
  • +

    BOOST_MATH_NAMESPACE_BEGIN

    + +
  • +
  • +

    BOOST_MATH_NAMESPACE_COMPONENTS

    + +
  • +
  • +

    BOOST_MATH_NAMESPACE_END

    + +
  • +
  • +

    BOOST_MATH_NAMESPACE_LEVELS

    + +
  • +
  • BOOST_MATH_NO_ATOMIC_INT

  • BOOST_MATH_NO_DEDUCED_FUNCTION_POINTERS

  • BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS

  • BOOST_MATH_NO_REAL_CONCEPT_TESTS

  • @@ -1375,7 +1482,7 @@
  • BOOST_MATH_POLY_METHOD

  • @@ -1390,7 +1497,7 @@
  • BOOST_MATH_RATIONAL_METHOD

  • @@ -1404,7 +1511,7 @@
  • BOOST_MATH_SMALL_CONSTANT

    - +
  • BOOST_MATH_STANDALONE

    @@ -1418,7 +1525,7 @@
  • BOOST_MATH_STD_USING

    @@ -1440,11 +1547,14 @@
  • BOOST_MATH_USE_C99

    - +
  • BOOST_MATH_USE_FLOAT128

    - +
  • box_constraints

    @@ -1475,7 +1585,7 @@ @@ -1511,7 +1621,11 @@
  • +
  • +

    Chatterjee Correlation (M nearest neighbours)

    + +
  • chatterjee_correlation

  • +

    chatterjee_correlation_mnn

    + +
  • +
  • Chebyshev Polynomials

  • @@ -3231,8 +3390,13 @@
  • -

    default_policy

    - +

    decltype

    +
  • defined

    @@ -3297,20 +3461,39 @@
  • +

    Derived macros

    + +
  • +
  • +

    deviation

    + +
  • +
  • Differential Evolution

  • differential_evolution

  • -

    differential_evolution_parameters

    - -
  • -
  • differentiation

  • @@ -3456,6 +3640,7 @@
  • +

    integrals

    + +
  • +
  • integrate

  • Inverse Gaussian (or Inverse Normal) Distribution

  • K @@ -6607,6 +6867,7 @@
  • Jacobi Elliptic SN, CN and DN

  • Known Issues, and TODO List

  • Quintic Hermite interpolation

  • +
  • Van den Bos Unit-Square Quadrature

  • @@ -6623,6 +6884,8 @@
  • accuracy

  • by

  • differentiation

  • +
  • F

  • +
  • integrals

  • integration

  • interpolation

  • J

  • @@ -6645,9 +6908,9 @@
  • G

  • kolmogorov_smirnov

  • kolmogorov_smirnov_distribution

  • +
  • ln

  • n

  • policy_type

  • -
  • skewness

  • value_type

  • @@ -6665,10 +6928,7 @@
  • kurtosis_excess

    - +
  • @@ -6776,6 +7036,7 @@ @@ -6854,6 +7117,7 @@
  • O

  • operator

  • performance

  • +
  • the

  • v

  • @@ -6930,6 +7194,7 @@
  • Legendre-Stieltjes Polynomials

  • +

    lgamma_p

    + +
  • +
  • +

    lgamma_q

    + +
  • +
  • Library Comparison with GNU C++ version 9.2.1 20191008 on linux

  • @@ -7273,7 +7548,6 @@
  • policy_type

  • scale

  • value_type

  • -
  • variance

  • logistic_distribution

  • @@ -7459,9 +7733,9 @@

    Mathematical Constants

  • @@ -7492,6 +7766,7 @@
  • Poisson Distribution

  • Uniform Distribution

  • Univariate Statistics

  • +
  • Von Mises Distribution

  • @@ -7521,7 +7796,10 @@
  • min

    - +
  • Minimax Approximations and the Remez Algorithm

    @@ -7588,6 +7866,7 @@
  • converge

  • cyl_bessel_i

  • cyl_bessel_k

  • +
  • fail

  • O

  • small

  • v

  • @@ -7629,6 +7908,7 @@
  • Comparison of Nth-root Finding Algorithms

  • Computing the Fifth Root

  • Conceptual Requirements for Real Number Types

  • +
  • Configurable Namespace

  • Cost of High-Precision Non-built-in Floating-point

  • Credits and Acknowledgements

  • Daubechies Wavelets and Scaling Functions

  • @@ -7659,6 +7939,7 @@
  • Norms

  • Overview

  • Overview of the Jacobi Elliptic Functions

  • +
  • Prime Sieve

  • Reciprocal square root

  • Reverse Mode Automatic Differentiation

  • Root-finding using Boost.Multiprecision

  • @@ -7713,8 +7994,15 @@
  • +

    namespace

    + +
  • +
  • Namespaces

    - +
  • nan

    @@ -7918,7 +8206,6 @@
  • Noncentral Beta Distribution

  • @@ -8204,18 +8496,11 @@
  • Octonion Value Operations

  • Quaternion Value Operations

  • Spherical Harmonics

  • +
  • Symplectic Integration

  • tanh_sinh

  • -

    one

    - -
  • -
  • ooura_fourier_cos

  • @@ -8354,6 +8639,7 @@
  • Roots of Cubic Polynomials

  • The Incomplete Beta Function Inverses

  • The Remez Method

  • +
  • Van den Bos Unit-Square Quadrature

  • @@ -8411,7 +8697,7 @@
  • Bezier Polynomials

  • Bilinear Uniform Interpolation

  • Boost.Math Frequently Asked Questions (FAQs)

  • -
  • Boost.Math Tuning

  • +
  • Boost.Math Tuning

  • C99 and C++ TR1 C-style Functions

  • C99 and TR1 C Functions Overview

  • Cardinal B-splines

  • @@ -8454,6 +8740,7 @@
  • Performance Tuning Macros

  • Polynomial and Rational Function Evaluation

  • Polynomials

  • +
  • Prime Sieve

  • Quintic Hermite interpolation

  • Random Search

  • Reciprocal square root

  • @@ -8505,6 +8792,13 @@
  • +

    place

    + +
  • +
  • plasma

  • @@ -8541,7 +8835,6 @@
  • Policy Class Reference

    @@ -8612,19 +8905,31 @@
  • Polynomial Method Comparison with Clang version 9.0.0 (tags/RELEASE_900/final) on linux

    - +
  • Polynomial Method Comparison with GNU C++ version 9.2.1 20191008 on linux

    - +
  • Polynomial Method Comparison with Intel C++ C++0x mode version 1910 on linux

    - +
  • Polynomial Method Comparison with Microsoft Visual C++ version 14.2 on Windows x64

    - +
  • Polynomials

    @@ -8654,10 +8959,17 @@
  • +

    pow1p

    + +
  • +
  • powm1

  • @@ -8700,6 +9012,21 @@
  • +

    Prime Sieve

    + +
  • +
  • promote_args

  • @@ -8839,6 +9172,7 @@
  • norm

  • of

  • sup

  • +
  • the

  • unreal

  • @@ -8892,7 +9226,6 @@
  • @@ -8904,10 +9237,6 @@
  • random_search

  • -

    random_search_parameters

    - -
  • -
  • random_uniform_initializer_rvar

  • @@ -8923,19 +9252,31 @@
  • Rational Method Comparison with Clang version 9.0.0 (tags/RELEASE_900/final) on linux

    - +
  • Rational Method Comparison with GNU C++ version 9.2.1 20191008 on linux

    - +
  • Rational Method Comparison with Intel C++ C++0x mode version 1910 on linux

    - +
  • Rational Method Comparison with Microsoft Visual C++ version 14.2 on Windows x64

    - +
  • Ratios of Gamma Functions

    @@ -9048,7 +9389,6 @@
  • constants

  • expression

  • interpolation

  • -
  • one

  • P

  • R

  • @@ -9119,6 +9459,7 @@
  • adjoint

  • autodiff

  • backward

  • +
  • block

  • BOOST_MATH_BUFFER_SIZE

  • BOOST_MATH_REVERSE_MODE_ET_ON

  • constants

  • @@ -9142,6 +9483,7 @@
  • rewind_to_checkpoint_at

  • rewind_to_last_checkpoint

  • rvar

  • +
  • types

  • x

  • zero_grad

  • @@ -9287,6 +9629,7 @@
  • Examples of Root-Finding (with and without derivatives)

  • Finding the Cubed Root With and Without Derivatives

  • Finding Zeros of Bessel Functions of the First and Second Kinds

  • +
  • Root Finding With Derivatives: Newton-Raphson, Halley & Schroeder

  • @@ -9299,6 +9642,7 @@
  • halley_iterate

  • newton_raphson_iterate

  • performance

  • +
  • root

  • schroder_iterate

  • @@ -9330,6 +9674,7 @@
  • cpp_bin_float

  • cpp_dec_float

  • multiprecision

  • +
  • types

  • @@ -9391,6 +9736,10 @@
  • +

    run

    + +
  • +
  • Runs tests

    • median

    • @@ -9422,6 +9771,21 @@
  • @@ -9516,6 +9881,13 @@
  • +

    segment

    + +
  • +
  • semipolar

  • @@ -9606,8 +9979,8 @@
  • Landau Distribution

  • Map-Airy Distribution

  • Pareto Distribution

  • -
  • Skew Normal Distribution

  • SαS Point5 Distribution

  • +
  • Skew Normal Distribution

  • Weibull Distribution

  • @@ -9618,18 +9991,19 @@
  • Sign Manipulation Functions

  • Signal Statistics

  • T
    U @@ -10534,6 +10968,10 @@
  • +

    undefined

    + +
  • +
  • unif01

  • +

    use

    + +
  • +
  • Use in non-template code

  • +

    Van den Bos Unit-Square Quadrature

    + +
  • +
  • variance

  • +

    Vector- and matrix-valued integrands

    + +
  • +
  • Vector-valued Barycentric Rational Interpolation

    W @@ -10975,6 +11453,7 @@
  • weights

    @@ -10987,6 +11466,7 @@
  • operator

  • performance

  • prime

  • +
  • the

  • v

  • whittaker_shannon

  • @@ -11017,7 +11497,6 @@
  • Barycentric Rational Interpolation

  • Cyclic Hankel Functions

  • Distribution Construction Examples

  • -
  • Finding Zeros of Bessel Functions of the First and Second Kinds

  • Noncentral T Distribution

  • Overview

  • Reverse Mode Automatic Differentiation

  • @@ -11051,7 +11530,6 @@
  • zero

      -
    • Bernoulli Numbers

    • Binomial Coin-Flipping Example

    • Examples Where Root Finding Goes Wrong

    • Finding the Cubed Root With and Without Derivatives

    • diff --git a/doc/html/math_toolkit/autodiff0.html b/doc/html/math_toolkit/autodiff0.html index b30c698609..f64841fd7c 100644 --- a/doc/html/math_toolkit/autodiff0.html +++ b/doc/html/math_toolkit/autodiff0.html @@ -5654,7 +5654,7 @@

      - False + True

      diff --git a/doc/html/math_toolkit/ccmath.html b/doc/html/math_toolkit/ccmath.html index f608aeac4a..257bf5c07e 100644 --- a/doc/html/math_toolkit/ccmath.html +++ b/doc/html/math_toolkit/ccmath.html @@ -181,6 +181,12 @@

      template <typename Arithmetic1, typename Arithmetic2> inline constexpr Promoted hypot(Arithmetic1 x, Arithmetic2 y) noexcept + template <typename Real> + inline constexpr Real hypot(Real x, Real y, Real z) noexcept + + template <typename Arithmetic1, typename Arithmetic2, typename Arithmetic3> + inline constexpr Promoted hypot(Arithmetic1 x, Arithmetic2 y, Arithmetic3 z) noexcept + template <typename Real> inline constexpr Real fdim(Real x, Real y) noexcept diff --git a/doc/html/math_toolkit/chatterjee_correlation.html b/doc/html/math_toolkit/chatterjee_correlation.html index 135a4f47de..46bb47e86b 100644 --- a/doc/html/math_toolkit/chatterjee_correlation.html +++ b/doc/html/math_toolkit/chatterjee_correlation.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@
      -PrevUpHomeNext +PrevUpHomeNext

      @@ -126,7 +126,7 @@


      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/math_toolkit/chatterjee_correlation_mnn.html b/doc/html/math_toolkit/chatterjee_correlation_mnn.html new file mode 100644 index 0000000000..ce2fb35e9a --- /dev/null +++ b/doc/html/math_toolkit/chatterjee_correlation_mnn.html @@ -0,0 +1,149 @@ + + + +Chatterjee Correlation (M nearest neighbours) + + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +

      + + Synopsis +

      +
      #include <boost/math/statistics/chatterjee_correlation.hpp>
      +
      +namespace boost::math::statistics {
      +
      +    C++17:
      +    template <typename ExecutionPolicy, typename Container>
      +    auto chatterjee_correlation_mnn(ExecutionPolicy&& exec, const Container& u, const Container& v, std::size_t M);
      +
      +    C++11:
      +    template <typename Container>
      +    auto chatterjee_correlation_mnn(const Container& u, const Container& v, std::size_t M);
      +}
      +
      +

      + + Description +

      +

      + chatterjee_correlation_mnn + computes the revised Chatterjee rank correlation of Lin and Han (2021), which + generalises Chatterjee's coefficient by incorporating the M + right nearest neighbours of each point rather than only the single right neighbour. + The statistic still consistently estimates the same measure of dependence (between + 0 and 1; zero if and only if X and Y are independent, unity if and only if + Y is a measurable function of X), but its use of additional neighbours boosts + the power of the associated independence test. +

      +

      + The original coefficient chatterjee_correlation + has a statistical detection boundary of n-1/4 for testing independence, which + is substantially weaker than the parametric n-1/2 rate. By letting M grow with the sample size (with M/n -> + 0), the revised statistic can approach near-parametric efficiency. +

      +

      + Let X and Y be random variables, where Y is not constant, and let (X_i, Y_i) + be samples sorted so that X_(0) < X_(1) < ... < X_(n-1). Writing R_i + for the rank of Y_i and j_m(i) for the index of the m-th right nearest neighbour + of X_i, the statistic is +

      +
      xi_{n,M} = -2 + 6 * sum_i sum_{m=1}^{M} min(R_i, R_{j_m(i)}) / ((n + 1) * (n*M + M*(M + 1) / 4))
      +
      +

      + The complexity is O(n log n + n M). For M + of order O(1) or O(poly-log n) this is nearly linear; as M + approaches n it tends to O(n2). +

      +

      + An example is given below: +

      +
      std::vector<double> X{1,2,3,4,5};
      +std::vector<double> Y{1,2,3,4,5};
      +using boost::math::statistics::chatterjee_correlation_mnn;
      +std::size_t M = 2;
      +double coeff = chatterjee_correlation_mnn(X, Y, M);
      +
      +

      + Nota bene: If the input is an integer type the output + will be a double precision type. +

      +

      + + Choice + of M +

      +

      + The asymptotic null variance of the statistic is minimised when M is of order sqrt(n), which is a reasonable + default for users who want improved power without the quadratic cost of large + M. Pushing M + closer to n increases the power + of the independence test against smooth alternatives at the cost of additional + computation. The choice is left to the caller; M + must satisfy 1 <= M <= n. +

      +

      + Nota bene: Even at M + = 1 this statistic is not identical to chatterjee_correlation: + it uses min(R_i, R_j) in place of |R_i - R_j| and a different normalisation, + so the two agree only up to a term of order 1/n. Use chatterjee_correlation + when the original coefficient is required. +

      +

      + + Invariants +

      +

      + The function expects at least two samples, a non-constant vector Y, the same + number of X's as Y's, and 1 <= M <= n. If Y is constant, the result is + a quiet NaN. The data set must be sorted by X values. If there are ties in + the values of X, then the statistic is random due to the random breaking of + ties. +

      +

      + + References +

      +
      • + Lin, Zhexiao, and Fang Han. "On boosting the power of Chatterjee's + rank correlation." Biometrika 110.2 (2023): 283-299. arXiv:2108.06828. +
      +
      + +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/math_toolkit/compilers_overview.html b/doc/html/math_toolkit/compilers_overview.html index 25dc38af02..32eaa4bd27 100644 --- a/doc/html/math_toolkit/compilers_overview.html +++ b/doc/html/math_toolkit/compilers_overview.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@
      -PrevUpHomeNext +PrevUpHomeNext

      @@ -34,7 +34,7 @@ to achieve this on all systems.

      -

      Table 1.9. Supported/Tested Compilers

      +

      Table 1.11. Supported/Tested Compilers

      @@ -602,7 +602,7 @@

      -

      Table 1.10. Unsupported Compilers

      +

      Table 1.12. Unsupported Compilers

      @@ -676,7 +676,7 @@
      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/math_toolkit/config_macros.html b/doc/html/math_toolkit/config_macros.html index bc52bf0e6f..3950fc41a9 100644 --- a/doc/html/math_toolkit/config_macros.html +++ b/doc/html/math_toolkit/config_macros.html @@ -32,14 +32,16 @@

      In normal use, only policy configuration macros are likely to be used. See - policy reference. + policy reference. Libraries that + embed their own copy of Boost.Math may also want BOOST_MATH_NAMESPACE_COMPONENTS, + see Configurable Namespace.

      For reference, information on Boost.Math macros used internally are described briefly below.

      -

      Table 1.11. Boost.Math Macros

      +

      Table 1.13. Boost.Math Macros

      @@ -59,6 +61,21 @@ + + + +
      +

      + BOOST_MATH_NAMESPACE_COMPONENTS +

      +
      +

      + Relocates the whole library from boost::math + into a namespace of your choosing, for example my_lib, math + for my_lib::math. See Configurable + Namespace. +

      +

      BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS @@ -280,7 +297,7 @@


      -

      Table 1.12. Boost.Math Tuning

      +

      Table 1.14. Boost.Math Tuning

      diff --git a/doc/html/math_toolkit/configurable_namespace.html b/doc/html/math_toolkit/configurable_namespace.html new file mode 100644 index 0000000000..be906c699c --- /dev/null +++ b/doc/html/math_toolkit/configurable_namespace.html @@ -0,0 +1,389 @@ + + + +Configurable Namespace + + + + + + + + + +
      + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +
      + + Overview +
      +

      + By default every entity in Boost.Math lives in namespace boost::math. Defining + the macro BOOST_MATH_NAMESPACE_COMPONENTS + relocates the whole library into a namespace of your choosing. This is intended + for libraries that embed their own copy of Boost.Math (typically in standalone + mode): moving the copy out of boost::math means + it can never collide with a different version of Boost.Math that the end user + also compiles or links against, whether as duplicate symbols in a static library + or as an ODR violation. +

      +
      #define BOOST_MATH_NAMESPACE_COMPONENTS my_lib, math
      +#include <boost/math/special_functions/gamma.hpp>
      +
      +int main()
      +{
      +    double x = my_lib::math::tgamma(5.0);            // 24
      +    double y = BOOST_MATH_NAMESPACE::tgamma(5.0);    // the same function
      +    return x == y ? 0 : 1;
      +}
      +
      +

      + Nothing changes unless the macro is defined: the default configuration produces + exactly the same code as before. +

      +
      + + Configuring + the namespace +
      +

      + BOOST_MATH_NAMESPACE_COMPONENTS + is a comma separated list of between one and five identifiers, outermost first. + The default is boost, + math. Some examples: +

      +
      +

      Table 1.1. Example configurations

      +
      ++++ + + + + + + + + + + + + + + + + + + + + + + +
      +

      + BOOST_MATH_NAMESPACE_COMPONENTS +

      +
      +

      + Library namespace +

      +
      +

      + boost, + math (default) +

      +
      +

      + ::boost::math +

      +
      +

      + my_lib, + math +

      +
      +

      + ::my_lib::math +

      +
      +

      + _Math +

      +
      +

      + ::_Math +

      +
      +

      + my_company, + third_party, + math +

      +
      +

      + ::my_company::third_party::math +

      +
      +
      +

      + The namespace is given as a list of components rather than as a qualified name + such as my_lib::math, because the preprocessor cannot split + a qualified name into its parts, and C++14 (the oldest standard the library + supports) has no nested namespace definitions. +

      +

      + The macro must be defined before the first Boost.Math header is included. In + a project with more than one translation unit, set it in the build system so + that every translation unit sees the same value: +

      +
      g++ -DBOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math ...
      +cl /DBOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math ...
      +
      +# CMake
      +target_compile_definitions(my_target PRIVATE BOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math)
      +
      +
      + + Macros +
      +

      + <boost/math/tools/config.hpp> + derives the following macros from BOOST_MATH_NAMESPACE_COMPONENTS. + They are always defined, so code that uses them works with any configuration, + including the default one. Defining any of them yourself is a compile time + error. +

      +
      +

      Table 1.2. Derived macros

      +
      +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +

      + Macro +

      +
      +

      + Default expansion +

      +
      +

      + Description +

      +
      +

      + BOOST_MATH_NAMESPACE +

      +
      +

      + boost::math +

      +
      +

      + The qualified name of the library namespace, for example ::BOOST_MATH_NAMESPACE::tgamma(x) or namespace + bm = + BOOST_MATH_NAMESPACE;. +

      +
      +

      + BOOST_MATH_NAMESPACE_BEGIN +

      +
      +

      + namespace boost + { namespace + math { +

      +
      +

      + Opens the library namespace. Use it only at global namespace scope. +

      +
      +

      + BOOST_MATH_NAMESPACE_END +

      +
      +

      + }} +

      +
      +

      + Closes the namespace opened by BOOST_MATH_NAMESPACE_BEGIN. +

      +
      +

      + BOOST_MATH_NAMESPACE_LEVELS +

      +
      +

      + 2 +

      +
      +

      + The number of components, as an integer literal that can be tested + with #if. +

      +
      +

      + BOOST_MATH_DETAIL_NAMESPACE +

      +
      +

      + boost::math_detail +

      +
      +

      + A sibling of the library namespace, formed by appending _detail to the innermost component, + which holds the few internal helpers that must not be enclosed by + the library namespace. BOOST_MATH_DETAIL_NAMESPACE_BEGIN + and BOOST_MATH_DETAIL_NAMESPACE_END + open and close it. User code should never need these. +

      +
      +
      +
      + + Code + that extends the library +
      +

      + Anything you declare inside the library namespace must follow it when it moves. + The usual case is the user_error + policy, whose handlers you define inside the policies namespace. Writing + them with the macros keeps them correct for every configuration: +

      +
      BOOST_MATH_NAMESPACE_BEGIN
      +namespace policies {
      +
      +template <class T>
      +T user_domain_error(const char* function, const char* message, const T& val)
      +{
      +    // ...
      +}
      +
      +} // namespace policies
      +BOOST_MATH_NAMESPACE_END
      +
      +

      + The same applies to anything else you previously wrote in namespace + boost { + namespace math + {, such as specializations of library + templates. The convenience macros BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS + and BOOST_MATH_DECLARE_DISTRIBUTIONS + work unchanged in any configuration. +

      +
      + + Limitations +
      +
        +
      • + Only C++ names move. Header paths, include guards and macro names stay + the same, so a single translation unit can contain only one configuration + of the library. Different translation units, or different libraries linked + into the same program, may each use a different namespace: that is the + purpose of the feature. +
      • +
      • + Every translation unit that shares one copy of the library must use the + same BOOST_MATH_NAMESPACE_COMPONENTS. +
      • +
      • + Libraries that call Boost.Math by its default name are not affected by + the macro and will not find a relocated copy. This includes other Boost + libraries that use Boost.Math internally, such as Boost.Multiprecision, + so relocation is intended for a self contained copy of Boost.Math. +
      • +
      • + The messages carried by exceptions and error handlers still name the function + as boost::math::.... +
      • +
      • + The fixed width floating point typedefs of <boost/cstdfloat.hpp> (boost::float64_t + and friends) are not part of boost::math + and stay in namespace boost. +
      • +
      • + The C++20 module is built + and tested with the default namespace only. +
      • +
      +
      + + Testing +
      +

      + The library's continuous integration builds every public header, plus a runtime + test, with BOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math. It checks that nothing is left in + boost::math and that no symbol in the resulting + binary is in namespace boost. + See libs/math/test/cmake_namespace_test. +

      +
      + +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/math_toolkit/conventions.html b/doc/html/math_toolkit/conventions.html index 13d9465baa..417f3bf502 100644 --- a/doc/html/math_toolkit/conventions.html +++ b/doc/html/math_toolkit/conventions.html @@ -28,7 +28,7 @@ Document Conventions

      - +

      This documentation aims to use of the following naming and formatting conventions. diff --git a/doc/html/math_toolkit/cxx20_modules.html b/doc/html/math_toolkit/cxx20_modules.html new file mode 100644 index 0000000000..01d1c3aba2 --- /dev/null +++ b/doc/html/math_toolkit/cxx20_modules.html @@ -0,0 +1,154 @@ + + + +Support for C++20 Modules + + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +


      +
      +PrevUpHomeNext +
      +
      + +
      + + C++20 + Modules Support +
      +

      + Boost.Math can be consumed as the named module boost.math. The + module covers the public interface of the library: special functions, statistical + distributions, constants, policies, ccmath, the public tools (root finding, + minima, polynomials, rational and series evaluation, norms, condition numbers + and friends), quadrature, the modern interpolators, statistics, optimization, + differentiation (autodiff, finite differences and Lanczos smoothing), the complex + inverse trigonometric functions, and the quaternion and octonion types. +

      +
      import boost.math;
      +
      +int main()
      +{
      +    return boost::math::cdf(boost::math::normal_distribution<>(), 0.0) == 0.5 ? 0 : 1;
      +}
      +
      +

      + Module support is completely inert unless the module is built and consumed + explicitly: nothing changes for existing header users. +

      +
      + + How + to build +
      +

      + The module is consumable from C++20 onward. The interface unit lives in libs/math/module/math.cppm + and builds with any toolchain that provides the standard library module (import std); + the standard library maintainers agreed to make import + std available in C++20 mode as well + as C++23, so a C++23 compilation mode is not required. CI exercises two configurations, + both with CMake 4.4, Ninja and the matching CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + UUID: clang 20 with libc++ runs the full module test suite, and GCC 15 with + libstdc++ builds the module and runs the quick test (libstdc++ cannot yet mix + the textual standard library includes used by the wider test sources with + import std + in the same translation unit). From a Boost superproject checkout: +

      +
      cmake -G Ninja -DBOOST_INCLUDE_LIBRARIES=math -DBUILD_TESTING=ON \
      +  -DBOOST_MATH_BUILD_MODULE=ON \
      +  -DCMAKE_CXX_COMPILER=clang++-20 \
      +  -DCMAKE_CXX_FLAGS="-stdlib=libc++ -Wno-reserved-module-identifier" \
      +  -DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD=<uuid-for-your-cmake-version> \
      +  -DCMAKE_CXX_STDLIB_MODULES_JSON=/usr/lib/llvm-20/lib/libc++.modules.json ..
      +cmake --build . --target tests
      +ctest
      +
      +

      + The module test suite reuses a curated subset of the regular test files, which + switch from textual inclusion to import + boost.math; when + BOOST_MATH_BUILD_MODULE is + defined. The cmake-module-test + job in the library's CI runs this configuration on every commit. +

      +
      + + Limitations +
      +
        +
      • + The module is always built in standalone mode, so it has no dependencies + on other Boost libraries. +
      • +
      • + Macros do not cross module boundaries. The policy configuration macros + (BOOST_MATH_DOMAIN_ERROR_POLICY + and friends) and the convenience macros BOOST_MATH_DECLARE_DISTRIBUTIONS + and BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS + therefore have no effect on an importing translation unit. Configure policies + at the call site with boost::math::policies::make_policy + or a policy<...> + type instead; those interfaces are fully available through the import. +
      • +
      • + The user_error policy is + not supported through the module, because a user supplied boost::math::policies::user_..._error definition cannot attach to the + module. +
      • +
      • + A program should consume Boost.Math either through the module or through + textual includes, not both. The only headers that are safe to include textually + alongside the import are boost/math/tools/config.hpp + and boost/math/tools/assert.hpp, which the test support headers rely + on. +
      • +
      • + Excluded from the module: the TR1/C99 interfaces and common_factor + headers, boost/math/bindings, boost/math/concepts, + boost/math/cstdfloat, all deprecated headers, and + the headers that require external non-Boost dependencies (chebyshev_transform.hpp and interpolators/cardinal_trigonometric.hpp + need FFTW, optimization/cma_es.hpp + needs Eigen). These remain available as ordinary includes. +
      • +
      • + __float128 support (BOOST_MATH_USE_FLOAT128) is not enabled + in the module build. +
      • +
      • + On libc++ the parallel execution policy overloads in statistics compile + out (no <execution> support), matching the ordinary header + behavior on that standard library. +
      • +
      +
      + +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/math_toolkit/differential_evolution.html b/doc/html/math_toolkit/differential_evolution.html index dfe497b04b..89cf35cc4d 100644 --- a/doc/html/math_toolkit/differential_evolution.html +++ b/doc/html/math_toolkit/differential_evolution.html @@ -205,7 +205,7 @@

      An example use can be found here. - More examples and API use cases can be studied in differential_evolution_test.cpp. + More examples and API use cases can be studied in test_differential_evolution.cpp.

      diff --git a/doc/html/math_toolkit/dist_ref.html b/doc/html/math_toolkit/dist_ref.html index 075a288821..5a51fcf212 100644 --- a/doc/html/math_toolkit/dist_ref.html +++ b/doc/html/math_toolkit/dist_ref.html @@ -97,6 +97,8 @@
      Triangular Distribution
      Uniform Distribution
      +
      Von Mises + Distribution
      Weibull Distribution
      Distribution Algorithms
      diff --git a/doc/html/math_toolkit/dist_ref/dists.html b/doc/html/math_toolkit/dist_ref/dists.html index 698cafb7fb..e5357bf805 100644 --- a/doc/html/math_toolkit/dist_ref/dists.html +++ b/doc/html/math_toolkit/dist_ref/dists.html @@ -94,6 +94,8 @@
      Triangular Distribution
      Uniform Distribution
      +
      Von Mises + Distribution
      Weibull Distribution
      diff --git a/doc/html/math_toolkit/dist_ref/dists/bernoulli_dist.html b/doc/html/math_toolkit/dist_ref/dists/bernoulli_dist.html index bbf907f88c..0e32fe2243 100644 --- a/doc/html/math_toolkit/dist_ref/dists/bernoulli_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/bernoulli_dist.html @@ -257,7 +257,7 @@

      - if x <= (1-p) 1 else 0 + if x >= p 0 else 1

      diff --git a/doc/html/math_toolkit/dist_ref/dists/chi_squared_dist.html b/doc/html/math_toolkit/dist_ref/dists/chi_squared_dist.html index bd5a433ef4..2a689fc14a 100644 --- a/doc/html/math_toolkit/dist_ref/dists/chi_squared_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/chi_squared_dist.html @@ -52,10 +52,10 @@ // Parameter estimation: BOOST_MATH_GPU_ENABLED static RealType find_degrees_of_freedom( - RealType difference_from_mean, + RealType difference_from_variance, RealType alpha, RealType beta, - RealType sd, + RealType variance, RealType hint = 100); }; diff --git a/doc/html/math_toolkit/dist_ref/dists/geometric_dist.html b/doc/html/math_toolkit/dist_ref/dists/geometric_dist.html index b561b87dd8..39a259678e 100644 --- a/doc/html/math_toolkit/dist_ref/dists/geometric_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/geometric_dist.html @@ -53,11 +53,9 @@ // Bounds on success fraction: BOOST_MATH_GPU_ENABLED static RealType find_lower_bound_on_p( RealType trials, - RealType successes, RealType probability); // alpha BOOST_MATH_GPU_ENABLED static RealType find_upper_bound_on_p( RealType trials, - RealType successes, RealType probability); // alpha // Estimate min/max number of trials: @@ -255,8 +253,8 @@
      Bound on success_fraction Parameter p
      static RealType find_lower_bound_on_p(
      -  RealType failures,
      -  RealType probability) // (0 <= alpha <= 1), 0.05 equivalent to 95% confidence.
      +  RealType trials,
      +  RealType alpha) // (0 <= alpha <= 1), 0.05 equivalent to 95% confidence.
       

      Returns a lower bound on the success fraction: diff --git a/doc/html/math_toolkit/dist_ref/dists/hyperexponential_dist.html b/doc/html/math_toolkit/dist_ref/dists/hyperexponential_dist.html index 424b49cf2f..11cd17d7eb 100644 --- a/doc/html/math_toolkit/dist_ref/dists/hyperexponential_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/hyperexponential_dist.html @@ -63,10 +63,8 @@ template <typename RateRangeT> hyperexponential_distribution(RateRangeT const& rate_range); - #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) // C++11 initializer lists supported. hyperexponential_distribution(std::initializer_list<RealType> l1, std::initializer_list<RealType> l2); hyperexponential_distribution(std::initializer_list<RealType> l1); - #endif // Accessors: std::size_t num_phases() const; diff --git a/doc/html/math_toolkit/dist_ref/dists/hypergeometric_dist.html b/doc/html/math_toolkit/dist_ref/dists/hypergeometric_dist.html index ed7f053de1..2008b89b45 100644 --- a/doc/html/math_toolkit/dist_ref/dists/hypergeometric_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/hypergeometric_dist.html @@ -161,8 +161,11 @@

      The domain of the random variable are the 64-bit unsigned integers in the range [max(0, n + r - N), min(n, r)]. A domain_error - is raised if the random variable is outside this range, or is not an integral - value. + is raised if the random variable is outside this range. The CDF and its + complement also raise a domain_error + for a non-integral random variable; the PDF instead returns the analytic + continuation of its formula in terms of binomial coefficients (see Implementation + below).

      @@ -206,20 +209,13 @@
      precision.

      - For larger N such that N < boost::math::prime(boost::math::max_prime) then only basic arithmetic is required - for the calculation and the accuracy is typically < 20 epsilon. This - takes care of N up to 104729. -

      -

      - For N > - boost::math::prime(boost::math::max_prime) - then accuracy quickly degrades, with 5 or 6 decimal digits being lost for - N = 110000. -

      -

      - In general for very large N, the user should expect to lose log10N decimal - digits of precision during the calculation, with the results becoming meaningless - for N >= 1015. + For larger N the error is typically a few tens of epsilon wherever the + PDF exceeds e-15 +(about 3 × 10-7), however large N is, as long as products + of the parameters are exactly representable (below 253 at double precision). + Further into the tails the error is also a few tens of epsilon for N up + to 104729; beyond that it grows in proportion to |ln f(k)|, reaching around + a thousand epsilon where f(k) ~ e-700.

      @@ -307,12 +303,50 @@
      accurate than the alternatives.

      - For much larger N, we can calculate the PDF from the factorials using either - lgamma, or by directly combining lanczos approximations to avoid calculating - via logarithms. We use the latter method, as it is usually 1 or 2 decimal - digits more accurate than computing via logarithms with lgamma. However, - in this area where N > 104729, the user should expect to lose around - log10N decimal digits during the calculation in the worst case. + Prime factorisation is, however, slow, and above the table of primes it + is not available at all. So for N above the table of factorials we use + Loader's saddle-point method, as does R's dhyper: + the PDF is the ratio of binomial densities +

      +

      + f(k) = Binom(k; r, p) Binom(n - k; N - r, + p) / Binom(n; N, p) +

      +

      + in which the powers of p cancel for any p; + with p = n / N + the denominator is at its mode. Each binomial density is exp of a sum of + Stirling-series remainders and deviance terms, all small near the mode, + so near the mode the accuracy does not depend on N. The means of the deviance + terms are ratios of products of the parameters, which we form without rounding, + and we use the symmetry f(k; r, n, N) = f(r - k; r, N - n, N) to keep + p <= 1/2, since for p near + 1 large powers of 1 - p would otherwise have to cancel. + Because the result is an exponential, its relative error grows like |ln + f(k)| × epsilon in the tails, so where the PDF is below e-15 and N + is within the table of primes we recompute it by prime factorisation. +

      +

      + Loader, C. (2000), "Fast and Accurate Computation of Binomial Probabilities". +

      +

      + For non-integral k the PDF is the analytic continuation + of the formula above, with the binomial coefficients written in terms of + gamma functions. It is computed from the PDF at the integer j + = floor(k) and the shift d = + k - j: +

      +

      + f(k) = f(j) × Γ(j+1)/Γ(j+1+d) × Γ(N-r-n+j+1)/Γ(N-r-n+j+1+d) + × Γ(r-k+1+d)/Γ(r-k+1) × Γ(n-k+1+d)/Γ(n-k+1) +

      +

      + where each ratio is evaluated with tgamma_delta_ratio, + which is accurate for small d and large arguments. + The result is accurate to a few epsilon beyond the conditioning of the + function in k, agrees with the integer values as + d → 0, and is log-concave, so it is monotone + on either side of the mode.

      The CDF and its complement is calculated by directly summing the PDFs. diff --git a/doc/html/math_toolkit/dist_ref/dists/kolmogorov_smirnov_dist.html b/doc/html/math_toolkit/dist_ref/dists/kolmogorov_smirnov_dist.html index b583c90761..153cd51667 100644 --- a/doc/html/math_toolkit/dist_ref/dists/kolmogorov_smirnov_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/kolmogorov_smirnov_dist.html @@ -143,7 +143,10 @@

      function.

      - The PDF is implemented separately, and the following ULP plot illustrates + The PDF is implemented separately: each of its two series is evaluated + from a single exponential whose argument is corrected for the rounding + of x2n (and, for small x, of π2/8 and of the division), so that its error + does not grow with the size of the exponent. The following ULP plot illustrates its accuracy:

      @@ -157,6 +160,14 @@

      refers to deviations from the limiting approximation, rather than deviations from the exact distribution.

      +

      + The quantile is accurate to a few ulps of x over the + whole range of p, including small n + (where it exceeds unity) and probabilities down to the smallest normalized + number. The mode, median, skewness and kurtosis are tabulated constants + of the standardized distribution, accurate to 100 decimal digits, and so + are exact to within the scaling by n. +

      Implementation @@ -192,8 +203,14 @@
      @@ -224,8 +241,8 @@
      2*x*x*n/π)

      - When 2*x*x*n > π: -jacobi_theta4m1tau(0, - 2*x*x*n/π) + When 2*x*x*n > π: -jacobi_theta4m1(0, + q), as for the cdf

      @@ -237,7 +254,20 @@
      @@ -249,7 +279,7 @@
      @@ -261,7 +291,21 @@
      + + + + @@ -297,8 +341,8 @@
      @@ -310,17 +354,24 @@

      - Using the relation: cdf = jacobi_theta4tau(0, - 2*x*x/π) + When 2*x*x*n <= π: jacobi_theta4tau(0, + 2*x*x*n/π) +

      +

      + When 2*x*x*n > π: 1 + jacobi_theta4m1(0, + q) with the nome q = exp(-2*x*x*n), whose exponent is formed + with its rounding error compensated so that the theta function, + which raises q to integer powers, does not amplify it

      - Using a Newton-Raphson iteration + Using a Newton-Raphson iteration on the logarithm of the CDF, + or of its complement, in a variable in which it is nearly linear: +

      +

      + When p < 0.6: W = π2/(8x2n), where ln cdf = ln(4/sqrt(π)) + + ln(W)/2 - W + ln(1 + e-8W + e-24W + ...) +

      +

      + When p >= 0.6: V = x2n, where ln(1 - cdf) = ln(2) - 2V + ln(1 + - e-6V + e-16V - ...) +

      +

      + The starting value inverts the first two terms of the expansion, + which is already exact to working precision in the tails.

      - Using a Newton-Raphson iteration + As the quantile, with p = 1 - q

      - Using a run-time PDF maximizer + 0.735467907916571982... / sqrt(n), a tabulated root of the derivative + of the PDF +

      +
      +

      + median +

      +
      +

      + 0.827573555189907690... / sqrt(n), a tabulated root of cdf = + 1/2

      - (9/16*sqrt(π/2)*ζ(3)/n3/2 - 3 * mean * variance - mean2 * variance) - / (variance3/2) + 0.860426137143668255..., a tabulated evaluation of (9/16*sqrt(π/2)*ζ(3) + - 3 * mean * variance - mean3) / (variance3/2) with n = 1

      - (7/720*π4/n2 - 4 * mean * skewness * variance3/2 - 6 * mean2 * variance - - mean4) / (variance2) + 3 + 0.881618967910523670..., a tabulated evaluation of (7/720*π4 - + 4 * mean * skewness * variance3/2 - 6 * mean2 * variance - mean4) + / (variance2) with n = 1

      +

      + The tabulated constants are accurate to 100 decimal digits; for types with + more precision than that, the mode is refined by a Newton-Raphson iteration, + the median is computed from the quantile, and the skewness and kurtosis + are computed from the formulae above. +



      [2] diff --git a/doc/html/math_toolkit/dist_ref/dists/nc_f_dist.html b/doc/html/math_toolkit/dist_ref/dists/nc_f_dist.html index ef4c833847..1b0b1c4458 100644 --- a/doc/html/math_toolkit/dist_ref/dists/nc_f_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/nc_f_dist.html @@ -53,6 +53,11 @@ // Accessor to non-centrality parameter lambda: BOOST_MATH_GPU_ENABLED RealType non_centrality()const; + + // Parameter finders: + BOOST_MATH_GPU_ENABLED static RealType find_non_centrality(const RealType x, const RealType v1, const RealType v2, const RealType p); + template <class A, class B, class C, class D> + BOOST_MATH_GPU_ENABLED static RealType find_non_centrality(const complemented3_type<A,B,C,D>& c); }; }} // namespaces @@ -94,6 +99,30 @@

      +
      BOOST_MATH_GPU_ENABLED static RealType find_non_centrality(const RealType x, const RealType v1, const RealType v2, const RealType p);
      +
      +

      + This function returns the non centrality parameter lambda + such that: +

      +

      + cdf(non_central_chi_squared<RealType, Policy>(v1, v2, lambda), x) == + p +

      +
      template <class A, class B, class C, class D>
      +BOOST_MATH_GPU_ENABLED static RealType find_non_centrality(const complemented4_type<A,B,C,D>& c);
      +
      +

      + When called with argument boost::math::complement(x, + v1, + v2, + q) + this function returns the non centrality parameter lambda + such that: +

      +

      + cdf(complement(non_central_chi_squared<RealType, Policy>(v1, v2, lambda), x)) == q. +

      Member diff --git a/doc/html/math_toolkit/dist_ref/dists/negative_binomial_dist.html b/doc/html/math_toolkit/dist_ref/dists/negative_binomial_dist.html index 5fbc8302bd..895fa8248f 100644 --- a/doc/html/math_toolkit/dist_ref/dists/negative_binomial_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/negative_binomial_dist.html @@ -241,7 +241,7 @@
      Bound on Parameter p
      BOOST_MATH_GPU_ENABLED static RealType find_lower_bound_on_p(
      -  RealType failures,
      +  RealType trials,
         RealType successes,
         RealType probability) // (0 <= alpha <= 1), 0.05 equivalent to 95% confidence.
       
      @@ -251,10 +251,9 @@

      -
      failures
      +
      trials

      - The total number of failures before the rth - success. + The total number of trials conducted.

      successes

      diff --git a/doc/html/math_toolkit/dist_ref/dists/students_t_dist.html b/doc/html/math_toolkit/dist_ref/dists/students_t_dist.html index 60557b726a..91e8a332d9 100644 --- a/doc/html/math_toolkit/dist_ref/dists/students_t_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/students_t_dist.html @@ -56,6 +56,11 @@ RealType beta, RealType sd, RealType hint = 100); + + // degrees of freedom inversion from a quantile and probability: + BOOST_MATH_GPU_ENABLED static RealType find_degrees_of_freedom( + RealType t, + RealType p); }; }} // namespaces @@ -177,6 +182,15 @@

      For more information on this function see the NIST Engineering Statistics Handbook.

      +
      BOOST_MATH_GPU_ENABLED static RealType find_degrees_of_freedom(
      +   RealType t,
      +   RealType p);
      +
      +

      + Returns the degrees of freedom ν such that CDF(x; ν) + = p. Requires 0 < p < 1 + and x ≠ 0, otherwise calls domain_error. +

      Non-member @@ -410,6 +424,19 @@

      + + +

      + find_degrees_of_freedom(t, p) +

      + + +

      + Uses a 2nd-order Edgeworth expansion as initial guess for a numerical + root finder +

      + +

      diff --git a/doc/html/math_toolkit/dist_ref/dists/uniform_dist.html b/doc/html/math_toolkit/dist_ref/dists/uniform_dist.html index 39dc3e4201..38e0f4e62e 100644 --- a/doc/html/math_toolkit/dist_ref/dists/uniform_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/uniform_dist.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@


      -PrevUpHomeNext +PrevUpHomeNext

      @@ -362,7 +362,7 @@


      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/math_toolkit/dist_ref/dists/von_mises_dist.html b/doc/html/math_toolkit/dist_ref/dists/von_mises_dist.html new file mode 100644 index 0000000000..1f1d4d8584 --- /dev/null +++ b/doc/html/math_toolkit/dist_ref/dists/von_mises_dist.html @@ -0,0 +1,231 @@ + + + +Von Mises Distribution + + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +
      #include <boost/math/distributions/von_mises.hpp>
      +
      namespace boost{ namespace math{
      + template <typename RealType = double,
      +           typename Policy   = policies::policy<> >
      + class von_mises_distribution;
      +
      + using von_mises = von_mises_distribution<>;
      +
      + template <typename RealType, typename Policy>
      + class von_mises_distribution
      + {
      + public:
      +    using value_type = RealType;
      +    using policy_type = Policy;
      +
      +    explicit von_mises_distribution(RealType mean = 0, RealType concentration = 1);
      +
      +    RealType mean() const;
      +    RealType concentration() const;
      +    RealType location() const;
      +    RealType scale() const;
      + };
      +
      +}} // namespaces
      +
      +

      + The von + Mises distribution, also known as the circular normal distribution, + is a continuous probability distribution of an angle. With mean μ and concentration + κ its probability density function is +

      +

      + f(x; μ, κ) = eκ cos(x - μ) / (2π I0(κ)) +

      +

      + for μ - π <= x <= μ + π, where I0 is the modified Bessel function of the + first kind. With κ = 0 it is the uniform distribution on the circle, and + as κ grows it approaches a normal distribution with variance 1/κ. +

      +
      + + Member + Functions +
      +
      explicit von_mises_distribution(RealType mean = 0, RealType concentration = 1);
      +
      +

      + Constructs a von Mises distribution with mean mean + and concentration concentration. +

      +

      + Requires that mean is finite and that concentration + is finite and non-negative; otherwise calls domain_error. +

      +
      RealType mean() const;
      +RealType location() const;
      +
      +

      + Return the mean parameter of this distribution. +

      +
      RealType concentration() const;
      +RealType scale() const;
      +
      +

      + Return the concentration parameter of this distribution. +

      +
      + + Non-member + Accessors +
      +

      + All the usual non-member accessor + functions that are generic to all distributions are supported: + Cumulative Distribution Function, + Probability Density Function, + Quantile, Hazard Function, Cumulative Hazard Function, + __logcdf, __logpdf, mean, + median, mode, + variance, standard deviation, skewness, kurtosis, + kurtosis_excess, + range and support. +

      +

      + The support is one turn centred on the mean, μ - π <= x <= μ + π. Outside + it the pdf is zero and the cdf is 0 or 1. +

      +

      + The mean, median and mode are all μ, and the skewness is zero. The moments + are those of circular statistics: variance + returns the circular variance 1 - I1(κ)/I0(κ), and standard_deviation + returns the circular standard deviation √(-2 ln(I1(κ)/I0(κ))), so the standard + deviation is not the square root of the variance. With zero concentration + the circular standard deviation is infinite, and standard_deviation + calls overflow_error. +

      +
      + + Accuracy +
      +

      + The pdf and cdf have full relative accuracy in both tails, at any precision, + apart from the growth of error inherent in exp(κ cos(x - μ)) when κ is large. + The plots below compare double + against cpp_bin_float_50, + with the condition number of the function drawn as an envelope; they are + generated by reporting/accuracy/von_mises_ulps.cpp. +

      +
      • + PDF with concentration of 4* +
      +

      + +

      +
      • + PDF with concentration of 64* +
      +

      + +

      +
      • + CDF with concentration of 4* +
      +

      + +

      +
      • + CDF with concentration of 64* +
      +

      + +

      +
      + + Implementation +
      +

      + The normalization e-κI0(κ) is computed from cyl_bessel_i, + or from its asymptotic series when eκ would overflow. +

      +

      + For x <= μ the cdf is +

      +

      + F(x) = e-2κ sin2(a/2) / (2π e-κI0(κ)) ∫0π-a e-2κ sin(a + + s/2) sin(s/2) ds +

      +

      + with a = μ - x. The integrand is positive, so there is no cancellation in + the left tail, and it decays like e-κ s sin(a), so the range is cut where + it falls below machine epsilon. Up to double precision the integral is + evaluated with a 30-point Gauss-Legendre rule, and beyond that with tanh-sinh + quadrature. For x > μ the cdf is 1 - F(2μ - x), and the complement follows + by symmetry. +

      +

      + The circular variance is computed as e-κ(I0(κ) - I1(κ)) / e-κI0(κ), never as + a difference of the Bessel functions: for moderate κ both are integrals of + positive functions over a full period, which the trapezoidal rule evaluates + to geometric accuracy, and for large κ every term of their asymptotic series + is positive. +

      +

      + The quantile is found by Newton iteration on the cdf, starting from the + normal approximation. +

      +
      + + References +
      +
      +
      + +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/math_toolkit/dist_ref/dists/weibull_dist.html b/doc/html/math_toolkit/dist_ref/dists/weibull_dist.html index 91a58136a3..2c3e24122d 100644 --- a/doc/html/math_toolkit/dist_ref/dists/weibull_dist.html +++ b/doc/html/math_toolkit/dist_ref/dists/weibull_dist.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@
      -PrevUpHomeNext +PrevUpHomeNext

      @@ -398,7 +398,7 @@


      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/math_toolkit/double_exponential.html b/doc/html/math_toolkit/double_exponential.html index 9a23fcc2dd..0bd16a17e8 100644 --- a/doc/html/math_toolkit/double_exponential.html +++ b/doc/html/math_toolkit/double_exponential.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@
      -PrevUpHomeNext +PrevUpHomeNext

      @@ -34,6 +34,8 @@ functions with large features near an endpoint with tanh-sinh quadrature

  • sinh_sinh
    exp_sinh
    +
    Vector- and + matrix-valued integrands
    Setting the Termination Condition for Integration
    Setting the @@ -55,7 +57,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/double_exponential/de_exp_sinh.html b/doc/html/math_toolkit/double_exponential/de_exp_sinh.html index 94998119b3..2c96433398 100644 --- a/doc/html/math_toolkit/double_exponential/de_exp_sinh.html +++ b/doc/html/math_toolkit/double_exponential/de_exp_sinh.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -111,7 +111,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/double_exponential/de_matrix.html b/doc/html/math_toolkit/double_exponential/de_matrix.html new file mode 100644 index 0000000000..31904a296b --- /dev/null +++ b/doc/html/math_toolkit/double_exponential/de_matrix.html @@ -0,0 +1,119 @@ + + + +Vector- and matrix-valued integrands + + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + The CPU exp_sinh, sinh_sinh, and tanh_sinh + classes also accept an explicit additive identity and scalar norm. Insert + zero, + norm after the bounds, or after + f when using the default + domain: +

    +
    integrator.integrate(f, zero, norm, tolerance, &error, &L1, &levels);
    +integrator.integrate(f, a, b, zero, norm, tolerance, &error, &L1, &levels);
    +
    +

    + The bounded form is available for exp_sinh + and tanh_sinh; sinh_sinh always integrates over the whole + real line. Arguments after norm + retain their existing defaults. The new overloads participate only if applying + norm to the integrand's result + can be explicitly converted to Real. + Existing overloads remain unchanged. +

    +

    + For example, using Eigen with exp-sinh: +

    +
    using Matrix = Eigen::Matrix<std::complex<double>, 2, 2>;
    +Matrix zero = Matrix::Zero();
    +auto f = [](double x) -> Matrix {
    +    Matrix result;
    +    result << std::exp(-x), 0., 0., std::exp(-2*x);
    +    return result;
    +};
    +auto norm = [](const Matrix& m) { return m.stableNorm(); };
    +boost::math::quadrature::exp_sinh<double> integrator;
    +Matrix result = integrator.integrate(f, zero, norm);
    +
    +

    + Return concrete owning values, with dimensions matching zero, + rather than expression templates referencing temporary values. The value + type must support addition, addition assignment, unary negation, scalar multiplication + on either side, and multiplication assignment by a scalar. The norm must + be nonnegative, vanish only at zero, and return a scalar convertible to + Real. It should also report + non-finite values for non-finite inputs; endpoint checks use this property. + A norm implementation that avoids intermediate overflow and underflow is + useful for the large dynamic ranges encountered near endpoints. +

    +

    + The selected norm is used for successive-estimate errors, the L1 integral, + tail truncation, and checks for non-finite values. Convergence compares the + error with tolerance * + L1; it does not impose a separate + relative tolerance on every entry. Error estimates are not rigorous bounds, + and exhausting refinement levels does not guarantee that the requested tolerance + was reached. +

    +

    + Both forms of the two-argument tanh-sinh integrand are supported: f(x, xc) + may return a matrix, while x + and the signed endpoint distance xc + remain scalars. For the new bounded tanh-sinh overloads, equal bounds return + zero and set requested error, + L1, and level outputs to zero without calling f. + Reversed finite bounds negate the integral; the two-argument functor receives + distances for the endpoints in increasing order. Exp-sinh retains its requirement + for a half-infinite domain. +

    +

    + Domain errors use the scalar policy. If it returns, the result is zero times its scalar error value; requested + error and L1 outputs receive that value, and levels is set to zero. Evaluation-error + policies receive the scalar norm of the problematic value; a non-throwing + evaluation policy returns that concrete value or current estimate, as appropriate. + Diagnostic outputs are not specified after an evaluation error. GPU free-function + interfaces are unchanged. +

    +
    + +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/math_toolkit/double_exponential/de_tol.html b/doc/html/math_toolkit/double_exponential/de_tol.html index 2cdf33c6dd..e83489f61a 100644 --- a/doc/html/math_toolkit/double_exponential/de_tol.html +++ b/doc/html/math_toolkit/double_exponential/de_tol.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -69,7 +69,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/error_handling.html b/doc/html/math_toolkit/error_handling.html index 412838390e..0602ca358d 100644 --- a/doc/html/math_toolkit/error_handling.html +++ b/doc/html/math_toolkit/error_handling.html @@ -151,7 +151,7 @@

    the default action for each error shown in bold:

    -

    Table 1.1. Possible Actions for Domain Errors

    +

    Table 1.3. Possible Actions for Domain Errors

    @@ -226,7 +226,7 @@


    -

    Table 1.2. Possible Actions for Pole Errors

    +

    Table 1.4. Possible Actions for Pole Errors

    @@ -301,7 +301,7 @@


    -

    Table 1.3. Possible Actions for Overflow Errors

    +

    Table 1.5. Possible Actions for Overflow Errors

    @@ -376,7 +376,7 @@


    -

    Table 1.4. Possible Actions for Underflow Errors

    +

    Table 1.6. Possible Actions for Underflow Errors

    @@ -451,7 +451,7 @@


    -

    Table 1.5. Possible Actions for Denorm Errors

    +

    Table 1.7. Possible Actions for Denorm Errors

    @@ -526,7 +526,7 @@


    -

    Table 1.6. Possible Actions for Rounding Errors

    +

    Table 1.8. Possible Actions for Rounding Errors

    @@ -605,7 +605,7 @@


    -

    Table 1.7. Possible Actions for Internal Evaluation Errors

    +

    Table 1.9. Possible Actions for Internal Evaluation Errors

    @@ -680,7 +680,7 @@


    -

    Table 1.8. Possible Actions for Indeterminate Result Errors

    +

    Table 1.10. Possible Actions for Indeterminate Result Errors

    diff --git a/doc/html/math_toolkit/fourier_integrals.html b/doc/html/math_toolkit/fourier_integrals.html index a7e120b3d9..00822ac4f1 100644 --- a/doc/html/math_toolkit/fourier_integrals.html +++ b/doc/html/math_toolkit/fourier_integrals.html @@ -243,7 +243,7 @@

    For more examples of other functions and tests, see the full test suite at - ooura_fourier_integral_test.cpp. + test_ooura_fourier_integral.cpp.

    Ngyen and Nuyens make use of Boost.Multiprecision diff --git a/doc/html/math_toolkit/fp_facets/examples.html b/doc/html/math_toolkit/fp_facets/examples.html index 0aa3958450..8c257460b5 100644 --- a/doc/html/math_toolkit/fp_facets/examples.html +++ b/doc/html/math_toolkit/fp_facets/examples.html @@ -154,51 +154,6 @@

    s << setprecison(std::numeric_limits<double>::max_digits10) << scientific << output_value; s >> input_value; -
    - - Use - with serialization archives -
    -

    - It is vital that the same locale is used when an archive is saved and when - it is loaded. Otherwise, loading the archive may fail. By default, archives - are saved and loaded with a classic C locale with a boost::archive::codecvt_null - facet added. Normally you do not have to worry about that. -

    -

    - The constructors for the archive classes, as a side-effect, imbue the stream - with such a locale. However, if you want to use the facets nonfinite_num_put and nonfinite_num_get - with archives, then you have to manage the locale manually. That is done - by calling the archive constructor with the flag boost::archive::no_codecvt, - thereby ensuring that the archive constructor will not - imbue the stream with a new locale. -

    -

    - The following code shows how to use nonfinite_num_put - with a text_oarchive. -

    -
    locale default_locale(locale::classic(), new boost::archive::codecvt_null<char>);
    -locale my_locale(default_locale, new nonfinite_num_put<char>);
    -
    -ofstream ofs("test.txt");
    -ofs.imbue(my_locale);
    -
    -boost::archive::text_oarchive oa(ofs, no_codecvt);
    -
    -double x = numeric_limits<double>::infinity();
    -oa & x;
    -
    -

    - The same method works with nonfinite_num_get - and text_iarchive. -

    -

    - If you use the nonfinite_num_put - with trap_infinity and/or - trap_nan flag with a serialization - archive, then you must set the exception mask of the stream. Serialization - archives do not check the stream state. -

    Other @@ -233,12 +188,6 @@

    A simple example of trapping nonfinite output is at nonfinite_num_facet_trap.cpp.

    -

    - A very basic example of using Boost.Archive is at ../../example/nonfinite_serialization_archives.cpp. -

    -

    - A full demonstration of serialization by Francois Mauger is at ../../example/nonfinite_num_facet_serialization.cpp -

    - + Examples

    diff --git a/doc/html/math_toolkit/gauss_hermite.html b/doc/html/math_toolkit/gauss_hermite.html new file mode 100644 index 0000000000..5312db0e4e --- /dev/null +++ b/doc/html/math_toolkit/gauss_hermite.html @@ -0,0 +1,189 @@ + + + +Gauss-Hermite quadrature + + + + + + + + + +

    + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + + Synopsis +

    +

    + #include <boost/math/quadrature/gauss_hermite.hpp> +

    +
    namespace boost{ namespace math{ namespace quadrature{
    +
    +template <class Real, unsigned Points, class Policy = boost::math::policies::policy<> >
    +struct gauss_hermite
    +{
    +   static const RandomAccessContainer& abscissa();
    +   static const RandomAccessContainer& weights();
    +
    +   template <class F>
    +   static auto integrate(F f, Real* pL1 = nullptr)->decltype(std::declval<F>()(std::declval<Real>()));
    +
    +   template <class F, class Norm>
    +   static auto integrate(F f, const decltype(f(Real(0)))& zero, Norm norm,
    +                         Real* pL1 = nullptr) -> decltype(f(Real(0)));
    +};
    +
    +}}} // namespaces
    +
    +

    + + Description +

    +

    + The gauss_hermite class template + computes +

    +

    + ∫-∞∞ f(x) e-x2 dx ≈ ∑i wi f(xi) +

    +

    + using Points evaluations of f, where + the abscissas /xi/ are the zeros of the Hermite polynomial /HPoints. + The rule is exact when /f is a polynomial of degree at most 2/Points/ + - 1. Note that the weight function exp(-x2) is not part + of f: pass only the factor that multiplies it. +

    +

    + Like gauss, + this is a "one shot" non-adaptive routine. It obtains no estimate + of the error, and is intended for smooth f that grow no + faster than a polynomial, such as expectations of smooth functions of a normally + distributed variable. +

    +
    static const RandomAccessContainer& abscissa();
    +static const RandomAccessContainer& weights();
    +
    +

    + These provide direct access to the abscissas and weights. Only the nonnegative + abscissas are stored, in increasing order; the rule is symmetric about zero. +

    +
    template <class F>
    +static auto integrate(F f, Real* pL1 = nullptr)->decltype(std::declval<F>()(std::declval<Real>()));
    +
    +

    + Integrates f(x) exp(-x2) + over the real line, and optionally sets *pL1 to the corresponding integral of |f|. + If that is substantially larger than the absolute value of the result, then + the sum was ill-conditioned. f may return a real or complex + value. +

    +
    template <class F, class Norm>
    +static auto integrate(F f, const decltype(f(Real(0)))& zero, Norm norm,
    +                      Real* pL1 = nullptr) -> decltype(f(Real(0)));
    +
    +

    + As for gauss, + this overload handles vector- and matrix-valued integrands: zero + is the additive identity of the returned type, and norm + returns a nonnegative scalar convertible to Real. +

    +

    + + Example +

    +

    + If X is normally distributed with mean μ and standard deviation + σ, then substituting X = μ + √2 σ x gives +

    +

    + E[g(X)] = π-1/2 ∫-∞∞ g(μ + √2 σ x) e-x2 dx +

    +

    + so, for example, E[cos X] = exp(-σ2/2) cos μ is computed + by +

    +
    using boost::math::quadrature::gauss_hermite;
    +using boost::math::constants::root_pi;
    +using boost::math::constants::root_two;
    +double mu = 0.5;
    +double sigma = 2;
    +auto g = [&](double x) { return std::cos(mu + root_two<double>() * sigma * x); };
    +double expectation = gauss_hermite<double, 30>::integrate(g) / root_pi<double>();
    +
    +

    + + Choosing + the number of points +

    +

    + gauss_hermite has pre-computed + tables of abscissas and weights for 7, 10 and 15 points, at up to 110 decimal + digits of precision. For other numbers of points, or higher precision types, + the abscissas and weights are computed the first time they are needed and then + cached. Each zero is isolated by bisection with a Sturm sequence, then refined + with Halley's method, all evaluated with the three-term recurrence for orthonormal + Hermite polynomials. In double precision the computed abscissas are within + a few ulps of the correctly rounded values and the weights within about one + hundred, for up to at least 200 points. +

    +

    + In double precision the recurrence overflows for more than 706 points (the + outer weights underflow long before that). integrate + then raises an evaluation_error + through the Policy; if the policy does not throw, the + result is a NaN. +

    +

    + As with gauss, defining BOOST_MATH_GAUSS_NO_COMPUTE_ON_DEMAND turns + any combination of type and number of points without pre-computed values into + a compile-time error. The program gauss_hermite_constants.cpp + generates the pre-computed tables, and is easily modified for other numbers + of points. +

    +

    + + References +

    +
      +
    • + G. H. Golub and J. H. Welsch, Calculation of Gauss quadrature + rules, Mathematics of Computation 23 (1969), 221-230. +
    • +
    • + W. Gautschi, Orthogonal Polynomials: Computation and Approximation, + Oxford University Press, 2004. +
    • +
    +
    + +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/math_toolkit/gauss_kronrod.html b/doc/html/math_toolkit/gauss_kronrod.html index 9fc69aae2a..5be8e712a6 100644 --- a/doc/html/math_toolkit/gauss_kronrod.html +++ b/doc/html/math_toolkit/gauss_kronrod.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -84,6 +84,59 @@

    + Vector- + and matrix-valued integrands +

    +

    + An additional overload accepts an explicit additive identity and a scalar norm: +

    +
    template <class F, class Norm>
    +static auto integrate(F f, Real a, Real b,
    +                      const decltype(f(a))& zero, Norm norm,
    +                      unsigned max_depth = 15,
    +                      Real tol = tools::root_epsilon<Real>(),
    +                      Real* error = nullptr, Real* pL1 = nullptr)
    +    -> decltype(f(a));
    +
    +

    + This overload participates only when norm(f(a)) can be + explicitly converted to Real. + Existing overloads and their behavior are unchanged. +

    +

    + As with the Gauss overloads, f must return a concrete value type supporting + addition, addition assignment, unary negation, and scalar multiplication on + either side. The supplied zero and all integrand values must have compatible + dimensions. The norm must be nonnegative and convertible to Real. + For example, with Eigen: +

    +
    Eigen::MatrixXcd zero = Eigen::MatrixXcd::Zero(rows, cols);
    +auto norm = [](const Eigen::MatrixXcd& m) { return m.norm(); };
    +Eigen::MatrixXcd result = boost::math::quadrature::gauss_kronrod<double, 15>::integrate(
    +    f, a, b, zero, norm, 15, 1e-10);
    +
    +

    + The supplied norm is used for the Gauss-Kronrod difference, the roundoff floor, + the relative convergence test, and the L1 integral. Tolerance therefore applies + to that norm, not separately to each matrix entry. error + is an estimate, not a rigorous bound, and reaching max_depth + does not guarantee the requested tolerance. In this overload, local error estimates + are scaled by interval width, and by the additional factor in the half-infinite + substitutions, to match the units of the returned integral. Reversing finite + bounds negates the integral but leaves error and L1 nonnegative. +

    +

    + Equal bounds return the supplied zero and set requested error and L1 outputs + to zero without evaluating f. + Invalid bounds invoke the scalar domain-error policy; if it returns instead + of throwing, the result is zero + multiplied by the policy's scalar error value, and requested error and L1 outputs + receive that value. For floating-point Eigen matrices the standard ignore-error + policy thus produces a matrix of NaNs with the supplied dimensions. No Eigen + dependency is added to Boost.Math headers. +

    +

    + Description

    static const RandomAccessContainer& abscissa();
    @@ -130,7 +183,7 @@ 

    the result is likely to be ill-conditioned.

    - + Choosing the number of points

    @@ -169,7 +222,7 @@

  • - + Complex Quadrature

    @@ -179,7 +232,7 @@

    and the complex type is deduced via the return type of the function.

    - + Examples

    @@ -230,7 +283,7 @@

    We still achieve 1e-15 precision, with an error estimate of 1e-10.

    - + Caveats

    @@ -251,7 +304,7 @@

    integration schemes which are generally much more robust.

    - + References

      @@ -280,7 +333,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/gpu.html b/doc/html/math_toolkit/gpu.html index 4416b66463..c75087f19a 100644 --- a/doc/html/math_toolkit/gpu.html +++ b/doc/html/math_toolkit/gpu.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -43,6 +43,22 @@

    + Library + owned kernels +
    +

    + One facility launches its own kernels instead of being called from a user's + kernel: the prime sieve (boost::math::prime_sieve, prime_range, + prime_count) accepts boost::math::execution::cuda as + its execution policy. When the translation unit is compiled by nvcc with BOOST_MATH_ENABLE_CUDA defined, the header + <boost/math/special_functions/prime_sieve.hpp> defines + BOOST_MATH_HAS_CUDA_PRIME_SIEVE + and sieves the requested range on the device, managing the device memory and + the kernel launches itself. Without nvcc the same call runs on the CPU. See + the prime sieve documentation for details and measurements. +

    +
    + Policies

    @@ -51,7 +67,7 @@

    is run on device it will be ignored.

    - + How to build with device support
    @@ -99,6 +115,10 @@
    }); } +

    + When using SYCL you must define BOOST_MATH_ENABLE_SYCL, since device support + is opt-in on that platform. For NVCC and NVRTC device support is enabled automatically. +

    Once your kernel function has been written then use the framework mechanism for launching the kernel. @@ -115,7 +135,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/history1.html b/doc/html/math_toolkit/history1.html index 5eba9e040e..d34c1ea5a8 100644 --- a/doc/html/math_toolkit/history1.html +++ b/doc/html/math_toolkit/history1.html @@ -64,6 +64,10 @@
  • Lots of minor fixes and improved code coverage.
  • +
  • + Add support for the M nearest-neighbour Chatterjee correlation of Lin and + Han (2021), see 990. +
  • diff --git a/doc/html/math_toolkit/history2.html b/doc/html/math_toolkit/history2.html index d29d142e0b..2333caf972 100644 --- a/doc/html/math_toolkit/history2.html +++ b/doc/html/math_toolkit/history2.html @@ -64,6 +64,10 @@
  • Lots of minor fixes and improved code coverage.
  • +
  • + Add support for the M nearest-neighbour Chatterjee correlation of Lin and + Han (2021), see 990. +
  • diff --git a/doc/html/math_toolkit/internals/simple_continued_fraction.html b/doc/html/math_toolkit/internals/simple_continued_fraction.html index 82cbbe9e07..623f604435 100644 --- a/doc/html/math_toolkit/internals/simple_continued_fraction.html +++ b/doc/html/math_toolkit/internals/simple_continued_fraction.html @@ -40,8 +40,10 @@ Real khinchin_harmonic_mean() const; + const std::vector<Z>& partial_denominators() const; + template<typename T, typename Z_> - friend std::ostream& operator<<(std::ostream& out, simple_continued_fraction<T, Z>& scf); + friend std::ostream& operator<<(std::ostream& out, const simple_continued_fraction<T, Z_>& scf); }; } @@ -66,6 +68,50 @@ with the modified Lentz's algorithm. Once a convergent is within a few ulps of the input value, the computation stops.

    +

    + Finite simple continued fractions are not unique: [a0; a1, ..., an, 1] + and [a0; a1, + ..., an + + 1] represent the same value. The class uses + the shorter, canonical representation, absorbing a trailing 1 into the preceding coefficient. For example, + 3.75 is represented as [3; + 1, 3], rather + than [3; 1, + 2, 1]. +

    +

    + The partial_denominators() member function returns a read-only reference + to the stored coefficients, including the integer part at index zero: +

    +
    const auto& a = cfrac.partial_denominators();
    +std::cout << a.size() << " coefficients\n";
    +std::cout << a[0] << "\n";    // Integer part: 3
    +std::cout << a.at(1) << "\n"; // First partial denominator: 7
    +
    +

    + The reference remains valid for the lifetime of cfrac. +

    +

    + A prefix of these coefficients defines a convergent, which can be used as + a rational approximation. For example, the first four coefficients of the + expansion of π give 355/113. With #include + <boost/rational.hpp>, + this can be computed by evaluating the prefix backwards: +

    +
    using rational = boost::rational<std::int64_t>;
    +std::size_t n = 4; // Use the first four coefficients of cfrac above.
    +rational approximation(a.at(n - 1));
    +for (std::size_t i = n - 1; i > 0; --i) {
    +    approximation = rational(a[i - 1]) + rational(1) / approximation;
    +}
    +std::cout << approximation << "\n"; // Prints: 355/113
    +
    +

    + In general, choose n between + 1 and a.size() + and an integer type wide enough for the rational arithmetic, including intermediate + results. Longer prefixes can overflow a fixed-width integer type. +

    Note that every floating point number is a rational number, and this exact rational can be exactly converted to a finite continued fraction. This is diff --git a/doc/html/math_toolkit/jacobi_theta/jacobi_theta1.html b/doc/html/math_toolkit/jacobi_theta/jacobi_theta1.html index a7c05f3d48..85a5577d7c 100644 --- a/doc/html/math_toolkit/jacobi_theta/jacobi_theta1.html +++ b/doc/html/math_toolkit/jacobi_theta/jacobi_theta1.html @@ -110,15 +110,19 @@

    - Accuracy tends to degenerate near q=1 (small τ). + Accuracy degrades gently as q approaches 1 (small τ), + where the rounding of log(q) is amplified by the size + of the exponents in the transformed series; the τ parameterization does not + have this problem.

    Implementation

    - The q parameterization is implemented using the τ parameterization, - where τ=-log(q)/π. + When q < exp(-π) the series above is summed directly + in q. Otherwise the q parameterization + is implemented using the τ parameterization, where τ=-log(q)/π.

    If τ is greater than or equal to 1, the summation above is used as-is. However @@ -131,7 +135,11 @@

    This transformation of variables ensures that the function will always converge - in a small number of iterations. + in a small number of iterations. The transformed series is a sum of differences + of Gaussians centered at ±π(n+1/2), which nearly cancel + as x approaches zero; each difference is therefore evaluated + using expm1 + so that full relative precision is retained for small x.

    - Accuracy tends to degenerate near q=1 (small τ). + Accuracy degrades gently as q approaches 1 (small τ), + where the rounding of log(q) is amplified by the size + of the exponents in the transformed series; the τ parameterization does not + have this problem.

    Implementation

    - The q parameterization is implemented using the τ parameterization, - where τ=-log(q)/π. + When q < exp(-π) the series above is summed directly + in q. Otherwise the q parameterization + is implemented using the τ parameterization, where τ=-log(q)/π.

    If τ is greater than or equal to 1, the summation above is used as-is. However diff --git a/doc/html/math_toolkit/jacobi_theta/jacobi_theta3.html b/doc/html/math_toolkit/jacobi_theta/jacobi_theta3.html index d0e2788a24..9b6f793e7d 100644 --- a/doc/html/math_toolkit/jacobi_theta/jacobi_theta3.html +++ b/doc/html/math_toolkit/jacobi_theta/jacobi_theta3.html @@ -127,15 +127,19 @@

    - Accuracy tends to degenerate near q=1 (small τ). + Accuracy degrades gently as q approaches 1 (small τ), + where the rounding of log(q) is amplified by the size + of the exponents in the transformed series; the τ parameterization does not + have this problem.

    Implementation

    - The q parameterization is implemented using the τ parameterization, - where τ=-log(q)/π. + When q < exp(-π) the series above is summed directly + in q. Otherwise the q parameterization + is implemented using the τ parameterization, where τ=-log(q)/π.

    If τ is greater than or equal to 1, the summation above is used as-is. However diff --git a/doc/html/math_toolkit/jacobi_theta/jacobi_theta4.html b/doc/html/math_toolkit/jacobi_theta/jacobi_theta4.html index 8f09a8aac2..0ef57c30b3 100644 --- a/doc/html/math_toolkit/jacobi_theta/jacobi_theta4.html +++ b/doc/html/math_toolkit/jacobi_theta/jacobi_theta4.html @@ -127,15 +127,19 @@

    - Accuracy tends to degenerate near q=1 (small τ). + Accuracy degrades gently as q approaches 1 (small τ), + where the rounding of log(q) is amplified by the size + of the exponents in the transformed series; the τ parameterization does not + have this problem.

    Implementation

    - The q parameterization is implemented using the τ parameterization, - where τ=-log(q)/π. + When q < exp(-π) the series above is summed directly + in q. Otherwise the q parameterization + is implemented using the τ parameterization, where τ=-log(q)/π.

    If τ is greater than or equal to 1, the summation above is used as-is. However diff --git a/doc/html/math_toolkit/jacobi_theta/jacobi_theta_overview.html b/doc/html/math_toolkit/jacobi_theta/jacobi_theta_overview.html index 5915ee1936..ffa1e2f9b7 100644 --- a/doc/html/math_toolkit/jacobi_theta/jacobi_theta_overview.html +++ b/doc/html/math_toolkit/jacobi_theta/jacobi_theta_overview.html @@ -110,11 +110,31 @@

    jacobi_theta1tau(x, a / boost::math::constants::pi<T>());
     

    - Internally, Boost implements the q parameterization + Internally, when q is larger than exp(-π) (that is, when + τ is less than 1), Boost implements the q parameterization by taking the logarithm of q and passing it to the τ parameterization; as such, using the τ parameterization directly will generally yield greater - precision. As another example, if the complement of q - is known with great accuracy, then instead of: + precision in that regime. When q is smaller than exp(-π), + the Fourier series is summed directly in terms of q, + and the two parameterizations are equally accurate. +

    +

    + Every term of the series is an exponential whose argument is a product or + quotient of τ, π and a small integer, or, in the transformed series used when + τ < 1, the square of z plus a multiple of π/2. Rounding + such an argument to working precision would cost as many ulps in the term + as the argument is large, so the rounding errors of π, of the products, of + the division and of the reduction of z are tracked exactly + (using error-free transformations that work for any binary floating-point + type) and applied as a correction factor to each term. The τ parameterization + is therefore accurate to a few ulps throughout, apart from the conditioning + of the function itself, for z up to about 1/ε (1016 for + double); beyond that the reduction + of z by the period loses accuracy in proportion to + zε2. In the q parameterization the + rounding of log(q) remains, and its effect grows as + q approaches 1. As another example, if the complement + of q is known with great accuracy, then instead of:

    jacobi_theta1(x, 1-q_complement);
     
    @@ -130,6 +150,12 @@
    these functions return one less than the evaluated function, and yield increased accuracy when q is small.

    +

    + All of the functions return the result of domain_error + if z is not finite, if q lies outside + (0, 1), or if τ is not strictly positive. A NaN argument is treated as a domain + error. +

    Testing diff --git a/doc/html/math_toolkit/naive_monte_carlo.html b/doc/html/math_toolkit/naive_monte_carlo.html index 49ccb45176..4f59dae38a 100644 --- a/doc/html/math_toolkit/naive_monte_carlo.html +++ b/doc/html/math_toolkit/naive_monte_carlo.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -230,7 +230,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/namespaces.html b/doc/html/math_toolkit/namespaces.html index b96ccf409a..ef4655edf8 100644 --- a/doc/html/math_toolkit/namespaces.html +++ b/doc/html/math_toolkit/namespaces.html @@ -29,7 +29,9 @@

    All math functions and distributions are in namespace - boost::math. + boost::math. Libraries that embed their own copy + of Boost.Math can move it into a different namespace, see Configurable + Namespace.

    So, for example, the Students-t distribution template in namespace diff --git a/doc/html/math_toolkit/navigation.html b/doc/html/math_toolkit/navigation.html index 7ae0278709..2f1ef23d85 100644 --- a/doc/html/math_toolkit/navigation.html +++ b/doc/html/math_toolkit/navigation.html @@ -28,7 +28,7 @@ Navigation

    - +

    Boost.Math documentation is provided in both HTML and PDF formats. diff --git a/doc/html/math_toolkit/number_series.html b/doc/html/math_toolkit/number_series.html index 11e894ad39..7212af631c 100644 --- a/doc/html/math_toolkit/number_series.html +++ b/doc/html/math_toolkit/number_series.html @@ -32,6 +32,7 @@ Numbers

    Tangent Numbers
    Prime Numbers
    +
    Prime Sieve
    Fibonacci Numbers
    diff --git a/doc/html/math_toolkit/number_series/fibonacci_numbers.html b/doc/html/math_toolkit/number_series/fibonacci_numbers.html index 27117b9d0d..43d40bea1d 100644 --- a/doc/html/math_toolkit/number_series/fibonacci_numbers.html +++ b/doc/html/math_toolkit/number_series/fibonacci_numbers.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -190,7 +190,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/number_series/prime_sieve.html b/doc/html/math_toolkit/number_series/prime_sieve.html new file mode 100644 index 0000000000..410da8a718 --- /dev/null +++ b/doc/html/math_toolkit/number_series/prime_sieve.html @@ -0,0 +1,964 @@ + + + +Prime Sieve + + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +
    + + Synopsis +
    +
    #include <boost/math/special_functions/prime_sieve.hpp>
    +
    +
    namespace boost { namespace math {
    +
    +namespace execution {
    +   struct cuda_policy {};
    +   inline constexpr cuda_policy cuda {};
    +}
    +
    +enum class prime_range_strategy { automatic, full_sieve, test_survivors };
    +
    +struct prime_sieve_options
    +{
    +   std::size_t l1d_bytes {0};          // 0 = detect
    +   std::size_t l2_bytes {0};           // 0 = detect (per core)
    +   std::size_t sieve_bytes {0};        // 0 = derive from sqrt(upper) and the caches; clamped to [16 KiB, 8 MiB]
    +   unsigned max_threads {0};           // 0 = std::thread::hardware_concurrency()
    +   std::size_t chunk_primes {1u << 19};  // primes per parallel chunk when storing output
    +   prime_range_strategy range_strategy {prime_range_strategy::automatic};
    +   bool probable_prime_only {false};   // beyond 2^64: Baillie-PSW only, skip the pseudosquares test
    +};
    +
    +// primes in [2, upper_bound)
    +template <class ExecutionPolicy, class Integer, class OutputIterator>
    +OutputIterator prime_sieve(ExecutionPolicy&& policy, Integer upper_bound, OutputIterator out, const prime_sieve_options& options = {});
    +template <class Integer, class OutputIterator>
    +OutputIterator prime_sieve(Integer upper_bound, OutputIterator out, const prime_sieve_options& options = {});
    +template <class ExecutionPolicy, class Integer, class T, class Alloc>
    +void prime_sieve(ExecutionPolicy&& policy, Integer upper_bound, std::vector<T, Alloc>& out, const prime_sieve_options& options = {});
    +template <class Integer, class T, class Alloc>
    +void prime_sieve(Integer upper_bound, std::vector<T, Alloc>& out, const prime_sieve_options& options = {});
    +
    +// primes in [lower_bound, upper_bound); the bounds may have different integer types
    +template <class ExecutionPolicy, class Lower, class Upper, class OutputIterator>
    +OutputIterator prime_range(ExecutionPolicy&& policy, Lower lower_bound, Upper upper_bound, OutputIterator out, const prime_sieve_options& options = {});
    +template <class Lower, class Upper, class OutputIterator>
    +OutputIterator prime_range(Lower lower_bound, Upper upper_bound, OutputIterator out, const prime_sieve_options& options = {});
    +template <class ExecutionPolicy, class Lower, class Upper, class T, class Alloc>
    +void prime_range(ExecutionPolicy&& policy, Lower lower_bound, Upper upper_bound, std::vector<T, Alloc>& out, const prime_sieve_options& options = {});
    +template <class Lower, class Upper, class T, class Alloc>
    +void prime_range(Lower lower_bound, Upper upper_bound, std::vector<T, Alloc>& out, const prime_sieve_options& options = {});
    +
    +// number of primes in [2, upper_bound) and in [lower_bound, upper_bound)
    +template <class ExecutionPolicy, class Integer>
    +std::uint64_t prime_count(ExecutionPolicy&& policy, Integer upper_bound, const prime_sieve_options& options = {});
    +template <class ExecutionPolicy, class Lower, class Upper>
    +std::uint64_t prime_count(ExecutionPolicy&& policy, Lower lower_bound, Upper upper_bound, const prime_sieve_options& options = {});
    +template <class Integer>
    +std::uint64_t prime_count(Integer upper_bound, const prime_sieve_options& options = {});
    +template <class Lower, class Upper>
    +std::uint64_t prime_count(Lower lower_bound, Upper upper_bound, const prime_sieve_options& options = {});
    +
    +// reserves room for all primes below upper_bound
    +template <class Integer, class T, class Alloc>
    +void prime_reserve(Integer upper_bound, std::vector<T, Alloc>& primes);
    +
    +}} // namespaces
    +
    +
    + + Description +
    +

    + These functions require C++17. +

    +

    + prime_sieve produces the + primes in the half-open range [2, upper_bound), + prime_range the primes in + [lower_bound, upper_bound), and prime_count + returns how many primes such a range contains without storing them. Output + is always in ascending order. The overloads taking a std::vector + append to it and are the fastest way to store the primes; the output iterator + overloads return the advanced iterator. A lower_bound + below 2 is treated as 2, negative bounds as 0, and an empty range produces + nothing. A negative bound is clamped in its own type, so mixing a signed + and an unsigned bound is safe. +

    +

    + Integer may be any builtin + integer type or a Boost.Multiprecision integer such as cpp_int + or mpz_int. Bounds that fit + in 64 bits are sieved with a segmented sieve of Eratosthenes in the style + of primesieve: + one byte represents 30 integers (the eight residues coprime to 30), multiples + of the primes up to 163 are removed by pre-computed periodic patterns, and + the sieving primes are split into three classes (many multiples per segment, + a few, or at most one) that use a mod 30 wheel with unrolled loops, lists + sorted by wheel position, and Oliveira e Silva's bucket sieve (fixed 8 KiB + buckets from a memory pool) respectively. Segments are sized to the L1 and + L2 data caches, which are detected on Linux and macOS and can be overridden + through prime_sieve_options; + when big primes are present the largest segment (8 MiB) is used. The wheel + tables and the 16 pre-sieve patterns (123 KB) are computed at compile time + with constexpr on GCC and Clang; + MSVC and nvcc, whose constexpr step limits are lower, generate the patterns + on first use (define BOOST_MATH_PRIME_SIEVE_RUNTIME_PRESIEVE + to force that everywhere). +

    +

    + Short intervals at large magnitudes (roughly when the interval is narrower + than sqrt(upper_bound) + / ln(upper_bound)) switch automatically to a window method: + the interval is sieved by the primes up to a modest depth and the survivors + are tested with a Baillie-PSW test in Montgomery arithmetic, which is deterministic + below 264. prime_range_strategy + forces either method. +

    +

    + Bounds beyond 264 use the same window method with the Lukes-Patterson-Williams + pseudosquares test (Sorenson, The pseudosquares prime sieve, + 2006), which is deterministic while upper_bound + divided by the sieving depth stays below the largest tabulated pseudosquare + (about 2.95 * 1023), and Baillie-PSW beyond that, for which no counterexample + is known. Setting probable_prime_only + uses Baillie-PSW everywhere and is roughly ten times faster. This path is + intended for windows of up to about 108 integers; the head of a range that + straddles 264 is still processed by the 64-bit engine. +

    +
    + + Execution + policies +
    +

    + The policy overloads accept the std::execution + policies and boost::math::execution::cuda: +

    +
    ++++ + + + + + + + + + + + + + + + + + + +
    +

    + Policy +

    +
    +

    + Effect +

    +
    +

    + std::execution::seq, std::execution::unseq, + or no policy +

    +
    +

    + Single threaded. +

    +
    +

    + std::execution::par, std::execution::par_unseq +

    +
    +

    + The range is cut into chunks of about 200 * sqrt(upper_bound) integers that are + handed to max_threads + worker threads through an atomic counter; each worker owns its + sieve and shares the read-only sieving primes. Output is committed + in order, so the result is identical to the sequential one. +

    +
    +

    + boost::math::execution::cuda +

    +
    +

    + When the translation unit is compiled by nvcc with BOOST_MATH_ENABLE_CUDA defined, + the range is sieved on the GPU (BOOST_MATH_HAS_CUDA_PRIME_SIEVE + is defined in that case). Otherwise the call runs on the CPU with + the parallel policy. +

    +
    +

    + The std::execution overloads are available when + the standard library provides the policy types (libstdc++ 9 and later, MSVC, + and libc++ with -fexperimental-library); + no parallel algorithms and therefore no TBB are required. Threads are never + used when Boost.Math is configured without thread support. +

    +
    + + Examples +
    +
    #include <boost/math/special_functions/prime_sieve.hpp>
    +#include <boost/multiprecision/cpp_int.hpp>
    +#include <execution>
    +#include <vector>
    +#include <list>
    +#include <iterator>
    +#include <cstdint>
    +
    +// All primes below one billion, using every core
    +std::vector<std::uint64_t> primes;
    +boost::math::prime_reserve(1'000'000'000, primes);
    +boost::math::prime_sieve(std::execution::par, 1'000'000'000, primes);
    +
    +// Count the primes in [10^18, 10^18 + 10^9) on one thread
    +std::uint64_t n = boost::math::prime_count(1'000'000'000'000'000'000ull, 1'000'000'001'000'000'000ull);
    +
    +// Primes just above 2^64 with an arbitrary precision type
    +using boost::multiprecision::cpp_int;
    +std::vector<cpp_int> big;
    +boost::math::prime_range(cpp_int(1) << 64, (cpp_int(1) << 64) + 1'000'000, big);
    +
    +// A range through any output iterator
    +std::list<int> small;
    +boost::math::prime_range(100, 1000, std::back_inserter(small));
    +
    +
    + + Performance +
    +

    + Measured with the Google Benchmark harness in reporting/performance/prime_sieve_performance.cpp on + an Apple M4 Max (12 performance and 4 efficiency cores, 128 KiB L1D), Apple + clang 17, -O3 + -march=native, + against primesieve 12.16 built from source on the same machine. Times are + wall clock in milliseconds. +

    +
    +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    + Task +

    +
    +

    + boost::math, 1 thread +

    +
    +

    + primesieve, 1 thread +

    +
    +

    + boost::math, 16 threads +

    +
    +

    + primesieve, 16 threads +

    +
    +

    + count primes below 108 +

    +
    +

    + 2.6 +

    +
    +

    + 3.2 +

    +
    +

    + 0.8 +

    +
    +
    +

    + count primes below 109 +

    +
    +

    + 37 +

    +
    +

    + 44 +

    +
    +

    + 5.4 +

    +
    +

    + 5 +

    +
    +

    + count primes below 1010 +

    +
    +

    + 495 +

    +
    +

    + 566 +

    +
    +

    + 63 +

    +
    +

    + 56 +

    +
    +

    + count primes below 1011 +

    +
    +

    + 6660 +

    +
    +

    + 7620 +

    +
    +

    + 744 +

    +
    +

    + 654 +

    +
    +

    + store primes below 109 +

    +
    +

    + 89 +

    +
    +

    + 84 +

    +
    +

    + 23 +

    +
    +
    +

    + store primes below 1010 +

    +
    +

    + 1051 +

    +
    +

    + 1027 +

    +
    +

    + 286 +

    +
    +
    +

    + count a 109 window at 1012 +

    +
    +

    + 91 +

    +
    +

    + 108 +

    +
    + +
    +

    + count a 109 window at 1015 +

    +
    +

    + 167 +

    +
    +

    + 267 +

    +
    + +
    +

    + count a 109 window at 1018 +

    +
    +

    + 619 +

    +
    +

    + 732 +

    +
    + +
    +

    + The same comparison on an Intel Core i9-11900K (8 cores, 48 KiB L1D, 512 + KiB L2 per core) with GCC 13, -O3 -march=native, + primesieve 12.16 built from source there: +

    +
    +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    + Task +

    +
    +

    + boost::math, 1 thread +

    +
    +

    + primesieve, 1 thread +

    +
    +

    + boost::math, 16 threads +

    +
    +

    + primesieve, 16 threads +

    +
    +

    + count primes below 109 +

    +
    +

    + 53 +

    +
    +

    + 51 +

    +
    + +
    +

    + count primes below 1010 +

    +
    +

    + 655 +

    +
    +

    + 640 +

    +
    +

    + 124 +

    +
    +

    + 146 +

    +
    +

    + count primes below 1011 +

    +
    + +

    + 8392 +

    +
    +

    + 1767 +

    +
    +

    + 1865 +

    +
    +

    + store primes below 109 +

    +
    +

    + 79 +

    +
    +

    + 70 +

    +
    + +
    +

    + count a 109 window at 1012 +

    +
    +

    + 128 +

    +
    +

    + 124 +

    +
    + +
    +

    + count a 109 window at 1015 +

    +
    +

    + 273 +

    +
    +

    + 224 +

    +
    + +
    +

    + count a 109 window at 1018 +

    +
    +

    + 1037 +

    +
    +

    + 796 +

    +
    + +
    +

    + Single threaded this library is 10 to 15 percent ahead on Apple silicon and + within 2 to 3 percent of primesieve on x86 for whole ranges, while primesieve + keeps a lead of 20 to 30 percent on x86 for windows at 1015 and beyond (the + bucket sieve is memory bound there and the Intel machine has a third of the + memory bandwidth). With all cores this library is ahead on both machines. + When compiled with AVX-512 VBMI2 support (-march=native on Ice Lake or Zen 4 and later) + primes are extracted from the sieve with byte compression instructions; define + BOOST_MATH_PRIME_SIEVE_NO_SIMD + to keep the portable loop. +

    +

    + Both sieves are O(n log log n) in time and use O(sqrt(n)) memory for the + sieving primes (about four bytes per prime here) plus the segment; the multithreaded + path additionally buffers at most 2 * max_threads + * chunk_primes output values. +

    +

    + The CUDA backend was measured on an NVIDIA GeForce RTX 3060 (CUDA 13.1, + nvcc -O3 -arch=sm_86) + against the same code running with std::execution::par on + that machine's Intel Core i9-11900K (8 cores, 16 threads). It stores 16 bytes + per sieving prime on the device, so ranges up to 264 +need about 3.3 GB of + device memory. +

    +
    +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    + Task +

    +
    +

    + execution::cuda, RTX 3060 +

    +
    +

    + std::execution::par, i9-11900K +

    +
    +

    + count primes below 109 +

    +
    +

    + 8 +

    +
    +

    + 11 +

    +
    +

    + count primes below 1010 +

    +
    +

    + 72 +

    +
    +

    + 136 +

    +
    +

    + count primes below 1011 +

    +
    +

    + 1077 +

    +
    +

    + 1786 +

    +
    +

    + count a 109 window at 1012 +

    +
    +

    + 13 +

    +
    +

    + 29 +

    +
    +

    + count a 109 window at 1015 +

    +
    +

    + 75 +

    +
    +

    + 136 +

    +
    +

    + count a 109 window at 1018 +

    +
    +

    + 656 +

    +
    +

    + 691 +

    +
    +

    + count a 230 window below 264 +

    +
    +

    + 2371 +

    +
    +

    + 2995 +

    +
    +

    + store primes below 1010 +

    +
    +

    + 1485 +

    +
    +

    + 430 +

    +
    +

    + Counting is where the GPU pays off; storing primes is dominated by the transfer + and compaction of the output (3.6 GB for the primes below 1010) and is faster + on the CPU. Windows near 264 are dominated by generating the 203 million sieving + primes on the host. +

    +
    + + References +
    +
    +
    + +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/math_toolkit/number_series/primes.html b/doc/html/math_toolkit/number_series/primes.html index 99392e41c0..bc7d304f94 100644 --- a/doc/html/math_toolkit/number_series/primes.html +++ b/doc/html/math_toolkit/number_series/primes.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -81,7 +81,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/oct_tests.html b/doc/html/math_toolkit/oct_tests.html index 98fa24b74a..47b738cde4 100644 --- a/doc/html/math_toolkit/oct_tests.html +++ b/doc/html/math_toolkit/oct_tests.html @@ -28,7 +28,7 @@ Test Program

    - The octonion_test.cpp test + The test_octonion.cpp test program tests octonions specialisations for float, double and long double (sample output).

    diff --git a/doc/html/math_toolkit/powers.html b/doc/html/math_toolkit/powers.html index ebcaa2babb..c8fbea6001 100644 --- a/doc/html/math_toolkit/powers.html +++ b/doc/html/math_toolkit/powers.html @@ -36,6 +36,7 @@

    sqrt1pm1
    powm1
    hypot
    +
    pow1p
    Compile Time Power of a Runtime Base
    Reciprocal square root
    diff --git a/doc/html/math_toolkit/powers/ct_pow.html b/doc/html/math_toolkit/powers/ct_pow.html index f0f2ddb441..e9ad28ec55 100644 --- a/doc/html/math_toolkit/powers/ct_pow.html +++ b/doc/html/math_toolkit/powers/ct_pow.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -267,7 +267,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/powers/hypot.html b/doc/html/math_toolkit/powers/hypot.html index 2bae0e4385..b872e098bf 100644 --- a/doc/html/math_toolkit/powers/hypot.html +++ b/doc/html/math_toolkit/powers/hypot.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -110,7 +110,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/powers/pow1p.html b/doc/html/math_toolkit/powers/pow1p.html new file mode 100644 index 0000000000..2a319d45ae --- /dev/null +++ b/doc/html/math_toolkit/powers/pow1p.html @@ -0,0 +1,109 @@ + + + +pow1p + + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    +

    +pow1p +

    +
    + + Synopsis +
    +
    #include <boost/math/special_functions/pow1p.hpp>
    +
    +namespace boost {
    +namespace math {
    +
    +template <typename T1, typename T2, typename Policy>
    +BOOST_MATH_GPU_ENABLED tools::promote_args_t<T1, T2>
    +pow1p(const T1 x, const T2 y, const Policy& pol)
    +
    +template <typename T1, typename T2>
    +BOOST_MATH_GPU_ENABLED tools::promote_args_t<T1, T2>
    +pow1p(const T1 x, const T2 y)
    +
    +}} // namespaces
    +
    +

    + The function pow1p computes + (1 + x)y where x and y are real numbers. This function is particularly useful + for scenarios where adding 1 to x before raising it to the power of y is + required. It provides a more numerically stable and efficient way to perform + this computation, especially for small values of x. When x is very small, + directly computing (1 + x)y using standard arithmetic operations can lead + to a loss of precision due to floating-point arithmetic limitations. The + pow1p function helps mitigate this issue by internally handling such cases + more accurately. +

    +

    + The type T must provide an + fma function, found either + as std::fma or by argument dependent lookup. +

    +
    + + Accuracy +
    +

    + In random testing against a 100 digit reference, the error is at most 3 ULP + for float and double, including tiny x + with huge y, where pow(1 + + x, y) loses + all precision. In the plots below, pow1p is shown in blue and pow(1 + + x, y) + in orange; red points are errors that exceed 100 ULP. +

    +

    + +

    +
    + + + + + +
    [Warning]Warning

    + pow1p relies on error-free transforms and IEEE overflow behavior. Compiling + with value-unsafe floating-point optimizations (-ffast-math, /fp:fast, + or icpx's default -fp-model=fast) + can make results for small x and large y + completely wrong. With icpx, use -fp-model=precise. +

    +
    + +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/math_toolkit/quat_tests.html b/doc/html/math_toolkit/quat_tests.html index f30408e4ba..b548b88d5f 100644 --- a/doc/html/math_toolkit/quat_tests.html +++ b/doc/html/math_toolkit/quat_tests.html @@ -28,7 +28,7 @@ Test Program

    - The quaternion_test.cpp + The test_quaternion.cpp test program tests quaternions specializations for float, double and long double (sample output, with message output enabled). diff --git a/doc/html/math_toolkit/result_type.html b/doc/html/math_toolkit/result_type.html index 752f899313..4c5b3d3f29 100644 --- a/doc/html/math_toolkit/result_type.html +++ b/doc/html/math_toolkit/result_type.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@


    -PrevUpHomeNext +PrevUpHomeNext

    @@ -177,7 +177,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/roots_deriv.html b/doc/html/math_toolkit/roots_deriv.html index 612e8dcaa3..188402001e 100644 --- a/doc/html/math_toolkit/roots_deriv.html +++ b/doc/html/math_toolkit/roots_deriv.html @@ -210,6 +210,19 @@
    starting point for digits would be 0.6*D for Newton and 0.4*D for Halley or Shröder iteration, where D is std::numeric_limits<T>::digits. +
  • + Out-of-bounds steps are assumed to have the root between the current guess + and the bound they crossed. If f(x) is not monotone + between the guess and the root (for example there is a local extremum in + the way) that assumption fails, and the iteration can end up at the bound + without f(x) ever changing sign. The implementation + attempts to detect this case: if the result has collapsed onto one end + of [min, max], f(x) never changed sign, and f(x) + at that end does not look like a root, an evaluation_error + is raised rather than returning the bound. The detection is heuristic, + so the best defence is a good initial guess, or a range [min, max] on which + f(x) is monotone. +
  • If you need some diagnostic output to see what is going on, you can #define BOOST_MATH_INSTRUMENT before the #include <boost/math/tools/roots.hpp>, and also ensure that display of all diff --git a/doc/html/math_toolkit/roots_noderiv/TOMS748.html b/doc/html/math_toolkit/roots_noderiv/TOMS748.html index 00b9714f06..8859cab16c 100644 --- a/doc/html/math_toolkit/roots_noderiv/TOMS748.html +++ b/doc/html/math_toolkit/roots_noderiv/TOMS748.html @@ -105,7 +105,7 @@ A unary functor (or C++ lambda) that is the function whose root is to be solved. f(x) need not be uniformly increasing or decreasing on x and may have multiple roots. However, the bounds - given must bracket a single root. + given must bracket at least one root.

    a

    diff --git a/doc/html/math_toolkit/sf_gamma/igamma.html b/doc/html/math_toolkit/sf_gamma/igamma.html index 1fe87286b1..93e467594e 100644 --- a/doc/html/math_toolkit/sf_gamma/igamma.html +++ b/doc/html/math_toolkit/sf_gamma/igamma.html @@ -47,6 +47,18 @@

    template <class T1, class T2, class Policy> BOOST_MATH_GPU_ENABLED calculated-result-type gamma_q(T1 a, T2 z, const Policy&); +template <class T1, class T2> +BOOST_MATH_GPU_ENABLED calculated-result-type lgamma_q(T1 a, T2 z); + +template <class T1, class T2, class Policy> +BOOST_MATH_GPU_ENABLED calculated-result-type lgamma_q(T1 a, T2 z, const Policy&); + +template <class T1, class T2> +BOOST_MATH_GPU_ENABLED calculated-result-type lgamma_p(T1 a, T2 z); + +template <class T1, class T2, class Policy> +BOOST_MATH_GPU_ENABLED calculated-result-type lgamma_p(T1 a, T2 z, const Policy&); + template <class T1, class T2> BOOST_MATH_GPU_ENABLED calculated-result-type tgamma_lower(T1 a, T2 z); @@ -109,6 +121,16 @@

  • template <class T1, class T2>
    +BOOST_MATH_GPU_ENABLED calculated-result-type lgamma_p(T1 a, T2 z);
    +
    +template <class T1, class T2, class Policy>
    +BOOST_MATH_GPU_ENABLED calculated-result-type lgamma_p(T1 a, T2 z, const Policy&);
    +
    +

    + Returns the natural log of the normalized lower incomplete gamma function + of a and z. +

    +
    template <class T1, class T2>
     BOOST_MATH_GPU_ENABLED calculated-result-type gamma_q(T1 a, T2 z);
     
     template <class T1, class T2, class Policy>
    @@ -129,6 +151,16 @@ 

    template <class T1, class T2>
    +BOOST_MATH_GPU_ENABLED calculated-result-type lgamma_q(T1 a, T2 z);
    +
    +template <class T1, class T2, class Policy>
    +BOOST_MATH_GPU_ENABLED calculated-result-type lgamma_q(T1 a, T2 z, const Policy&);
    +
    +

    + Returns the natural log of the normalized upper incomplete gamma function + of a and z. +

    +
    template <class T1, class T2>
     BOOST_MATH_GPU_ENABLED calculated-result-type tgamma_lower(T1 a, T2 z);
     
     template <class T1, class T2, class Policy>
    @@ -973,6 +1005,18 @@ 
    other methods. Use of log(1+x)-x here is inspired by Temme (see references below).

    +

    + The natural log of the normalized upper incomplete gamma function is computed + as expected except when the normalized upper incomplete gamma function begins + to underflow. This approximately occurs at +

    +
    ((x > 1000) && ((a < x) || (fabs(a - 50) / x < 1))) || ((x > log_max_value<T>() - 10) && (x > a))
    +
    +

    + in which case an expansion, for large x, of the (non-normalised) upper incomplete + gamma function is used. The return is then normalised by subtracting the + log of the gamma function and adding a log(x)-x-log(x). +

    References diff --git a/doc/html/math_toolkit/sf_gamma/polygamma.html b/doc/html/math_toolkit/sf_gamma/polygamma.html index e2eed2bf06..913a653f83 100644 --- a/doc/html/math_toolkit/sf_gamma/polygamma.html +++ b/doc/html/math_toolkit/sf_gamma/polygamma.html @@ -347,7 +347,7 @@

    The coefficients of the cosine terms can be calculated iteratively starting - from C1,0 = -1 and then using + from C0,1 = -1 and then using

    diff --git a/doc/html/math_toolkit/standalone.html b/doc/html/math_toolkit/standalone.html index 6b964fbc53..e606050804 100644 --- a/doc/html/math_toolkit/standalone.html +++ b/doc/html/math_toolkit/standalone.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@


    -PrevUpHomeNext +PrevUpHomeNext

    @@ -52,6 +52,12 @@ much mandatory. In other words, if you hit issues, try upping your compiler's conformance level to C++17 if you can.

    +

    + If you embed a standalone copy of this library inside another library, you + can also move it out of namespace boost::math so + that it cannot collide with another version of Boost.Math: see Configurable + Namespace. +

    Latest tarballs of this library can be obtained from:

    @@ -79,7 +85,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/symplectic.html b/doc/html/math_toolkit/symplectic.html new file mode 100644 index 0000000000..3d811b6cb5 --- /dev/null +++ b/doc/html/math_toolkit/symplectic.html @@ -0,0 +1,269 @@ + + + +Symplectic Integration + + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + + Synopsis +

    +
    #include <boost/math/quadrature/symmetric.hpp>
    +namespace boost{ namespace math{ namespace quadrature {
    +
    +enum class available_methods
    +{
    +    Y6,
    +    Y4,
    +    Y2,
    +    SRKNB6,
    +    SRKNB11
    +};
    +
    +template <typename RandomAccessContainer, typename RealType, class Func, class Policy>
    +std::pair<std::vector<RandomAccessContainer>, std::vector<RandomAccessContainer> > integrate_hamiltonian(RandomAccessContainer p0,
    +                                                                                                         RandomAccessContainer q0,
    +                                                                                                         const RealType dt,
    +                                                                                                         const unsigned steps,
    +                                                                                                         Func dHdp,
    +                                                                                                         Func dHdq,
    +                                                                                                         available_methods method,
    +                                                                                                         const Policy& pol)
    +
    +template <typename RandomAccessContainer, typename RealType, class Func>
    +std::pair<std::vector<RandomAccessContainer>, std::vector<RandomAccessContainer> > integrate_hamiltonian(RandomAccessContainer p0,
    +                                                                                                         RandomAccessContainer q0,
    +                                                                                                         const RealType dt,
    +                                                                                                         const unsigned steps,
    +                                                                                                         Func dHdp,
    +                                                                                                         Func dHdq,
    +                                                                                                         available_methods method)
    +
    +template <typename RandomAccessContainer, typename RealType, class Func>
    +std::pair<std::vector<RandomAccessContainer>, std::vector<RandomAccessContainer> > integrate_hamiltonian(RandomAccessContainer p0,
    +                                                                                                         RandomAccessContainer q0,
    +                                                                                                         const RealType dt,
    +                                                                                                         const unsigned steps,
    +                                                                                                         Func dHdp,
    +                                                                                                         Func dHdq)
    +
    +template <typename RandomAccessContainer, typename RealType, class Func, class Policy>
    +BOOST_MATH_EXPORT std::tuple<std::vector<RealType>, std::vector<RealType>, std::vector<RealType>, std::vector<RealType> > integrate_hamiltonian_adaptive(RandomAccessContainer p0,
    +                                                                                                                                                         RandomAccessContainer q0,
    +                                                                                                                                                         const std::pair<RealType, RealType> timeInterval,
    +                                                                                                                                                         const Func dHdp,
    +                                                                                                                                                         const Func dHdq,
    +                                                                                                                                                         const RealType atol,
    +                                                                                                                                                         const RealType rtol,
    +                                                                                                                                                         const available_methods& method,
    +                                                                                                                                                         const Policy pol)
    +template <typename RandomAccessContainer, typename RealType, class Func>
    +BOOST_MATH_EXPORT std::tuple<std::vector<RealType>, std::vector<RealType>, std::vector<RealType>, std::vector<RealType> > integrate_hamiltonian_adaptive(RandomAccessContainer p0,
    +                                                                                                                                                        RandomAccessContainer q0,
    +                                                                                                                                                        const std::pair<RealType, RealType> timeInterval,
    +                                                                                                                                                        const Func dHdp,
    +                                                                                                                                                        const Func dHdq,
    +                                                                                                                                                        const RealType atol,
    +                                                                                                                                                        const RealType rtol,
    +                                                                                                                                                        const available_methods& method)
    +
    +template <typename RandomAccessContainer, typename RealType, class Func>
    +BOOST_MATH_EXPORT std::tuple<std::vector<RealType>, std::vector<RealType>, std::vector<RealType>, std::vector<RealType> > integrate_hamiltonian_adaptive(RandomAccessContainer p0,
    +                                                                                                                                                        RandomAccessContainer q0,
    +                                                                                                                                                        const std::pair<RealType, RealType> timeInterval,
    +                                                                                                                                                        const Func dHdp,
    +                                                                                                                                                        const Func dHdq,
    +                                                                                                                                                        const RealType atol,
    +                                                                                                                                                        const RealType rtol)
    +
    +template <typename RealType, class Func, class Policy>
    +BOOST_MATH_EXPORT boost::math::interpolators::cubic_hermite<std::vector<RealType> > integrate_hamiltonian_cubic(RealType p0,
    +                                                                                                                RealType q0,
    +                                                                                                                const RealType dt,
    +                                                                                                                const unsigned steps,
    +                                                                                                                Func dHdp,
    +                                                                                                                Func dHdq,
    +                                                                                                                available_methods method,
    +                                                                                                                const Policy& pol)
    +
    +template <typename RealType, class Func>
    +BOOST_MATH_EXPORT boost::math::interpolators::cubic_hermite<std::vector<RealType> > integrate_hamiltonian_cubic(RealType p0,
    +                                                                                                                RealType q0,
    +                                                                                                                const RealType dt,
    +                                                                                                                const unsigned steps,
    +                                                                                                                Func dHdp,
    +                                                                                                                Func dHdq,
    +                                                                                                                available_methods method)
    +
    +template <typename RealType, class Func>
    +BOOST_MATH_EXPORT boost::math::interpolators::cubic_hermite<std::vector<RealType> > integrate_hamiltonian_cubic(RealType p0,
    +                                                                                                                RealType q0,
    +                                                                                                                const RealType dt,
    +                                                                                                                const unsigned steps,
    +                                                                                                                Func dHdp,
    +                                                                                                                Func dHdq)
    +}}} // namespaces
    +
    +

    + + Description +

    +

    + The above functions calculate the phase space trajectory for a given Hamiltonian. + The functional integrate_hamiltonian + integrates a multi-dimensional system given a timestep and number of steps + and returns the phase-space trajectory of (p, q) at each time. Then a Cubic Hermite spline + can be used to interpolate to any p using the derivative dp/dt = + -dH/dq. This + leads to the next functional, integrate_hamiltonian_cubic, + which integrates a 1 dimensional system given a timestep and number of steps + and returns a Cubic Hermite spline which interpolates p + to any time. Lastly, the functional integrate_hamiltonian_adaptive + integrates a multi-dimensional system to a given absolute and relative tolerance + on a given time interval, (tmin, tmax), + using an integrating controller to adjust the timestep. This function returns + the tuple (t, p, + q, error). +

    +

    + The trajectories are calculated using symplectic integration which preserves + the energy of a system. Even higher order traditional numerical integration + algorithms will gain or lose energy at long times. The functional implements + the methods in Yoshida's + landmark paper and methods by Blanes + and Moan. We assume that the Hamiltonian is separable so that it can + be written as H = + T(p) + + V(q). +

    +

    + We now give an example for a simple harmonic oscillator with the Hamiltonian +

    +

    + + +

    +

    + For simplicity we will assume k = m = + 1. Then the partial derivatives of the + Hamiltonian with respect to p + and q are +

    +
    double dHdp(double p)
    +{
    +    return p;
    +}
    +
    +double dHdq(double q)
    +{
    +    return q;
    +}
    +
    +

    + Note that the functional can be readily generalized to multiple coordinates + by changing the signature of dHdp + to +

    +
    std::vector<double> dHdp(std::vector<double> p)
    +{
    +    // calculate the partial derivatives with respect to each p_i
    +}
    +
    +

    + We then define the timestep size and number of steps of the algorithm to go + from t=0 to t=100 +

    +
    RealType dt = 0.05;
    +RealType t_end = 100;
    +unsigned int steps = t_end / dt;
    +
    +

    + Lastly, we define the initial conditions so that the oscillator starts from + rest at x=1 +

    +
    RealType q0 = 1;
    +RealType p0 = 0;
    +
    +

    + We now evolve the system using the following +

    +
    std::vector<RealType> p;
    +std::vector<RealType> q;
    +
    +std::tie(p, q) = boost::math::quadrature::integrate_hamiltonian(p0, q0, dt, steps, dHdp, dHdq, available_methods::Y6);
    +
    +

    + The ouput vectors q, + p are the position and momentum of + the system at each time. In higher dimensions the output will be a vector of + vectors. +

    +

    + The last argument that we pass to integrate_hamiltonian, + available_methods::Y6 here, sets the integration method to use. + The value Y6 stands for Yoshida's + 6th order integrator. Yoshida's 2nd and 4th order methods are also available + by passing the value Y2, or + Y4 respectively. The 4th order + and 6th order symplectic Runge-Kutta-Nystrom methods from Table 3 of Blanes + and Moan are available using the values SRKNB6 + and SRKNB11. +

    +

    + The final Policy argument is optional and can + be used to control the behaviour of the function: how it handles errors, what + level of precision to use etc. Refer to the policy documentation + for more details. +

    +

    + References: +

    +

    + Yoshida, Haruo. [`Construction of higher order symplectic integrators], Physics + Letters A, 150.5-7 (1990): 262-268. +

    +

    + Blanes, Sergio, and Per Christian Moan. [Practical + symplectic partitioned + runge–kutta and runge–kutta–nyström methods], + Journal of Computational and Applied Mathematics 142.2 (2002): 313-330. +

    +
    + +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/math_toolkit/trapezoidal.html b/doc/html/math_toolkit/trapezoidal.html index f49eac7f2b..c0471b74e9 100644 --- a/doc/html/math_toolkit/trapezoidal.html +++ b/doc/html/math_toolkit/trapezoidal.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -49,6 +49,47 @@

    + Vector- + and matrix-valued integrands +

    +

    + An additional overload accepts an explicit zero value and scalar norm: +

    +
    template<class F, class Real, class Norm>
    +auto trapezoidal(F f, Real a, Real b, const decltype(f(a))& zero, Norm norm,
    +    Real tol = boost::math::tools::root_epsilon<Real>(),
    +    std::size_t max_refinements = 12,
    +    Real* error_estimate = nullptr, Real* L1 = nullptr) -> decltype(f(a));
    +
    +

    + A policy overload accepts the same arguments without defaults, followed by + const Policy& pol. + These overloads participate only if norm(f(a)) can be + explicitly converted to Real. + Existing overloads remain unchanged. +

    +

    + Return a concrete owning vector or matrix, with dimensions matching zero. The value type needs addition, addition + assignment, unary negation, and scalar multiplication. The supplied norm controls + the successive-estimate error and L1 integral, so tolerance is measured against + tol * + L1, not independently for each entry. + For an Eigen matrix, a typical norm is [](const Matrix& m) + { return m.norm(); }. +

    +
    Matrix result = boost::math::quadrature::trapezoidal(
    +    f, a, b, zero, norm, 1e-10);
    +
    +

    + Equal bounds return zero and + set requested error and L1 outputs to zero without calling f. + Reversed bounds negate the integral and preserve nonnegative error and L1 estimates. + Invalid bounds invoke the scalar domain-error policy; if it returns, the result + is zero multiplied by its scalar + error value, and requested error and L1 outputs receive that value. +

    +

    + Description

    @@ -238,7 +279,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/math_toolkit/univariate_statistics.html b/doc/html/math_toolkit/univariate_statistics.html index 06c5738fd7..5e9515f89e 100644 --- a/doc/html/math_toolkit/univariate_statistics.html +++ b/doc/html/math_toolkit/univariate_statistics.html @@ -353,7 +353,7 @@

    four moments

    - Simultaneously computes the first four central + Simultaneously computes the mean and the second, third, and fourth central moments in a single pass through the data:

    std::vector<double> v{1,2,3,4,5};
    diff --git a/doc/html/math_toolkit/van_den_bos_unit_square.html b/doc/html/math_toolkit/van_den_bos_unit_square.html
    new file mode 100644
    index 0000000000..56ca61f325
    --- /dev/null
    +++ b/doc/html/math_toolkit/van_den_bos_unit_square.html
    @@ -0,0 +1,178 @@
    +
    +
    +
    +Van den Bos Unit-Square Quadrature
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + + Synopsis +

    +
    #include <boost/math/quadrature/van_den_bos_unit_square.hpp>
    +namespace boost { namespace math { namespace quadrature {
    +
    +template<class F>
    +auto van_den_bos_unit_square(
    +    F const& f,
    +    double tolerance,
    +    double* error_estimate = nullptr,
    +    double* L1 = nullptr,
    +    std::size_t* evaluations = nullptr);
    +
    +}}} // namespaces
    +
    +

    + + Description +

    +

    + van_den_bos_unit_square computes + an adaptive positive cubature of a real- or complex-valued function over the + reference square [0,1]^2. The integrand receives the two coordinates as separate + double arguments. +

    +

    + For a nondegenerate parallelogram with one vertex p0 and + edge vectors a and b, use the affine + map p(u,v) = p0 + + u a + v + b, where (u,v) lies in [0,1]^2. The integral + over the parallelogram is the integral of f(p0 + + u a + + v b) over the + unit square, multiplied by abs(det(a,b)). The caller must perform this mapping and + include the constant Jacobian abs(det(a,b)) in the integrand. +

    +

    + The precomputed rules contain no points on the boundary of the square, so the + routine does not evaluate the integrand at an endpoint singularity. Interior + nodes approach the boundary as the levels increase, however, so excluding the + endpoints does not by itself make an improper integral well conditioned. Singular + integrals may still require a suitable change of variables. +

    +

    + The precomputed rules form a nested hierarchy. After the first level, only + points newly introduced by the next level are evaluated. The routine requires + two consecutive adjacent-level differences to satisfy tolerance + before stopping, which avoids accepting an isolated cancellation. If the maximum + level is reached first, the last rule is returned and its difference is used + as the final error_estimate + (subject to the roundoff floor). +

    +

    + The optional L1 output is the + weighted sum of the absolute integrand values. evaluations + reports the number of function calls, including calls reused by all subsequent + levels. The supported result types are float + and double, including complex + values with float or double components. Higher-precision return types + are not supported. +

    +

    + Nodes and weights are computed offline. If the requested tolerance is not reached + by the final precomputed level, the routine returns that level's result and + error estimate; it does not compute additional levels. +

    +

    + Requires C++17. +

    +

    + Positive cubature rules satisfying the same moment conditions are not unique. + The nodes and weights of this routine are chosen on a Fejer type-II grid. The + nodes are strictly contained in (0,1)^2, and the + weighted rule is invariant under D4. +

    +

    + + Dilogarithm + example +

    +

    + For a smooth special-function example, the integral of 1/(1-xy/2) over the unit square is pi^2/6 - log^2(2). +

    +
    using boost::math::quadrature::van_den_bos_unit_square;
    +
    +double error_estimate = 0;
    +double value = van_den_bos_unit_square(
    +    [](double x, double y)
    +    {
    +        return 1 / (1 - x * y / 2);
    +    },
    +    1e-10,
    +    &error_estimate);
    +
    +

    + + Square-lattice + Green function +

    +

    + The resolvent of the nearest-neighbor square lattice gives the genuinely two-dimensional + periodic integral of 1/(z - cos(2*pi*x) - cos(2*pi*y)) over the unit square. For z > + 2, its closed form is G(z) + = 2*K(2/z)/(pi*z), where K is the complete + elliptic integral of the first kind. For example, z = 3 + can be computed with +

    +
    double const z = 3;
    +double const two_pi = 2 * boost::math::constants::pi<double>();
    +double value = van_den_bos_unit_square(
    +    [=](double x, double y)
    +    {
    +        return 1 / (z - std::cos(two_pi * x)
    +                      - std::cos(two_pi * y));
    +    },
    +    1e-6);
    +
    +

    + The lattice value z = 2, and the parameter value z + = 1 in the dilogarithm family (1-zxy)^-1, give improper + integrals. Although the rules do not evaluate the singular boundary points + themselves, singular integrands may require a suitable change of variables + and should not be expected to have reliable adjacent-level error estimates + without such treatment. +

    +

    + The construction follows the positive, nested reduction approach of van den Bos et al., adapted + here to the uniform measure on the unit square. +

    +
    + +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/math_toolkit/wavelet_transforms.html b/doc/html/math_toolkit/wavelet_transforms.html index b8922c9a62..daa6962fe5 100644 --- a/doc/html/math_toolkit/wavelet_transforms.html +++ b/doc/html/math_toolkit/wavelet_transforms.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -102,7 +102,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/overview.html b/doc/html/overview.html index 7e7e6439ba..40c92e6453 100644 --- a/doc/html/overview.html +++ b/doc/html/overview.html @@ -36,10 +36,12 @@
    Directory and File Structure
    Namespaces
    Standalone Usage
    +
    Configurable Namespace
    Calculation of the Type of the Result
    Error Handling
    Support for GPU programming in Boost.Math
    +
    Support for C++20 Modules
    Compilers
    Configuration Macros
    Policies
    diff --git a/doc/html/quadrature.html b/doc/html/quadrature.html index 9041b488ae..ea80630792 100644 --- a/doc/html/quadrature.html +++ b/doc/html/quadrature.html @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -29,9 +29,12 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/special.html b/doc/html/special.html index 543c511377..0b4711fa2a 100644 --- a/doc/html/special.html +++ b/doc/html/special.html @@ -35,6 +35,7 @@ Numbers
    Tangent Numbers
    Prime Numbers
    +
    Prime Sieve
    Fibonacci Numbers
    @@ -218,6 +219,7 @@
    sqrt1pm1
    powm1
    hypot
    +
    pow1p
    Compile Time Power of a Runtime Base
    Reciprocal square root
    diff --git a/doc/html/standalone_HTML.manifest b/doc/html/standalone_HTML.manifest index 57ce0d9d84..3ebe0e7e5f 100644 --- a/doc/html/standalone_HTML.manifest +++ b/doc/html/standalone_HTML.manifest @@ -7,9 +7,11 @@ math_toolkit/hints.html math_toolkit/directories.html math_toolkit/namespaces.html math_toolkit/standalone.html +math_toolkit/configurable_namespace.html math_toolkit/result_type.html math_toolkit/error_handling.html math_toolkit/gpu.html +math_toolkit/cxx20_modules.html math_toolkit/compilers_overview.html math_toolkit/config_macros.html math_toolkit/intro_pol_overview.html @@ -154,6 +156,7 @@ math_toolkit/dist_ref/dists/skew_normal_dist.html math_toolkit/dist_ref/dists/students_t_dist.html math_toolkit/dist_ref/dists/triangular_dist.html math_toolkit/dist_ref/dists/uniform_dist.html +math_toolkit/dist_ref/dists/von_mises_dist.html math_toolkit/dist_ref/dists/weibull_dist.html math_toolkit/dist_ref/dist_algorithms.html math_toolkit/future.html @@ -168,6 +171,7 @@ math_toolkit/runs_test.html math_toolkit/ljung_box.html math_toolkit/linear_regression.html math_toolkit/chatterjee_correlation.html +math_toolkit/chatterjee_correlation_mnn.html vector_functionals.html math_toolkit/norms.html special.html @@ -175,6 +179,7 @@ math_toolkit/number_series.html math_toolkit/number_series/bernoulli_numbers.html math_toolkit/number_series/tangent_numbers.html math_toolkit/number_series/primes.html +math_toolkit/number_series/prime_sieve.html math_toolkit/number_series/fibonacci_numbers.html math_toolkit/sf_gamma.html math_toolkit/sf_gamma/tgamma.html @@ -281,6 +286,7 @@ math_toolkit/powers/cbrt.html math_toolkit/powers/sqrt1pm1.html math_toolkit/powers/powm1.html math_toolkit/powers/hypot.html +math_toolkit/powers/pow1p.html math_toolkit/powers/ct_pow.html math_toolkit/powers/rsqrt.html math_toolkit/powers/logaddexp.html @@ -357,15 +363,18 @@ math_toolkit/pchip.html math_toolkit/quintic_hermite.html math_toolkit/bilinear_uniform.html quadrature.html +math_toolkit/van_den_bos_unit_square.html math_toolkit/trapezoidal.html math_toolkit/gauss.html math_toolkit/gauss_kronrod.html +math_toolkit/gauss_hermite.html math_toolkit/double_exponential.html math_toolkit/double_exponential/de_overview.html math_toolkit/double_exponential/de_tanh_sinh.html math_toolkit/double_exponential/de_tanh_sinh_2_arg.html math_toolkit/double_exponential/de_sinh_sinh.html math_toolkit/double_exponential/de_exp_sinh.html +math_toolkit/double_exponential/de_matrix.html math_toolkit/double_exponential/de_tol.html math_toolkit/double_exponential/de_levels.html math_toolkit/double_exponential/de_thread.html @@ -374,6 +383,7 @@ math_toolkit/double_exponential/gpu_usage.html math_toolkit/double_exponential/de_refes.html math_toolkit/fourier_integrals.html math_toolkit/naive_monte_carlo.html +math_toolkit/symplectic.html math_toolkit/wavelet_transforms.html math_toolkit/diff.html math_toolkit/autodiff.html diff --git a/doc/html/statistics.html b/doc/html/statistics.html index f341a83212..c9b2ac3846 100644 --- a/doc/html/statistics.html +++ b/doc/html/statistics.html @@ -39,6 +39,8 @@
    The Ljung-Box Test
    Linear Regression
    Chatterjee Correlation
    +
    Chatterjee Correlation + (M nearest neighbours)

    diff --git a/doc/html/vector_functionals.html b/doc/html/vector_functionals.html index 264af3effe..9e80721ddf 100644 --- a/doc/html/vector_functionals.html +++ b/doc/html/vector_functionals.html @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -42,7 +42,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/images/von_mises_ulps_cdf_4d.svg b/doc/images/von_mises_ulps_cdf_4d.svg new file mode 100644 index 0000000000..74e63c60c4 --- /dev/null +++ b/doc/images/von_mises_ulps_cdf_4d.svg @@ -0,0 +1,1048 @@ + + + + + + + +-256.8 + +-218.4 + +-180.1 + +-141.7 + +-103.3 + +-64.98 + +-26.62 + +11.74 + +-2.513 + +-1.885 + +-1.257 + +-0.6283 + +0 + +0.6283 + +1.257 + +1.885 + +2.513 + +3.142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/von_mises_ulps_cdf_64d.svg b/doc/images/von_mises_ulps_cdf_64d.svg new file mode 100644 index 0000000000..fc69f74d16 --- /dev/null +++ b/doc/images/von_mises_ulps_cdf_64d.svg @@ -0,0 +1,1048 @@ + + + + + + + +-152.6 + +-110.7 + +-68.86 + +-27 + +14.86 + +56.72 + +98.58 + +140.4 + +-2.513 + +-1.885 + +-1.257 + +-0.6283 + +0 + +0.6283 + +1.257 + +1.885 + +2.513 + +3.142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/von_mises_ulps_pdf_4d.svg b/doc/images/von_mises_ulps_pdf_4d.svg new file mode 100644 index 0000000000..ec08dc1874 --- /dev/null +++ b/doc/images/von_mises_ulps_pdf_4d.svg @@ -0,0 +1,1048 @@ + + + + + + + +-6.237 + +-3.408 + +-0.5789 + +2.25 + +5.08 + +7.909 + +10.74 + +13.57 + +-2.513 + +-1.885 + +-1.257 + +-0.6283 + +0 + +0.6283 + +1.257 + +1.885 + +2.513 + +3.142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/von_mises_ulps_pdf_64d.svg b/doc/images/von_mises_ulps_pdf_64d.svg new file mode 100644 index 0000000000..b61866e0d6 --- /dev/null +++ b/doc/images/von_mises_ulps_pdf_64d.svg @@ -0,0 +1,1048 @@ + + + + + + + +-127.8 + +-90.31 + +-52.77 + +-15.24 + +22.29 + +59.83 + +97.36 + +134.9 + +-2.513 + +-1.885 + +-1.257 + +-0.6283 + +0 + +0.6283 + +1.257 + +1.885 + +2.513 + +3.142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/internals/recurrence.qbk b/doc/internals/recurrence.qbk index e4d524e088..872127d9f7 100644 --- a/doc/internals/recurrence.qbk +++ b/doc/internals/recurrence.qbk @@ -25,6 +25,8 @@ template struct backward_recurrence_iterator; + + struct recurrence_offset; }}} // namespaces @@ -136,6 +138,8 @@ Returns F[sub n - number_of_steps]. forward_recurrence_iterator(const Recurrence& r, value_type f_n_minus_1, value_type f_n); forward_recurrence_iterator(const Recurrence& r, value_type f_n); + forward_recurrence_iterator(const Recurrence& r, value_type f_n_minus_1, value_type f_n, recurrence_offset k0); + forward_recurrence_iterator(const Recurrence& r, value_type f_n, recurrence_offset k0); /* Operators omitted for clarity */ }; @@ -150,6 +154,8 @@ only one value is provided, then the second is computed by using the recurrence backward_recurrence_iterator(const Recurrence& r, value_type f_n_plus_1, value_type f_n); backward_recurrence_iterator(const Recurrence& r, value_type f_n); + backward_recurrence_iterator(const Recurrence& r, value_type f_n_plus_1, value_type f_n, recurrence_offset k0); + backward_recurrence_iterator(const Recurrence& r, value_type f_n, recurrence_offset k0); /* Operators omitted for clarity */ }; @@ -159,6 +165,18 @@ only one value is provided, then the second is computed by using the recurrence Note that /incrementing/ this iterator moves the value returned successively to F[sub n-1], F[sub n-2] etc. + struct recurrence_offset + { + explicit recurrence_offset(int k); + int value; + }; + +By default both iterators call the recurrence functor with 0, then 1, 2, ... (forwards) or -1, -2, ... (backwards). +The constructors that take a `recurrence_offset(k0)` start from index /k0/ instead. This matters when the coefficients +depend on /v + n/ for non-integer /v/: passing the base /v/ to the functor and the integer offset to the iterator +rounds each /v + n/ once, whereas a functor constructed from the rounded /v + k0/ puts every later order out by the +error in that rounding. + [endsect] [/section:recurrence Tools For 3-Term Recurrence Relations] [/ diff --git a/doc/internals/simple_continued_fraction.qbk b/doc/internals/simple_continued_fraction.qbk index 45896ffd74..8cd0142cdd 100644 --- a/doc/internals/simple_continued_fraction.qbk +++ b/doc/internals/simple_continued_fraction.qbk @@ -19,8 +19,10 @@ Real khinchin_harmonic_mean() const; + const std::vector& partial_denominators() const; + template - friend std::ostream& operator<<(std::ostream& out, simple_continued_fraction& scf); + friend std::ostream& operator<<(std::ostream& out, const simple_continued_fraction& scf); }; } @@ -40,6 +42,36 @@ Here's a minimal working example: The class computes partial denominators while simultaneously computing convergents with the modified Lentz's algorithm. Once a convergent is within a few ulps of the input value, the computation stops. +Finite simple continued fractions are not unique: `[a0; a1, ..., an, 1]` and +`[a0; a1, ..., an + 1]` represent the same value. +The class uses the shorter, canonical representation, absorbing a trailing `1` into the preceding coefficient. +For example, `3.75` is represented as `[3; 1, 3]`, rather than `[3; 1, 2, 1]`. + +The `partial_denominators()` member function returns a read-only reference to the stored coefficients, +including the integer part at index zero: + + const auto& a = cfrac.partial_denominators(); + std::cout << a.size() << " coefficients\n"; + std::cout << a[0] << "\n"; // Integer part: 3 + std::cout << a.at(1) << "\n"; // First partial denominator: 7 + +The reference remains valid for the lifetime of `cfrac`. + +A prefix of these coefficients defines a convergent, which can be used as a rational approximation. +For example, the first four coefficients of the expansion of π give `355/113`. +With `#include `, this can be computed by evaluating the prefix backwards: + + using rational = boost::rational; + std::size_t n = 4; // Use the first four coefficients of cfrac above. + rational approximation(a.at(n - 1)); + for (std::size_t i = n - 1; i > 0; --i) { + approximation = rational(a[i - 1]) + rational(1) / approximation; + } + std::cout << approximation << "\n"; // Prints: 355/113 + +In general, choose `n` between `1` and `a.size()` and an integer type wide enough for the rational +arithmetic, including intermediate results. Longer prefixes can overflow a fixed-width integer type. + Note that every floating point number is a rational number, and this exact rational can be exactly converted to a finite continued fraction. This is perfectly sensible behavior, but we do not do it here. This is because when examining known values like π, it creates a large number of incorrect partial denominators, even if every bit of the binary representation is correct. diff --git a/doc/interpolators/cardinal_trigonometric.qbk b/doc/interpolators/cardinal_trigonometric.qbk index 9a15bd2124..43776df6bc 100644 --- a/doc/interpolators/cardinal_trigonometric.qbk +++ b/doc/interpolators/cardinal_trigonometric.qbk @@ -75,8 +75,11 @@ The graphs are visually indistinguishable at 20 samples. [heading Caveats] -This routine depends on FFTW3, and hence will only compile in float, double, long double, and quad precision, unlike the large bulk of the library which is compatible with arbitrary precision arithmetic. -The FFTW linker flags must be added to the compile step, i.e., `-lm -lfftw3` for double precision, `-lm -lfftw3f` for float, so on. +The Fourier coefficients are computed with the library's own [link math_toolkit.fft fast Fourier transform], +so `Real` may be `float`, `double`, `long double`, or a multiprecision type such as `boost::multiprecision::cpp_bin_float_50`. +With a multiprecision `Real`, also include the Boost.Multiprecision header for the matching complex type, which the transform uses internally: +`` for `cpp_bin_float`, `` for `float128`, +and `` for `mpfr_float`. Evaluation of derivatives is done by differentiation of Horner's method. As always, differentiation amplifies noise; and because some rounding error is produced by computation of the Fourier coefficients, this error is amplified by differentiation. diff --git a/doc/math.qbk b/doc/math.qbk index f48c87b88c..4182fe8149 100644 --- a/doc/math.qbk +++ b/doc/math.qbk @@ -313,6 +313,7 @@ and use the function's name as the link text.] [def __sqrt1pm1 [link math_toolkit.powers.sqrt1pm1 sqrt1pm1]] [def __rsqrt [link math_toolkit.powers.rsqrt rsqrt]] [def __powm1 [link math_toolkit.powers.powm1 powm1]] +[def __pow1p [link math_toolkit.powers.pow1p pow1p]] [def __hypot [link math_toolkit.powers.hypot hypot]] [def __pow [link math_toolkit.powers.ct_pow pow]] @@ -526,13 +527,11 @@ functions, but in reality the results returned from these functions only have meaning if an integer value is provided for the random variate argument. -The quantile function will by default return an integer result that has been -/rounded outwards/. That is to say lower quantiles (where the probability is -less than 0.5) are rounded downward, and upper quantiles (where the probability -is greater than 0.5) are rounded upwards. This behaviour -ensures that if an X% quantile is requested, then /at least/ the requested -coverage will be present in the central region, and /no more than/ -the requested coverage will be present in the tails. +The quantile function will by default return an integer result: +`quantile(dist, p)` is the smallest integer /k/ with `cdf(dist, k) >= p`, and +`quantile(complement(dist, q))` is the smallest integer /k/ with +`cdf(complement(dist, k)) <= q`. This is the `integer_round_up` policy, and +the definition R, SciPy, Julia and Mathematica use. This behaviour can be changed so that the quantile functions are rounded differently, or even return a real-valued result using @@ -559,9 +558,11 @@ and as a CD ISBN 0-9504833-2-X 978-0-9504833-2-0, Classification 519.2-dc22. [include overview/overview.qbk] [include overview/structure.qbk] [/getting about, directory and file structure.] [include overview/standalone.qbk] +[include overview/namespace.qbk] [include overview/result_type_calc.qbk] [include overview/error_handling.qbk] [include overview/gpu.qbk] +[include overview/modules.qbk] [section:compilers_overview Compilers] [compilers_overview] @@ -766,12 +767,15 @@ and as a CD ISBN 0-9504833-2-X 978-0-9504833-2-0, Classification 519.2-dc22. [endmathpart] [mathpart quadrature Quadrature and Differentiation] +[include quadrature/van_den_bos_unit_square.qbk] [include quadrature/trapezoidal.qbk] [include quadrature/gauss.qbk] [include quadrature/gauss_kronrod.qbk] +[include quadrature/gauss_hermite.qbk] [include quadrature/double_exponential.qbk] [include quadrature/ooura_fourier_integrals.qbk] [include quadrature/naive_monte_carlo.qbk] +[include quadrature/symplectic.qbk] [include quadrature/wavelet_transforms.qbk] [include differentiation/numerical_differentiation.qbk] [include differentiation/autodiff.qbk] @@ -783,6 +787,10 @@ and as a CD ISBN 0-9504833-2-X 978-0-9504833-2-0, Classification 519.2-dc22. [include filters/daubechies.qbk] [endmathpart] +[mathpart fft Fast Fourier Transform] +[include fft/fft.qbk] +[endmathpart] + [include complex/complex-tr1.qbk] [include quaternion/math-quaternion.qbk] [include octonion/math-octonion.qbk] diff --git a/doc/octonion/math-octonion.qbk b/doc/octonion/math-octonion.qbk index 2d8dcfa558..751bbf8ba2 100644 --- a/doc/octonion/math-octonion.qbk +++ b/doc/octonion/math-octonion.qbk @@ -925,7 +925,7 @@ Computes the n-th power of the octonion q. [section:oct_tests Test Program] -The [@../../test/octonion_test.cpp octonion_test.cpp] +The [@../../test/test_octonion.cpp test_octonion.cpp] test program tests octonions specialisations for float, double and long double ([@../octonion/output.txt sample output]). diff --git a/doc/optimization/differential_evolution.qbk b/doc/optimization/differential_evolution.qbk index 08ca73c51e..359127b7fa 100644 --- a/doc/optimization/differential_evolution.qbk +++ b/doc/optimization/differential_evolution.qbk @@ -104,7 +104,7 @@ So if the maximum generations is hit, the iteration stops, even if (say) a `valu [h4:examples Examples] An example use can be found [@../../example/differential_evolution.cpp here]. -More examples and API use cases can be studied in [@../../test/differential_evolution_test.cpp differential_evolution_test.cpp]. +More examples and API use cases can be studied in [@../../test/test_differential_evolution.cpp test_differential_evolution.cpp]. [h5:caveats Caveats] diff --git a/doc/overview/config_macros.qbk b/doc/overview/config_macros.qbk index 6d5e52c4cf..071fbd96bb 100644 --- a/doc/overview/config_macros.qbk +++ b/doc/overview/config_macros.qbk @@ -4,11 +4,15 @@ Almost all configuration details are set up automatically by ``. In normal use, only policy configuration macros are likely to be used. See __policy_ref. +Libraries that embed their own copy of Boost.Math may also want `BOOST_MATH_NAMESPACE_COMPONENTS`, +see [link math_toolkit.configurable_namespace Configurable Namespace]. For reference, information on Boost.Math macros used internally are described briefly below. [table Boost.Math Macros [[MACRO][Notes]] +[[`BOOST_MATH_NAMESPACE_COMPONENTS`] [Relocates the whole library from `boost::math` into a namespace of your choosing, +for example `my_lib, math` for `my_lib::math`. See [link math_toolkit.configurable_namespace Configurable Namespace].]] [[`BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS`] [Do not produce or use long double functions: this macro gets set when the platform's long double or standard library long double support is absent or buggy.]] [[`BOOST_MATH_USE_FLOAT128`][When set the numeric constants support the `__float128` data type with constants having the `Q` suffix.]] diff --git a/doc/overview/gpu.qbk b/doc/overview/gpu.qbk index 58df868a63..d08b34ae56 100644 --- a/doc/overview/gpu.qbk +++ b/doc/overview/gpu.qbk @@ -7,6 +7,16 @@ These functions will have the annotation `BOOST_MATH_GPU_ENABLED` or `BOOST_MATH Functions marked with `BOOST_MATH_GPU_ENABLED` are tested using CUDA (both NVCC and NVRTC) as well as SYCL to provide a wide range of support. Functions marked with `BOOST_MATH_CUDA_ENABLED` are few, but due to its restrictions SYCL is unsupported. +[h4 Library owned kernels] + +One facility launches its own kernels instead of being called from a user's kernel: the prime sieve +(`boost::math::prime_sieve`, `prime_range`, `prime_count`) accepts `boost::math::execution::cuda` as +its execution policy. When the translation unit is compiled by nvcc with `BOOST_MATH_ENABLE_CUDA` +defined, the header `` defines +`BOOST_MATH_HAS_CUDA_PRIME_SIEVE` and sieves the requested range on the device, managing the device +memory and the kernel launches itself. Without nvcc the same call runs on the CPU. See the prime sieve +documentation for details and measurements. + [h4 Policies] The default policy on all devices is ignore error due to the lack of throwing ability. diff --git a/doc/overview/modules.qbk b/doc/overview/modules.qbk new file mode 100644 index 0000000000..8fe6cbcf82 --- /dev/null +++ b/doc/overview/modules.qbk @@ -0,0 +1,57 @@ +[section:cxx20_modules Support for C++20 Modules] + +[h4 C++20 Modules Support] + +Boost.Math can be consumed as the named module `boost.math`. +The module covers the public interface of the library: special functions, statistical distributions, constants, policies, ccmath, the public tools (root finding, minima, polynomials, rational and series evaluation, norms, condition numbers and friends), quadrature, the modern interpolators, statistics, optimization, differentiation (autodiff, finite differences and Lanczos smoothing), the complex inverse trigonometric functions, and the quaternion and octonion types. + + import boost.math; + + int main() + { + return boost::math::cdf(boost::math::normal_distribution<>(), 0.0) == 0.5 ? 0 : 1; + } + +Module support is completely inert unless the module is built and consumed explicitly: nothing changes for existing header users. + +[h4 How to build] + +The module is consumable from C++20 onward. +The interface unit lives in `libs/math/module/math.cppm` and builds with any toolchain that provides the standard library module (`import std`); the standard library maintainers agreed to make `import std` available in C++20 mode as well as C++23, so a C++23 compilation mode is not required. +CI exercises two configurations, both with CMake 4.4, Ninja and the matching `CMAKE_EXPERIMENTAL_CXX_IMPORT_STD` UUID: clang 20 with libc++ runs the full module test suite, and GCC 15 with libstdc++ builds the module and runs the quick test (libstdc++ cannot yet mix the textual standard library includes used by the wider test sources with `import std` in the same translation unit). +From a Boost superproject checkout: + + cmake -G Ninja -DBOOST_INCLUDE_LIBRARIES=math -DBUILD_TESTING=ON \ + -DBOOST_MATH_BUILD_MODULE=ON \ + -DCMAKE_CXX_COMPILER=clang++-20 \ + -DCMAKE_CXX_FLAGS="-stdlib=libc++ -Wno-reserved-module-identifier" \ + -DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD= \ + -DCMAKE_CXX_STDLIB_MODULES_JSON=/usr/lib/llvm-20/lib/libc++.modules.json .. + cmake --build . --target tests + ctest + +The module test suite reuses a curated subset of the regular test files, which switch from textual inclusion to `import boost.math;` when `BOOST_MATH_BUILD_MODULE` is defined. +The `cmake-module-test` job in the library's CI runs this configuration on every commit. + +[h4 Limitations] + +* The module is always built in standalone mode, so it has no dependencies on other Boost libraries. +* Macros do not cross module boundaries. + The policy configuration macros (`BOOST_MATH_DOMAIN_ERROR_POLICY` and friends) and the convenience macros `BOOST_MATH_DECLARE_DISTRIBUTIONS` and `BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS` therefore have no effect on an importing translation unit. + Configure policies at the call site with `boost::math::policies::make_policy` or a `policy<...>` type instead; those interfaces are fully available through the import. +* The `user_error` policy is not supported through the module, because a user supplied `boost::math::policies::user_..._error` definition cannot attach to the module. +* A program should consume Boost.Math either through the module or through textual includes, not both. + The only headers that are safe to include textually alongside the import are `boost/math/tools/config.hpp` and `boost/math/tools/assert.hpp`, which the test support headers rely on. +* Excluded from the module: the TR1/C99 interfaces and `common_factor` headers, `boost/math/bindings`, `boost/math/concepts`, `boost/math/cstdfloat`, all deprecated headers, and `optimization/cma_es.hpp`, which requires Eigen. + These remain available as ordinary includes. +* `__float128` support (`BOOST_MATH_USE_FLOAT128`) is not enabled in the module build. +* On libc++ the parallel execution policy overloads in statistics compile out (no `` support), matching the ordinary header behavior on that standard library. + +[endsect] [/section:cxx20_modules Support for C++20 Modules] + +[/ + Copyright 2026 Matt Borland. + 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). +] diff --git a/doc/overview/namespace.qbk b/doc/overview/namespace.qbk new file mode 100644 index 0000000000..f8824fd022 --- /dev/null +++ b/doc/overview/namespace.qbk @@ -0,0 +1,115 @@ +[section:configurable_namespace Configurable Namespace] + +[h4 Overview] + +By default every entity in Boost.Math lives in namespace `boost::math`. +Defining the macro `BOOST_MATH_NAMESPACE_COMPONENTS` relocates the whole library into a namespace of your choosing. +This is intended for libraries that embed their own copy of Boost.Math (typically in [link math_toolkit.standalone standalone mode]): +moving the copy out of `boost::math` means it can never collide with a different version of Boost.Math that the +end user also compiles or links against, whether as duplicate symbols in a static library or as an ODR violation. + + #define BOOST_MATH_NAMESPACE_COMPONENTS my_lib, math + #include + + int main() + { + double x = my_lib::math::tgamma(5.0); // 24 + double y = BOOST_MATH_NAMESPACE::tgamma(5.0); // the same function + return x == y ? 0 : 1; + } + +Nothing changes unless the macro is defined: the default configuration produces exactly the same code as before. + +[h4 Configuring the namespace] + +`BOOST_MATH_NAMESPACE_COMPONENTS` is a comma separated list of between one and five identifiers, outermost first. +The default is `boost, math`. Some examples: + +[table Example configurations +[[`BOOST_MATH_NAMESPACE_COMPONENTS`][Library namespace]] +[[`boost, math` (default)][`::boost::math`]] +[[`my_lib, math`][`::my_lib::math`]] +[[`_Math`][`::_Math`]] +[[`my_company, third_party, math`][`::my_company::third_party::math`]] +] + +The namespace is given as a list of components rather than as a qualified name such as `my_lib::math`, because the +preprocessor cannot split a qualified name into its parts, and C++14 (the oldest standard the library supports) has no +nested namespace definitions. + +The macro must be defined before the first Boost.Math header is included. +In a project with more than one translation unit, set it in the build system so that every translation unit sees the same value: + + g++ -DBOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math ... + cl /DBOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math ... + + # CMake + target_compile_definitions(my_target PRIVATE BOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math) + +[h4 Macros] + +`` derives the following macros from `BOOST_MATH_NAMESPACE_COMPONENTS`. +They are always defined, so code that uses them works with any configuration, including the default one. +Defining any of them yourself is a compile time error. + +[table Derived macros +[[Macro][Default expansion][Description]] +[[`BOOST_MATH_NAMESPACE`][`boost::math`][The qualified name of the library namespace, for example `::BOOST_MATH_NAMESPACE::tgamma(x)` +or `namespace bm = BOOST_MATH_NAMESPACE;`.]] +[[`BOOST_MATH_NAMESPACE_BEGIN`][`namespace boost { namespace math {`][Opens the library namespace. Use it only at global namespace scope.]] +[[`BOOST_MATH_NAMESPACE_END`][`}}`][Closes the namespace opened by `BOOST_MATH_NAMESPACE_BEGIN`.]] +[[`BOOST_MATH_NAMESPACE_LEVELS`][`2`][The number of components, as an integer literal that can be tested with `#if`.]] +[[`BOOST_MATH_DETAIL_NAMESPACE`][`boost::math_detail`][A sibling of the library namespace, formed by appending `_detail` to the +innermost component, which holds the few internal helpers that must not be enclosed by the library namespace. +`BOOST_MATH_DETAIL_NAMESPACE_BEGIN` and `BOOST_MATH_DETAIL_NAMESPACE_END` open and close it. User code should never need these.]] +] + +[h4 Code that extends the library] + +Anything you declare inside the library namespace must follow it when it moves. +The usual case is the [link math_toolkit.pol_ref.error_handling_policies user_error policy], whose handlers you define +inside the policies namespace. Writing them with the macros keeps them correct for every configuration: + + BOOST_MATH_NAMESPACE_BEGIN + namespace policies { + + template + T user_domain_error(const char* function, const char* message, const T& val) + { + // ... + } + + } // namespace policies + BOOST_MATH_NAMESPACE_END + +The same applies to anything else you previously wrote in `namespace boost { namespace math {`, such as specializations of library templates. +The convenience macros `BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS` and `BOOST_MATH_DECLARE_DISTRIBUTIONS` work unchanged in any configuration. + +[h4 Limitations] + +* Only C++ names move. Header paths, include guards and macro names stay the same, so a single translation unit can + contain only one configuration of the library. Different translation units, or different libraries linked into the same + program, may each use a different namespace: that is the purpose of the feature. +* Every translation unit that shares one copy of the library must use the same `BOOST_MATH_NAMESPACE_COMPONENTS`. +* Libraries that call Boost.Math by its default name are not affected by the macro and will not find a relocated copy. + This includes other Boost libraries that use Boost.Math internally, such as Boost.Multiprecision, so relocation is + intended for a self contained copy of Boost.Math. +* The messages carried by exceptions and error handlers still name the function as `boost::math::...`. +* The fixed width floating point typedefs of [link math_toolkit.specified_typedefs ``] + (`boost::float64_t` and friends) are not part of `boost::math` and stay in namespace `boost`. +* The [link math_toolkit.cxx20_modules C++20 module] is built and tested with the default namespace only. + +[h4 Testing] + +The library's continuous integration builds every public header, plus a runtime test, with +`BOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math`. It checks that nothing is left in `boost::math` and that no symbol in the +resulting binary is in namespace `boost`. See `libs/math/test/cmake_namespace_test`. + +[endsect] [/section:configurable_namespace Configurable Namespace] + +[/ + Copyright 2026 Matt Borland. + 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). +] diff --git a/doc/overview/roadmap.qbk b/doc/overview/roadmap.qbk index 4f356ea5e4..77fa973e0f 100644 --- a/doc/overview/roadmap.qbk +++ b/doc/overview/roadmap.qbk @@ -8,6 +8,23 @@ All old bug reports including closed ones can be viewed on Trac Recent issues on GitHub [@https://github.com/boostorg/math/issues?utf8=%E2%9C%93&q=is%3Aissue here]. +[h4 Unreleased] + +* [*Breaking change:] `double` arguments are no longer promoted to `long double` internally by default +(`BOOST_MATH_PROMOTE_DOUBLE_POLICY` now defaults to `false` on all platforms), see +[@https://github.com/boostorg/math/issues/1211 1211]. `long double` is x87 on x86 and software emulated on +AArch64 Linux, so promotion was slow, but results for `double` may now differ in the last few bits. +To restore the old behavior define `BOOST_MATH_PROMOTE_DOUBLE_POLICY` as `true`, or pass `promote_double` in a policy. +* [*Breaking change:] the quantiles of discrete distributions now default to `integer_round_up` +(`BOOST_MATH_DISCRETE_QUANTILE_POLICY` used to default to `integer_round_outwards`), see +[@https://github.com/boostorg/math/issues/1203 1203]. `quantile(dist, p)` is now the smallest /k/ with `cdf(dist, k) >= p`, +and `quantile(complement(dist, q))` the smallest /k/ with `cdf(complement(dist, k)) <= q`, as in R, SciPy, Julia and Mathematica. +Lower quantiles (p < 0.5) are therefore often one larger than before. The geometric distribution now rounds its quantile +as the policy asks (it used to return a real value whatever the policy), and the hypergeometric quantile now returns +/k/ when p is exactly `cdf(dist, k)`. To restore the old behavior define `BOOST_MATH_DISCRETE_QUANTILE_POLICY` as +`integer_round_outwards`, or pass `discrete_quantile` in a policy (with `discrete_quantile` +for the old geometric results). + [h4 Math-4.2.1 (Boost-1.86)] * Correct Bessel function results at infinity, see [@https://github.com/boostorg/math/issues/1143 1143]. @@ -17,6 +34,7 @@ Recent issues on GitHub [@https://github.com/boostorg/math/issues?utf8=%E2%9C%93 * Add improvement to Heuman Lambda precision. * Improve Skew Normal root finding, see [@https://github.com/boostorg/math/issues/1120 1120]. * Lots of minor fixes and improved code coverage. +* Add support for the M nearest-neighbour Chatterjee correlation of Lin and Han (2021), see [@https://github.com/boostorg/math/issues/990 990]. [h4 Math-4.2.0 (Boost-1.85)] diff --git a/doc/overview/standalone.qbk b/doc/overview/standalone.qbk index 9eb21faba5..2137b82cec 100644 --- a/doc/overview/standalone.qbk +++ b/doc/overview/standalone.qbk @@ -11,6 +11,9 @@ which would otherwise be detected by Boost.Config. In addition, if you use a se later C++ standards, then support for that later standard version becomes pretty much mandatory. In other words, if you hit issues, try upping your compiler's conformance level to C++17 if you can. +If you embed a standalone copy of this library inside another library, you can also move it out of namespace `boost::math` +so that it cannot collide with another version of Boost.Math: see [link math_toolkit.configurable_namespace Configurable Namespace]. + Latest tarballs of this library can be obtained from: Latest [@https://github.com/boostorg/math/releases official releases] (including full Boost releases). diff --git a/doc/overview/structure.qbk b/doc/overview/structure.qbk index 1cd72b441d..a0523f44cd 100644 --- a/doc/overview/structure.qbk +++ b/doc/overview/structure.qbk @@ -156,6 +156,8 @@ that conform to the requirements specified by `real_concept`.]] [section:namespaces Namespaces] All math functions and distributions are in `namespace boost::math`. +Libraries that embed their own copy of Boost.Math can move it into a different namespace, +see [link math_toolkit.configurable_namespace Configurable Namespace]. So, for example, the Students-t distribution template in `namespace boost::math` is diff --git a/doc/performance/performance.qbk b/doc/performance/performance.qbk index 015cf20b88..9903850009 100644 --- a/doc/performance/performance.qbk +++ b/doc/performance/performance.qbk @@ -51,19 +51,22 @@ improvement in performance, as does switching to a different compiler There are a number of [link policy Policies] that can be used to trade accuracy for performance: * Internal promotion: by default functions with `float` arguments are evaluated at `double` precision -internally to ensure full precision in the result. Similarly `double` precision functions are -evaluated at `long double` precision internally by default. Changing these defaults can have a significant +internally to ensure full precision in the result. `double` precision functions are evaluated at `double` +precision by default (older releases promoted them to `long double`, which is slow on x86 and very slow +where `long double` is software emulated). Changing the `float` default can have a significant speed advantage at the expense of accuracy, note also that evaluating using `float` internally may result in numerical instability for some of the more complex algorithms, we suggest you use this option with care. +Defining `BOOST_MATH_PROMOTE_DOUBLE_POLICY` as `true` turns promotion of `double` on again for the extra accuracy. * Target accuracy: just because you choose to evaluate at `double` precision doesn't mean you necessarily want to target full 16-digit accuracy, if you wish you can change the default (full machine precision) to whatever is "good enough" for your particular use case. -For example, suppose you want to evaluate `double` precision functions at `double` precision internally, you -can change the global default by passing `-DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false` on the command line, or -at the point of call via something like this: +For example, suppose you want `float` precision functions to be evaluated at `float` precision internally, you +can change the global default by passing `-DBOOST_MATH_PROMOTE_FLOAT_POLICY=false` on the command line. +Likewise, to get the extra accuracy of `long double` for `double` functions, pass `-DBOOST_MATH_PROMOTE_DOUBLE_POLICY=true`. +Either can also be selected at the point of call via something like this: - double val = boost::math::erf(my_argument, boost::math::policies::make_policy(boost::math::policies::promote_double())); + double val = boost::math::erf(my_argument, boost::math::policies::make_policy(boost::math::policies::promote_double())); However, an easier option might be: @@ -73,10 +76,10 @@ However, an easier option might be: namespace precise{ // - // Define a Policy for accurate evaluation - this is the same as the default, unless - // someone has changed the global defaults. + // Define a Policy for accurate evaluation - double is evaluated internally at + // long double precision (the default evaluates double at double precision): // - typedef boost::math::policies::policy<> accurate_policy; + typedef boost::math::policies::policy > accurate_policy; // // Invoke BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS to declare // functions that use the above policy. Note no trailing @@ -91,7 +94,7 @@ However, an easier option might be: // // Define a Policy for fast evaluation: // - using namespace boost::math::policies[ + using namespace boost::math::policies; typedef policy > fast_policy; // // Invoke BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS: diff --git a/doc/policies/policy.qbk b/doc/policies/policy.qbk index 984e6281e3..921b4cd18d 100644 --- a/doc/policies/policy.qbk +++ b/doc/policies/policy.qbk @@ -242,7 +242,7 @@ control whether internal promotion to a higher precision floating-point type tak precision internally: defaults to `boost::math::policies::promote_float`]] [[`boost::math::policies::promote_double`] [Indicates whether `double` arguments should be promoted to `long double` - precision internally: defaults to `boost::math::policies::promote_double`]] + precision internally: defaults to `boost::math::policies::promote_double`]] ] [h4 Examples] @@ -325,10 +325,10 @@ discrete quantiles work, and how integer results are rounded: enum discrete_quantile_policy_type { real, - integer_round_outwards, // default + integer_round_outwards, integer_round_inwards, integer_round_down, - integer_round_up, + integer_round_up, // default integer_round_nearest }; @@ -349,7 +349,7 @@ Results in `x = 27.3898` and `y = 68.1584`. [h5 integer_round_outwards] -This is the default policy: an integer value is returned so that: +An integer value is returned so that: * Lower quantiles (where the probability is less than 0.5) are rounded down. @@ -399,12 +399,28 @@ and also ['at least 5% coverage in each tail]. [h5 integer_round_down] Always rounds down to an integer value, no matter whether it's an upper -or a lower quantile. +or a lower quantile: `quantile(dist, p)` is the largest integer /k/ with +`cdf(dist, k) <= p`, and `quantile(complement(dist, q))` the largest /k/ with +`cdf(complement(dist, k)) >= q`. [h5 integer_round_up] -Always rounds up to an integer value, no matter whether it's an upper -or a lower quantile. +This is the default policy. It always rounds up to an integer value, no matter whether it's an upper +or a lower quantile: `quantile(dist, p)` is the smallest integer /k/ with +`cdf(dist, k) >= p`, and `quantile(complement(dist, q))` the smallest /k/ with +`cdf(complement(dist, k)) <= q`. This is the usual definition of the quantile +of a discrete distribution, and the one R, SciPy, Julia and Mathematica use. +For example the 5% and 95% quantiles of `binomial(50, 0.5)` are +19 and 31: `cdf(binomial(50, 0.5), 18) < 0.05 <= cdf(binomial(50, 0.5), 19)` +and `cdf(binomial(50, 0.5), 30) < 0.95 <= cdf(binomial(50, 0.5), 31)`. + +All of the discrete distributions (binomial, negative binomial, Poisson, +geometric, hypergeometric and Bernoulli) settle the answer on the cdf at +integers, so `quantile(dist, cdf(dist, k)) == k` +and `quantile(complement(dist, cdf(complement(dist, k)))) == k`, except where +the cdf rounds to the same value at consecutive integers (then the smallest of +them is returned), and except that `p == 1` (or `q == 0`) gives the end of the +support for distributions that have one, since only there is the cdf exactly 1. [h5 integer_round_nearest] @@ -587,8 +603,10 @@ to `true`, but can be set to `false` to turn promotion of Determines whether `double` types get promoted to `long double` internally to ensure maximum precision in the result, defaults -to `true`, but can be set to `false` to turn promotion of -`double`'s off. +to `false` (it defaulted to `true` in releases before the change +described in the revision history), but can be set to `true` to turn promotion of +`double`'s on. Promotion is slow on most platforms: `long double` is x87 on x86 +and is software emulated on AArch64 Linux. [h5 BOOST_MATH_DISCRETE_QUANTILE_POLICY] @@ -596,7 +614,7 @@ Determines how discrete quantiles return their results: either as an integer, or as a real value, can be set to one of the enumerated values: `real`, `integer_round_outwards`, `integer_round_inwards`, `integer_round_down`, `integer_round_up`, `integer_round_nearest`. Defaults to -`integer_round_outwards`. +`integer_round_up`. [h5 BOOST_MATH_ASSERT_UNDEFINED_POLICY] @@ -826,7 +844,7 @@ which in turn inherits from `std::integral_constant`. policy<...>::promote_double_type Specifies whether or not to promote `double` arguments to `long double` precision -internally. Will be an instance of `boost::math::policies::promote_float` +internally (the default is not to). Will be an instance of `boost::math::policies::promote_float` which in turn inherits from `std::integral_constant`. policy<...>::discrete_quantile_type diff --git a/doc/policies/policy_tutorial.qbk b/doc/policies/policy_tutorial.qbk index f44e9d6eef..72d69617eb 100644 --- a/doc/policies/policy_tutorial.qbk +++ b/doc/policies/policy_tutorial.qbk @@ -64,13 +64,11 @@ if these work OK for you then you can stop reading now!] will result in the lowest level of error for the type of the result.]] [[Behaviour of Discrete Quantiles] [ - The quantile function will by default return an integer result that has been - /rounded outwards/. That is to say lower quantiles (where the probability is - less than 0.5) are rounded downward, and upper quantiles (where the probability - is greater than 0.5) are rounded upwards. This behaviour - ensures that if an X% quantile is requested, then /at least/ the requested - coverage will be present in the central region, and /no more than/ - the requested coverage will be present in the tails. + The quantile function will by default return an integer result: +`quantile(dist, p)` is the smallest integer /k/ with `cdf(dist, k) >= p`, and +`quantile(complement(dist, q))` is the smallest integer /k/ with +`cdf(complement(dist, k)) <= q`. This is the `integer_round_up` policy, and +the definition R, SciPy, Julia and Mathematica use. This behaviour can be changed so that the quantile functions are rounded differently, or even return a real-valued result using @@ -400,33 +398,61 @@ still leaves the question: ['What is actually the right thing to do?] And in particular: ['What policy should we use by default?] -In coming to an answer we should realise that: +Calculating an integer result is often much faster than calculating a +real-valued result (in our tests it was up to 20 times faster), and the +random variable can only take integer values anyway, so the default is an +integer. Which integer? The usual definition of the quantile of a discrete +distribution is the smallest value /k/ for which `cdf(dist, k) >= p`. It is +what R, SciPy, Julia and Mathematica return, it is the empirical quantile of a +large sample, and it is the default here: the `integer_round_up` policy. In +the example above the result is 19, since: -* Calculating an integer result is often much faster than -calculating a real-valued result: in fact in our tests it -was up to 20 times faster. -* Normally people calculate quantiles so that they can perform -a test of some kind: ['"If the random variable is less than N -then we can reject our null-hypothesis with 90% confidence."] + cdf(binomial(50, 0.5), 18) < 0.05 <= cdf(binomial(50, 0.5), 19) -So there is a genuine benefit to calculating an integer result -as well as it being "the right thing to do" from a philosophical -point of view. What's more if someone asks for a quantile at 0.05, -then we can normally assume that they are asking for -['[*at least] 95% of the probability to the right of the value chosen, -and [*no more than] 5% of the probability to the left of the value chosen.] +Upper quantiles are best found from the complement: +`quantile(complement(dist, q))` is the smallest /k/ for which +`cdf(complement(dist, k)) <= q`, that is, for which the probability of a +value greater than /k/ is at most /q/. This is `quantile(dist, 1 - q)` +without the rounding error in `1 - q`, which matters when /q/ is small. For +example: -In the above binomial example we would therefore round the result down to 18. + quantile(complement(binomial(50, 0.5), 0.05)); -The converse applies to upper-quantiles: If the probability is greater than -0.5 we would want to round the quantile up, ['so that [*at least] the requested -probability is to the left of the value returned, and [*no more than] 1 - the -requested probability is to the right of the value returned.] +returns 31, since: -Likewise for two-sided intervals, we would round lower quantiles down, -and upper quantiles up. This ensures that we have ['at least the requested -probability in the central region] and ['no more than 1 minus the requested -probability in the tail areas.] + cdf(complement(binomial(50, 0.5), 30)) > 0.05 >= cdf(complement(binomial(50, 0.5), 31)) + +Together these give a two-sided interval. If L and U are the lower and upper +quantiles, then less than 5% of the probability lies below L and no more than +5% above U, so /at least/ 90% lies in the central region: + + L <= X && X <= U + +and we would reject the null hypothesis if: + + X < L || X > U + +The moral here is to ['always be very careful with your comparisons +when dealing with a discrete distribution], and if in doubt, +['base your comparisons on CDF's instead]. + +[heading Rounding Outwards] + +The `integer_round_outwards` policy, which you can select by defining +`BOOST_MATH_DISCRETE_QUANTILE_POLICY` as `integer_round_outwards` (see +[link math_toolkit.pol_ref.policy_defaults Using Macros to Change the Policy Defaults]) +or by using the policy directly, rounds lower quantiles (probability less than 0.5) down and upper +quantiles (probability greater than 0.5) up. The reasoning is that if someone +asks for a quantile at 0.05, then we can normally assume that they are asking +for ['[*at least] 95% of the probability to the right of the value chosen, +and [*no more than] 5% of the probability to the left of the value chosen], +counting the value chosen as part of the left tail. + +In the above binomial example the 0.05 quantile is then rounded down to 18. +The converse applies to upper-quantiles: they are rounded up, +['so that [*at least] the requested probability is to the left of the value +returned, and [*no more than] 1 - the requested probability is to the right +of the value returned.] For example, taking our 50 sample binomial distribution with a success fraction of 0.5, if we wanted a two sided 90% confidence interval, then we would ask @@ -435,12 +461,11 @@ for the 0.05 and 0.95 quantiles with the results ['rounded outwards] so that [$../graphs/binomial_pdf_3.png] -So far so good, but there is in fact a trap waiting for the unwary here: +With this policy: quantile(binomial(50, 0.5), 0.05); -returns 18 as the result, which is what we would expect from the graph above, -and indeed there is no x greater than 18 for which: +returns 18, and there is no x greater than 18 for which: cdf(binomial(50, 0.5), x) <= 0.05; @@ -448,7 +473,7 @@ However: quantile(binomial(50, 0.5), 0.95); -returns 31, and indeed while there is no x less than 31 for which: +returns 31, and there is no x less than 31 for which: cdf(binomial(50, 0.5), x) >= 0.95; @@ -457,13 +482,6 @@ would be 32 (since 32 = 50 - 18), but we need to remember that the cdf of the binomial is /inclusive/ of the random variable. So while the left tail area /includes/ the quantile returned, the right tail area always excludes an upper quantile value: since that "belongs" to the central area. - -Look at the graph above to see what's going on here: the lower quantile -of 18 belongs to the left tail, so any value <= 18 is in the left tail. -The upper quantile of 31 on the other hand belongs to the central area, -so the tail area actually starts at 32, so any value > 31 is in the -right tail. - Therefore if U and L are the upper and lower quantiles respectively, then a random variable X is in the tail area - where we would reject the null hypothesis if: @@ -474,9 +492,10 @@ And the a variable X is inside the central region if: L < X <= U -The moral here is to ['always be very careful with your comparisons -when dealing with a discrete distribution], and if in doubt, -['base your comparisons on CDF's instead]. +Unless the lower probability is exactly the cdf at some integer, this is the +same region as the default gives: only the lower end is reported one lower. Note also that the result jumps at a probability of 0.5, where the +rounding changes direction, so (for example) the quantiles of uniformly spaced +probabilities are not spread evenly around the median. [heading Other Rounding Policies are Available] @@ -486,7 +505,7 @@ to know that other rounding options are available: [variablelist [[integer_round_outwards] - [This is the default policy as described above: lower quantiles + [As described above: lower quantiles are rounded down (probability < 0.5), and upper quantiles (probability > 0.5) are rounded up. @@ -494,7 +513,7 @@ to know that other rounding options are available: in the tails, and /at least/ the requested probability in the central area.]] [[integer_round_inwards] - [This is the exact opposite of the default policy: + [This is the exact opposite of `integer_round_outwards`: lower quantiles are rounded up (probability < 0.5), and upper quantiles (probability > 0.5) are rounded down. @@ -503,9 +522,11 @@ to know that other rounding options are available: in the tails, and /no more than/ the requested probability in the central area.]] [[integer_round_down][This policy will always round the result down - no matter whether it is an upper or lower quantile]] -[[integer_round_up][This policy will always round the result up - no matter whether it is an upper or lower quantile]] + no matter whether it is an upper or lower quantile, giving the largest /k/ + with `cdf(dist, k) <= p` (or `cdf(complement(dist, k)) >= q`)]] +[[integer_round_up][This is the default policy: it will always round the result up + no matter whether it is an upper or lower quantile, giving the smallest /k/ + with `cdf(dist, k) >= p` (or `cdf(complement(dist, k)) <= q`)]] [[integer_round_nearest][This policy will always round the result to the nearest integer no matter whether it is an upper or lower quantile]] diff --git a/doc/quadrature/double_exponential.qbk b/doc/quadrature/double_exponential.qbk index 2959b94cd3..cb0a779901 100644 --- a/doc/quadrature/double_exponential.qbk +++ b/doc/quadrature/double_exponential.qbk @@ -380,6 +380,64 @@ check we end up with `0 * Infinity` as the result (a NaN). [endsect] [/section:de_exp_sinh exp_sinh] +[section:de_matrix Vector- and matrix-valued integrands] + +The CPU `exp_sinh`, `sinh_sinh`, and `tanh_sinh` classes also accept an explicit +additive identity and scalar norm. Insert `zero, norm` after the bounds, or after +`f` when using the default domain: + + integrator.integrate(f, zero, norm, tolerance, &error, &L1, &levels); + integrator.integrate(f, a, b, zero, norm, tolerance, &error, &L1, &levels); + +The bounded form is available for `exp_sinh` and `tanh_sinh`; `sinh_sinh` always +integrates over the whole real line. Arguments after `norm` retain their existing +defaults. The new overloads participate only if applying `norm` to the integrand's +result can be explicitly converted to `Real`. Existing overloads remain unchanged. + +For example, using Eigen with exp-sinh: + + using Matrix = Eigen::Matrix, 2, 2>; + Matrix zero = Matrix::Zero(); + auto f = [](double x) -> Matrix { + Matrix result; + result << std::exp(-x), 0., 0., std::exp(-2*x); + return result; + }; + auto norm = [](const Matrix& m) { return m.stableNorm(); }; + boost::math::quadrature::exp_sinh integrator; + Matrix result = integrator.integrate(f, zero, norm); + +Return concrete owning values, with dimensions matching `zero`, rather than +expression templates referencing temporary values. The value type must support +addition, addition assignment, unary negation, scalar multiplication on either +side, and multiplication assignment by a scalar. The norm must be nonnegative, +vanish only at zero, and return a scalar convertible to `Real`. It should also +report non-finite values for non-finite inputs; endpoint checks use this property. +A norm implementation that avoids intermediate overflow and underflow is useful +for the large dynamic ranges encountered near endpoints. + +The selected norm is used for successive-estimate errors, the L1 integral, +tail truncation, and checks for non-finite values. Convergence compares the error +with `tolerance * L1`; it does not impose a separate relative tolerance on every +entry. Error estimates are not rigorous bounds, and exhausting refinement levels +does not guarantee that the requested tolerance was reached. + +Both forms of the two-argument tanh-sinh integrand are supported: `f(x, xc)` may +return a matrix, while `x` and the signed endpoint distance `xc` remain scalars. +For the new bounded tanh-sinh overloads, equal bounds return `zero` and set requested +error, L1, and level outputs to zero without calling `f`. Reversed finite bounds +negate the integral; the two-argument functor receives distances for the endpoints +in increasing order. Exp-sinh retains its requirement for a half-infinite domain. + +Domain errors use the scalar policy. If it returns, the result is `zero` times +its scalar error value; requested error and L1 outputs receive that value, and +levels is set to zero. Evaluation-error policies receive the scalar norm of the +problematic value; a non-throwing evaluation policy returns that concrete value +or current estimate, as appropriate. Diagnostic outputs are not specified after +an evaluation error. GPU free-function interfaces are unchanged. + +[endsect] + [section:de_tol Setting the Termination Condition for Integration] The integrate method for all three double-exponential quadratures supports ['tolerance] argument that acts as the diff --git a/doc/quadrature/gauss.qbk b/doc/quadrature/gauss.qbk index e2bdd6b478..2da438bbd2 100644 --- a/doc/quadrature/gauss.qbk +++ b/doc/quadrature/gauss.qbk @@ -85,6 +85,53 @@ so it can be effectively computed via Gaussian quadrature using the following co Complex W = integrator.integrate(lw, (Real) 0, pi()); +[heading Vector- and matrix-valued integrands] + +Additional overloads accept an explicit additive identity and a scalar-valued norm: + + template + static auto integrate(F f, const decltype(f(Real(0)))& zero, Norm norm, + Real* pL1 = nullptr) -> decltype(f(Real(0))); + + template + static auto integrate(F f, Real a, Real b, + const decltype(f(Real(0)))& zero, Norm norm, + Real* pL1 = nullptr) -> decltype(f(Real(0))); + +These overloads participate in overload resolution only when `norm(f(Real(0)))` +is convertible to `Real` by an explicit cast. Existing overloads are unchanged. + +The integrand must return a concrete value type supporting addition, addition +assignment, unary negation, and multiplication by `Real` on either side. +All returned values and `zero` must have compatible dimensions. In particular, +return an owning matrix rather than an unevaluated expression referencing temporaries. +`norm` must return a nonnegative scalar norm convertible to `Real`. +If requested, `pL1` receives the quadrature approximation to the integral of +`norm(f(x))` over the interval in increasing order. This is not an error estimate. + +For example, with Eigen available: + + using Matrix = Eigen::Matrix, 2, 2>; + Matrix zero = Matrix::Zero(); + auto f = [](double x) -> Matrix { + Matrix result; + result << x, 0., 0., x*x; + return result; + }; + auto norm = [](const Matrix& m) { return m.norm(); }; + Matrix result = boost::math::quadrature::gauss::integrate( + f, 0., 1., zero, norm); + +The explicit zero also allows dynamically sized matrices: initialize it with the required dimensions. +For equal bounds the supplied zero is returned, `*pL1` is set to zero if requested, +and the integrand is not evaluated. + +Invalid bounds invoke the existing scalar domain-error policy. If that policy +returns a scalar error value instead of throwing, the result is `zero` multiplied +by that value, and `*pL1` receives that value if requested. For floating-point Eigen +matrices and the ignore-error policy, this produces a matrix of NaNs with the +supplied dimensions. Custom value types must support this multiplication too. + [heading Choosing the number of points] Internally class `gauss` has pre-computed tables of abscissa and weights for 7, 15, 20, 25 and 30 points at up to 100-decimal diff --git a/doc/quadrature/gauss_hermite.qbk b/doc/quadrature/gauss_hermite.qbk new file mode 100644 index 0000000000..0d4e0fa120 --- /dev/null +++ b/doc/quadrature/gauss_hermite.qbk @@ -0,0 +1,105 @@ +[/ +Copyright (c) 2026 Jacob Hass +Copyright (c) 2026 Nick Thompson +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) +] + +[section:gauss_hermite Gauss-Hermite quadrature] + +[heading Synopsis] + +`#include ` + + namespace boost{ namespace math{ namespace quadrature{ + + template > + struct gauss_hermite + { + static const RandomAccessContainer& abscissa(); + static const RandomAccessContainer& weights(); + + template + static auto integrate(F f, Real* pL1 = nullptr)->decltype(std::declval()(std::declval())); + + template + static auto integrate(F f, const decltype(f(Real(0)))& zero, Norm norm, + Real* pL1 = nullptr) -> decltype(f(Real(0))); + }; + + }}} // namespaces + +[heading Description] + +The `gauss_hermite` class template computes + +[expression ['[int][sub -[infin]][super [infin]] f(x) e[super -x[super 2]] dx [approx] [sum][sub i] w[sub i] f(x[sub i])]] + +using /Points/ evaluations of /f/, where the abscissas /x[sub i]/ are the zeros of the Hermite polynomial /H[sub Points]/. +The rule is exact when /f/ is a polynomial of degree at most 2/Points/ - 1. +Note that the weight function exp(-/x/[super 2]) is not part of /f/: pass only the factor that multiplies it. + +Like [link math_toolkit.gauss `gauss`], this is a "one shot" non-adaptive routine. +It obtains no estimate of the error, and is intended for smooth /f/ that grow no faster than a polynomial, +such as expectations of smooth functions of a normally distributed variable. + + static const RandomAccessContainer& abscissa(); + static const RandomAccessContainer& weights(); + +These provide direct access to the abscissas and weights. Only the nonnegative abscissas are stored, in increasing order; +the rule is symmetric about zero. + + template + static auto integrate(F f, Real* pL1 = nullptr)->decltype(std::declval()(std::declval())); + +Integrates /f/(/x/) exp(-/x/[super 2]) over the real line, and optionally sets `*pL1` to the corresponding integral of |/f/|. +If that is substantially larger than the absolute value of the result, then the sum was ill-conditioned. +/f/ may return a real or complex value. + + template + static auto integrate(F f, const decltype(f(Real(0)))& zero, Norm norm, + Real* pL1 = nullptr) -> decltype(f(Real(0))); + +As for [link math_toolkit.gauss `gauss`], this overload handles vector- and matrix-valued integrands: +`zero` is the additive identity of the returned type, and `norm` returns a nonnegative scalar convertible to `Real`. + +[heading Example] + +If /X/ is normally distributed with mean [mu] and standard deviation [sigma], then substituting /X/ = [mu] + [radic]2 [sigma] /x/ gives + +[expression ['E\[g(X)\] = [pi][super -1/2] [int][sub -[infin]][super [infin]] g([mu] + [radic]2 [sigma] x) e[super -x[super 2]] dx]] + +so, for example, E\[cos /X/\] = exp(-[sigma][super 2]/2) cos [mu] is computed by + + using boost::math::quadrature::gauss_hermite; + using boost::math::constants::root_pi; + using boost::math::constants::root_two; + double mu = 0.5; + double sigma = 2; + auto g = [&](double x) { return std::cos(mu + root_two() * sigma * x); }; + double expectation = gauss_hermite::integrate(g) / root_pi(); + +[heading Choosing the number of points] + +`gauss_hermite` has pre-computed tables of abscissas and weights for 7, 10 and 15 points, at up to 110 decimal digits of precision. +For other numbers of points, or higher precision types, the abscissas and weights are computed the first time they are needed and then cached. +Each zero is isolated by bisection with a Sturm sequence, then refined with Halley's method, all evaluated +with the three-term recurrence for orthonormal Hermite polynomials. +In double precision the computed abscissas are within a few ulps of the correctly rounded values and the weights within about one hundred, +for up to at least 200 points. + +In double precision the recurrence overflows for more than 706 points (the outer weights underflow long before that). +`integrate` then raises an __evaluation_error through the /Policy/; if the policy does not throw, the result is a NaN. + +As with `gauss`, defining `BOOST_MATH_GAUSS_NO_COMPUTE_ON_DEMAND` turns any combination of type and number of points without +pre-computed values into a compile-time error. +The program [@../../tools/gauss_hermite_constants.cpp gauss_hermite_constants.cpp] generates the pre-computed tables, +and is easily modified for other numbers of points. + +[heading References] + +* G. H. Golub and J. H. Welsch, ['Calculation of Gauss quadrature rules], Mathematics of Computation 23 (1969), 221-230. +* W. Gautschi, ['Orthogonal Polynomials: Computation and Approximation], Oxford University Press, 2004. + +[endsect] [/section:gauss_hermite Gauss-Hermite quadrature] diff --git a/doc/quadrature/gauss_kronrod.qbk b/doc/quadrature/gauss_kronrod.qbk index 31aeba9bba..449ab5c7d1 100644 --- a/doc/quadrature/gauss_kronrod.qbk +++ b/doc/quadrature/gauss_kronrod.qbk @@ -42,6 +42,49 @@ with no end point singularities. For difficult functions, or those with end poi Real* pL1 = nullptr)->decltype(std::declval()(std::declval())); }; +[heading Vector- and matrix-valued integrands] + +An additional overload accepts an explicit additive identity and a scalar norm: + + template + static auto integrate(F f, Real a, Real b, + const decltype(f(a))& zero, Norm norm, + unsigned max_depth = 15, + Real tol = tools::root_epsilon(), + Real* error = nullptr, Real* pL1 = nullptr) + -> decltype(f(a)); + +This overload participates only when `norm(f(a))` can be explicitly converted +to `Real`. Existing overloads and their behavior are unchanged. + +As with the [link math_toolkit.gauss Gauss overloads], `f` must return a concrete +value type supporting addition, addition assignment, unary negation, and scalar +multiplication on either side. The supplied zero and all integrand values must +have compatible dimensions. The norm must be nonnegative and convertible to `Real`. +For example, with Eigen: + + Eigen::MatrixXcd zero = Eigen::MatrixXcd::Zero(rows, cols); + auto norm = [](const Eigen::MatrixXcd& m) { return m.norm(); }; + Eigen::MatrixXcd result = boost::math::quadrature::gauss_kronrod::integrate( + f, a, b, zero, norm, 15, 1e-10); + +The supplied norm is used for the Gauss-Kronrod difference, the roundoff floor, +the relative convergence test, and the L1 integral. Tolerance therefore applies +to that norm, not separately to each matrix entry. `error` is an estimate, not a +rigorous bound, and reaching `max_depth` does not guarantee the requested tolerance. +In this overload, local error estimates are scaled by interval width, and by the +additional factor in the half-infinite substitutions, to match the units of the +returned integral. Reversing finite bounds negates the integral but leaves error +and L1 nonnegative. + +Equal bounds return the supplied zero and set requested error and L1 outputs to +zero without evaluating `f`. Invalid bounds invoke the scalar domain-error policy; +if it returns instead of throwing, the result is `zero` multiplied by the policy's +scalar error value, and requested error and L1 outputs receive that value. For +floating-point Eigen matrices the standard ignore-error policy thus produces a +matrix of NaNs with the supplied dimensions. No Eigen dependency is added to +Boost.Math headers. + [heading Description] static const RandomAccessContainer& abscissa(); diff --git a/doc/quadrature/ooura_fourier_integrals.qbk b/doc/quadrature/ooura_fourier_integrals.qbk index 6b04fa8509..7d3a250cf2 100644 --- a/doc/quadrature/ooura_fourier_integrals.qbk +++ b/doc/quadrature/ooura_fourier_integrals.qbk @@ -115,7 +115,7 @@ And with diagnostics on: Working code of this example is at [@../../example/ooura_fourier_integrals_multiprecision_example.cpp ooura_fourier_integrals_multiprecision_example.cpp] For more examples of other functions and tests, see the full test suite at -[@../../test/ooura_fourier_integral_test.cpp ooura_fourier_integral_test.cpp]. +[@../../test/test_ooura_fourier_integral.cpp test_ooura_fourier_integral.cpp]. Ngyen and Nuyens make use of __multiprecision in their extension to multiple dimensions, showing relative errors reducing to [cong] 10[super -2000]! diff --git a/doc/quadrature/symplectic.qbk b/doc/quadrature/symplectic.qbk new file mode 100644 index 0000000000..f530cfbd0b --- /dev/null +++ b/doc/quadrature/symplectic.qbk @@ -0,0 +1,186 @@ +[/ +Copyright (c) 2026 Jacob Hass +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) +] + +[section:symplectic Symplectic Integration] + +[heading Synopsis] + + #include + namespace boost{ namespace math{ namespace quadrature { + + enum class available_methods + { + Y6, + Y4, + Y2, + SRKNB6, + SRKNB11 + }; + + template + std::pair, std::vector > integrate_hamiltonian(RandomAccessContainer p0, + RandomAccessContainer q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq, + available_methods method, + const ``__Policy&`` pol) + + template + std::pair, std::vector > integrate_hamiltonian(RandomAccessContainer p0, + RandomAccessContainer q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq, + available_methods method) + + template + std::pair, std::vector > integrate_hamiltonian(RandomAccessContainer p0, + RandomAccessContainer q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq) + + template + BOOST_MATH_EXPORT std::tuple, std::vector, std::vector, std::vector > integrate_hamiltonian_adaptive(RandomAccessContainer p0, + RandomAccessContainer q0, + const std::pair timeInterval, + const Func dHdp, + const Func dHdq, + const RealType atol, + const RealType rtol, + const available_methods& method, + const Policy pol) + template + BOOST_MATH_EXPORT std::tuple, std::vector, std::vector, std::vector > integrate_hamiltonian_adaptive(RandomAccessContainer p0, + RandomAccessContainer q0, + const std::pair timeInterval, + const Func dHdp, + const Func dHdq, + const RealType atol, + const RealType rtol, + const available_methods& method) + + template + BOOST_MATH_EXPORT std::tuple, std::vector, std::vector, std::vector > integrate_hamiltonian_adaptive(RandomAccessContainer p0, + RandomAccessContainer q0, + const std::pair timeInterval, + const Func dHdp, + const Func dHdq, + const RealType atol, + const RealType rtol) + + template + BOOST_MATH_EXPORT boost::math::interpolators::cubic_hermite > integrate_hamiltonian_cubic(RealType p0, + RealType q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq, + available_methods method, + const Policy& pol) + + template + BOOST_MATH_EXPORT boost::math::interpolators::cubic_hermite > integrate_hamiltonian_cubic(RealType p0, + RealType q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq, + available_methods method) + + template + BOOST_MATH_EXPORT boost::math::interpolators::cubic_hermite > integrate_hamiltonian_cubic(RealType p0, + RealType q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq) + }}} // namespaces + +[heading Description] + +The above functions calculate the phase space trajectory for a given Hamiltonian. The functional +`integrate_hamiltonian` integrates a multi-dimensional system given a timestep and number of steps and returns +the phase-space trajectory of `(p, q)` at each time. Then a Cubic Hermite spline can be used to interpolate to any p using the +derivative `dp/dt = -dH/dq`. This leads to the next functional, `integrate_hamiltonian_cubic`, which integrates a 1 dimensional +system given a timestep and number of steps and returns a Cubic Hermite spline which interpolates `p` to any time. +Lastly, the functional `integrate_hamiltonian_adaptive` integrates a multi-dimensional system to a given absolute +and relative tolerance on a given time interval, `(tmin, tmax)`, using an integrating controller to adjust the timestep. This function +returns the tuple `(t, p, q, error)`. + +The trajectories are calculated using symplectic integration which preserves the energy of +a system. Even higher order traditional numerical integration algorithms will gain or lose +energy at long times. The functional implements the methods in [@https://www.sciencedirect.com/science/article/abs/pii/0375960190900923 Yoshida's] +landmark paper and methods by [@https://www.sciencedirect.com/science/article/pii/S0377042701004927?fr=RR-2&ref=pdf_download&rr=a1b51ec059e1fbec Blanes and Moan]. +We assume that the Hamiltonian is separable so that it can be written as `H = T(p) + V(q)`. + +We now give an example for a simple harmonic oscillator with the Hamiltonian +[/ $H = \frac{p^2}{2m} + \frac{1}{2}kx^2$ ] +[equation harmonic_oscillator] + +For simplicity we will assume `k = m = 1`. Then the partial derivatives of the Hamiltonian +with respect to `p` and `q` are + + double dHdp(double p) + { + return p; + } + + double dHdq(double q) + { + return q; + } + +Note that the functional can be readily generalized to multiple coordinates by changing the +signature of `dHdp` to + + std::vector dHdp(std::vector p) + { + // calculate the partial derivatives with respect to each p_i + } + +We then define the timestep size and number of steps of the algorithm to go from `t=0` to `t=100` + + RealType dt = 0.05; + RealType t_end = 100; + unsigned int steps = t_end / dt; + +Lastly, we define the initial conditions so that the oscillator starts from rest at `x=1` + + RealType q0 = 1; + RealType p0 = 0; + +We now evolve the system using the following + + std::vector p; + std::vector q; + + std::tie(p, q) = boost::math::quadrature::integrate_hamiltonian(p0, q0, dt, steps, dHdp, dHdq, available_methods::Y6); + +The ouput vectors `q, p` are the position and momentum of the system at each time. In +higher dimensions the output will be a vector of vectors. + +The last argument that we pass to `integrate_hamiltonian`, `available_methods::Y6` here, sets the integration +method to use. The value `Y6` stands for Yoshida's 6th order integrator. Yoshida's 2nd and +4th order methods are also available by passing the value `Y2`, or `Y4` respectively. +The 4th order and 6th order symplectic Runge-Kutta-Nystrom methods from Table 3 of Blanes and Moan +are available using the values `SRKNB6` and `SRKNB11`. + +[optional_policy] + +References: + +Yoshida, Haruo. [`Construction of higher order symplectic integrators], Physics Letters A, 150.5-7 (1990): 262-268. + +Blanes, Sergio, and Per Christian Moan. [`Practical symplectic partitioned runge–kutta and runge–kutta–nyström methods`], Journal of Computational and Applied Mathematics 142.2 (2002): 313-330. + +[endsect] [/section:symplectic Symplectic Integration] + diff --git a/doc/quadrature/trapezoidal.qbk b/doc/quadrature/trapezoidal.qbk index de01cb838a..dd2cb0553c 100644 --- a/doc/quadrature/trapezoidal.qbk +++ b/doc/quadrature/trapezoidal.qbk @@ -25,6 +25,36 @@ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) }}} // namespaces +[heading Vector- and matrix-valued integrands] + +An additional overload accepts an explicit zero value and scalar norm: + + template + auto trapezoidal(F f, Real a, Real b, const decltype(f(a))& zero, Norm norm, + Real tol = boost::math::tools::root_epsilon(), + std::size_t max_refinements = 12, + Real* error_estimate = nullptr, Real* L1 = nullptr) -> decltype(f(a)); + +A policy overload accepts the same arguments without defaults, followed by +`const Policy& pol`. These overloads participate only if `norm(f(a))` can be +explicitly converted to `Real`. Existing overloads remain unchanged. + +Return a concrete owning vector or matrix, with dimensions matching `zero`. +The value type needs addition, addition assignment, unary negation, and scalar +multiplication. The supplied norm controls the successive-estimate error and +L1 integral, so tolerance is measured against `tol * L1`, not independently for +each entry. For an Eigen matrix, a typical norm is +`[](const Matrix& m) { return m.norm(); }`. + + Matrix result = boost::math::quadrature::trapezoidal( + f, a, b, zero, norm, 1e-10); + +Equal bounds return `zero` and set requested error and L1 outputs to zero without +calling `f`. Reversed bounds negate the integral and preserve nonnegative error +and L1 estimates. Invalid bounds invoke the scalar domain-error policy; if it +returns, the result is `zero` multiplied by its scalar error value, and requested +error and L1 outputs receive that value. + [heading Description] The functional `trapezoidal` calculates the integral of a function /f/ using the surprisingly simple trapezoidal rule. diff --git a/doc/quadrature/van_den_bos_unit_square.qbk b/doc/quadrature/van_den_bos_unit_square.qbk new file mode 100644 index 0000000000..277c58dedd --- /dev/null +++ b/doc/quadrature/van_den_bos_unit_square.qbk @@ -0,0 +1,113 @@ +[/ +Copyright (c) 2026 Nicholas Thompson and Matt Borland +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) +] + +[section:van_den_bos_unit_square Van den Bos Unit-Square Quadrature] + +[heading Synopsis] + + #include + namespace boost { namespace math { namespace quadrature { + + template + auto van_den_bos_unit_square( + F const& f, + double tolerance, + double* error_estimate = nullptr, + double* L1 = nullptr, + std::size_t* evaluations = nullptr); + + }}} // namespaces + +[heading Description] + +`van_den_bos_unit_square` computes an adaptive positive cubature of a +real- or complex-valued function over the reference square [0,1]^2. The +integrand receives the two coordinates as separate `double` arguments. + +For a nondegenerate parallelogram with one vertex [^p0] and edge vectors +[^a] and [^b], use the affine map +`p(u,v) = p0 + u a + v b`, where `(u,v)` lies in `[0,1]^2`. The integral +over the parallelogram is the integral of `f(p0 + u a + v b)` over the unit +square, multiplied by `abs(det(a,b))`. The caller must perform this mapping +and include the constant Jacobian `abs(det(a,b))` in the integrand. + +The precomputed rules contain no points on the boundary of the square, so the +routine does not evaluate the integrand at an endpoint singularity. Interior +nodes approach the boundary as the levels increase, however, so excluding the +endpoints does not by itself make an improper integral well conditioned. +Singular integrals may still require a suitable change of variables. + +The precomputed rules form a nested hierarchy. After the first level, +only points newly introduced by the next level are evaluated. The routine +requires two consecutive adjacent-level differences to satisfy `tolerance` +before stopping, which avoids accepting an isolated cancellation. If the +maximum level is reached first, the last rule is returned and its difference +is used as the final `error_estimate` (subject to the roundoff floor). + +The optional `L1` output is the weighted sum of the absolute integrand values. +`evaluations` reports the number of function calls, including calls reused by +all subsequent levels. The supported result types are `float` and `double`, +including complex values with `float` or `double` components. Higher-precision +return types are not supported. + +Nodes and weights are computed offline. If the requested tolerance is not +reached by the final precomputed level, the routine returns that level's +result and error estimate; it does not compute additional levels. + +Requires C++17. + +Positive cubature rules satisfying the same moment conditions are not unique. +The nodes and weights of this routine are chosen on a Fejer type-II grid. The +nodes are strictly contained in `(0,1)^2`, and the weighted rule is invariant +under D[sub 4]. + +[heading Dilogarithm example] + +For a smooth special-function example, the integral of `1/(1-xy/2)` over the +unit square is `pi^2/6 - log^2(2)`. + + using boost::math::quadrature::van_den_bos_unit_square; + + double error_estimate = 0; + double value = van_den_bos_unit_square( + [](double x, double y) + { + return 1 / (1 - x * y / 2); + }, + 1e-10, + &error_estimate); + +[heading Square-lattice Green function] + +The resolvent of the nearest-neighbor square lattice gives the genuinely +two-dimensional periodic integral of +`1/(z - cos(2*pi*x) - cos(2*pi*y))` over the unit square. For [^z > 2], its +closed form is `G(z) = 2*K(2/z)/(pi*z)`, where [^K] is the complete elliptic +integral of the first kind. For example, [^z = 3] can be computed with + + double const z = 3; + double const two_pi = 2 * boost::math::constants::pi(); + double value = van_den_bos_unit_square( + [=](double x, double y) + { + return 1 / (z - std::cos(two_pi * x) + - std::cos(two_pi * y)); + }, + 1e-6); + +The lattice value [^z = 2], and the parameter value [^z = 1] in the +dilogarithm family `(1-zxy)^-1`, give improper integrals. Although the +rules do not evaluate the singular boundary points themselves, singular +integrands may require a suitable change of variables and should not be +expected to have reliable adjacent-level error estimates without such +treatment. + +The construction follows the positive, nested reduction approach of +[@https://arxiv.org/abs/1809.09842 van den Bos et al.], adapted here to the +uniform measure on the unit square. + +[endsect] [/section:van_den_bos_unit_square Van den Bos Unit-Square Quadrature] diff --git a/doc/quaternion/math-quaternion.qbk b/doc/quaternion/math-quaternion.qbk index 6d5408b433..aaa3573f64 100644 --- a/doc/quaternion/math-quaternion.qbk +++ b/doc/quaternion/math-quaternion.qbk @@ -839,7 +839,7 @@ Computes the n-th power of the quaternion q. [section:quat_tests Test Program] -The [@../../test/quaternion_test.cpp quaternion_test.cpp] +The [@../../test/test_quaternion.cpp test_quaternion.cpp] test program tests quaternions specializations for float, double and long double ([@../quaternion/output.txt sample output], with message output enabled). diff --git a/doc/roots/polynomial_roots.qbk b/doc/roots/polynomial_roots.qbk new file mode 100644 index 0000000000..dd2e1b35e7 --- /dev/null +++ b/doc/roots/polynomial_roots.qbk @@ -0,0 +1,84 @@ +[section:polynomial_roots Complex Roots of a Polynomial] + +`` +#include +`` + + template + auto polynomial_roots(RandomAccessContainer const& coefficients); + + template + auto polynomial_roots_companion_matrix(RandomAccessContainer const& coefficients); + +`polynomial_roots` computes all finite complex roots of a polynomial with real, +floating-point coefficients, held in any random access container: `std::vector`, `std::array`, +`std::span` and so on. Both functions return a `std::vector`. If the container's +`value_type`, `Real`, is a built-in floating-point type, `Complex` is `std::complex`; if it is a +Boost.Multiprecision type, `Complex` is the matching multiprecision complex type (`cpp_complex_50` for +`cpp_bin_float_50`, and so on), whose header, e.g. ``, must be +included first. Coefficients are supplied in ascending order, so +`{a0, a1, ..., an}` represents +[@https://en.wikipedia.org/wiki/Polynomial a0 + a1 z + ... + an z^n]. +The returned order is unspecified. + +The implementation follows the piecewise approximation strategy of Imbach and +Moroz: a Newton-polygon sweep divides the complex plane into radial rings, the +rings are divided into angular sectors, and low-degree Taylor polynomials are +factored locally, with expansions of an order set by the precision of `Real`. +Candidate roots are polished and checked against the input polynomial. A global Aberth iteration is used as a safety net for unresolved or +ill-conditioned clusters. + +Exact leading zero coefficients are ignored. Exact trailing zero coefficients +produce the corresponding number of roots at zero. The zero polynomial and +non-finite coefficients cause `std::domain_error` to be thrown. + +[heading The companion QR algorithm] + +`polynomial_roots_companion_matrix` computes the same roots as the eigenvalues of the companion matrix, +by the core-chasing QR algorithm of Aurentz, Mach, Vandebril and Watkins. It +stores the companion matrix as O(n) 2x2 unitary rotations, so it takes O(n[super 2]) +time and O(n) memory, against O(n[super 3]) and O(n[super 2]) for a dense +eigensolver. Before the iteration the variable is scaled so that the constant +and leading coefficients have equal magnitude. + +The two functions make different guarantees. `polynomial_roots_companion_matrix` is proven normwise +backward stable: all of its roots are the exact roots of a single polynomial +whose coefficient vector is within a modest multiple of n[epsilon] of the input, +relative to the norm of the coefficients. `polynomial_roots` checks a stronger, +coefficientwise, bound on each root: each one is an exact root of a polynomial +whose coefficients each differ from the input in only the last few bits. +It has no a priori proof of convergence, but it returns only roots that +pass this check. The coefficientwise bound matters when the roots span many +orders of magnitude, as in [prod](z - 10[super -k]): the small roots are +determined by the small coefficients, which a normwise perturbation may change +completely, so `polynomial_roots_companion_matrix` gets the small roots wrong while `polynomial_roots` +gets them to nearly full precision. For roots of comparable magnitude the +two agree. + +Exact zero coefficients are handled as for `polynomial_roots`. The zero +polynomial and non-finite coefficients cause `std::domain_error` to be +thrown, and `std::runtime_error` is thrown in the unlikely event that the QR +iteration fails to converge. + +[heading Example] + + std::array p{1, 0, 1}; // 1 + z^2 + auto roots = boost::math::tools::polynomial_roots(p); + +The result contains approximations to `i` and `-i`. + +[heading References] + +J. Imbach and G. Moroz, "Fast evaluation and root finding for polynomials with +floating-point coefficients", 2023. + +J. L. Aurentz, T. Mach, R. Vandebril and D. S. Watkins, "Fast and backward +stable computation of roots of polynomials", SIAM J. Matrix Anal. Appl. 36 +(2015), 942-973. + +J. L. Aurentz, T. Mach, L. Robol, R. Vandebril and D. S. Watkins, "Fast and +backward stable computation of roots of polynomials, Part II: backward error +analysis; companion matrix and companion pencil", SIAM J. Matrix Anal. Appl. +39 (2018), 1245-1269. + +[endsect] diff --git a/doc/roots/roots.qbk b/doc/roots/roots.qbk index ea347639b9..cdc1a51f07 100644 --- a/doc/roots/roots.qbk +++ b/doc/roots/roots.qbk @@ -110,6 +110,13 @@ substantially with each iteration, ['digits] should be set by experiment so that iteration just takes the next value into the zone where ['f(x)] becomes inaccurate. A good starting point for ['digits] would be 0.6*D for Newton and 0.4*D for Halley or Shr'''ö'''der iteration, where D is `std::numeric_limits::digits`. +* Out-of-bounds steps are assumed to have the root between the current guess and the bound +they crossed. If ['f(x)] is not monotone between the guess and the root (for example there is a +local extremum in the way) that assumption fails, and the iteration can end up at the bound without +['f(x)] ever changing sign. The implementation attempts to detect this case: if the result has collapsed +onto one end of [min, max], ['f(x)] never changed sign, and ['f(x)] at that end does not look like a root, +an __evaluation_error is raised rather than returning the bound. The detection is heuristic, so the +best defence is a good initial guess, or a range [min, max] on which ['f(x)] is monotone. * If you need some diagnostic output to see what is going on, you can `#define BOOST_MATH_INSTRUMENT` before the `#include `, and also ensure that display of all the significant digits with diff --git a/doc/roots/roots_overview.qbk b/doc/roots/roots_overview.qbk index 30bd2e3855..c6749516e0 100644 --- a/doc/roots/roots_overview.qbk +++ b/doc/roots/roots_overview.qbk @@ -19,6 +19,7 @@ There are several fully-worked __root_finding_examples, including: [include roots.qbk] [include cubic_roots.qbk] [include quartic_roots.qbk] +[include polynomial_roots.qbk] [include root_finding_examples.qbk] [include minima.qbk] [include root_comparison.qbk] diff --git a/doc/roots/roots_without_derivatives.qbk b/doc/roots/roots_without_derivatives.qbk index 5c82ef4155..15197e985d 100644 --- a/doc/roots/roots_without_derivatives.qbk +++ b/doc/roots/roots_without_derivatives.qbk @@ -373,7 +373,7 @@ The __root_finding_TOMS748 parameters are: [variablelist [[f] [A unary functor (or C++ lambda) that is the function whose root is to be solved. f(x) need not be uniformly increasing or decreasing on ['x] and - may have multiple roots. However, the bounds given must bracket a single root.]] + may have multiple roots. However, the bounds given must bracket at least one root.]] [[a] [The lower bound for the initial bracket of the root.]] [[b] [The upper bound for the initial bracket of the root. It is a precondition that ['a < b] and that ['a] and ['b] diff --git a/doc/sf/beta.qbk b/doc/sf/beta.qbk index 7e1904c254..4e6a3a24f8 100644 --- a/doc/sf/beta.qbk +++ b/doc/sf/beta.qbk @@ -13,6 +13,12 @@ template BOOST_MATH_GPU_ENABLED ``__sf_result`` beta(T1 a, T2 b, const ``__Policy``&); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` lbeta(T1 a, T2 b); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` lbeta(T1 a, T2 b, const ``__Policy``&); }} // namespaces @@ -29,6 +35,11 @@ The beta function is defined by: The return type of these functions is computed using the __arg_promotion_rules when T1 and T2 are different types. +`lbeta` returns the natural logarithm of the beta function, log B(a, b). +It stays finite and accurate where `beta` underflows, for example when both /a/ and /b/ are large, +and where lgamma(a) + lgamma(b) - lgamma(a + b) would lose every digit to cancellation, +when one argument is much larger than the other. + [h4 Accuracy] The following table shows peak errors for various domains of input arguments, @@ -69,9 +80,21 @@ immediately cuts the maximum error in half: This may not be the final solution, but it is very competitive compared to other implementation methods. +`lbeta` takes the logarithm of this form term by term. With /a/ >= /b/, /c = a + b/ and /xgh = x + g - 1\/2/, +and since /agh = cgh - b/, the two power terms merge: + +log B(a, b) = log(L(a) L(b) / L(c)) + (a - 1\/2) log1p(-b \/ cgh) + b log(bgh \/ cgh) + (1 - log bgh) \/ 2 + +where /L/ is the scaled Lanczos sum. None of these terms cancel when one argument is large, and none underflow +when both are. In double precision the result is within 2 ulps where |log B| >= 1, and within 1 epsilon +absolute error elsewhere, for arguments across the whole exponent range. +Without a __lanczos approximation, `lbeta` takes logarithms in the generic method below, except that when one +argument is small it uses lgamma and __tgamma_delta_ratio directly, and when both lie between 1 and the +threshold for Stirling's approximation it takes the logarithm of `beta` itself, which cannot overflow or underflow there. + The generic implementation - where no __lanczos approximation is available - is implemented in a very similar way to the generic version of the gamma function -by means of Sterling's approximation. +by means of Stirling's approximation. Again in order to avoid numerical overflow the power terms that prefix the series are collected together diff --git a/doc/sf/ccmath.qbk b/doc/sf/ccmath.qbk index b71c235217..a4977b4dd4 100644 --- a/doc/sf/ccmath.qbk +++ b/doc/sf/ccmath.qbk @@ -149,6 +149,12 @@ All of the following functions require C++17 or greater. template inline constexpr Promoted hypot(Arithmetic1 x, Arithmetic2 y) noexcept + template + inline constexpr Real hypot(Real x, Real y, Real z) noexcept + + template + inline constexpr Promoted hypot(Arithmetic1 x, Arithmetic2 y, Arithmetic3 z) noexcept + template inline constexpr Real fdim(Real x, Real y) noexcept diff --git a/doc/sf/chebyshev.qbk b/doc/sf/chebyshev.qbk index 1ba3d38301..2f79ec0a42 100644 --- a/doc/sf/chebyshev.qbk +++ b/doc/sf/chebyshev.qbk @@ -146,7 +146,7 @@ The API is given below. { public: template - chebyshev_transform(const F& f, Real a, Real b, Real tol=500*std::numeric_limits::epsilon()); + chebyshev_transform(const F& f, Real a, Real b, Real tol=500*std::numeric_limits::epsilon(), size_t max_refinements = 16); Real operator()(Real x) const @@ -165,8 +165,13 @@ By /near-minimax/, we mean that the resulting Chebyshev polynomial is "very clos The notion of "very close" can be made rigorous; see Trefethen's "Approximation Theory and Approximation Practice" for details. The Chebyshev transform works by creating a vector of values by evaluating the input function at the Chebyshev points, and then performing a discrete cosine transform on the resulting vector. -In order to do this efficiently, we have used [@http://www.fftw.org/ FFTW3]. -So to compile, you must have `FFTW3` installed, and link with `-lfftw3` for double precision, `-lfftw3f` for float precision, `-lfftw3l` for long double precision, and `-lfftw3q` for quad (`__float128`) precision. +The cosine transform is computed with the library's own [link math_toolkit.fft fast Fourier transform], +so `Real` may be `float`, `double`, `long double`, or a multiprecision type such as `boost::multiprecision::cpp_bin_float_50`. +With a multiprecision `Real`, also include the Boost.Multiprecision header for the matching complex type, which the transform uses internally: +`` for `cpp_bin_float`, `` for `float128`, +and `` for `mpfr_float`. +The function is sampled at 256 Chebyshev points, and the number of points is doubled until the trailing coefficients are negligible +or `max_refinements` doublings have been made. After the coefficients of the Chebyshev series are known, the routine goes back through them and filters out all the coefficients whose absolute ratio to the largest coefficient are less than the tolerance requested in the constructor. [endsect] [/section:chebyshev Chebyshev Polynomials] diff --git a/doc/sf/hypergeometric.qbk b/doc/sf/hypergeometric.qbk index 9978cf14fc..3d678de9e2 100644 --- a/doc/sf/hypergeometric.qbk +++ b/doc/sf/hypergeometric.qbk @@ -471,6 +471,10 @@ You should divide this value by the result to get an estimate of ['relative erro It should be noted that the error estimates are rather crude - the error can be significantly underestimated in some circumstances, and over-estimated in others. +If ['p_abs_error] is not provided, and the error estimate shows that more than half of the digits of the result are +likely to be wrong (the relative error estimate is larger than the square root of machine epsilon), then an __evaluation_error is raised +rather than returning a result which is wrong in most of its digits. + The `hypergeometric_pFq_precision` functions will calculate `pFq` to a specified number of decimal places, and if `timeout` is reached then they raise an __evaluation_error. Note that while these functions are defined as templates, they require type `Real` to be a *variable-precision* floating-point type: in practice the only type currently supported diff --git a/doc/sf/ibeta.qbk b/doc/sf/ibeta.qbk index 5227b2d342..4b179a62d8 100644 --- a/doc/sf/ibeta.qbk +++ b/doc/sf/ibeta.qbk @@ -19,6 +19,18 @@ template BOOST_MATH_GPU_ENABLED ``__sf_result`` ibetac(T1 a, T2 b, T3 x, const ``__Policy``&); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` libeta(T1 a, T2 b, T3 x); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` libeta(T1 a, T2 b, T3 x, const ``__Policy``&); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` libetac(T1 a, T2 b, T3 x); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` libetac(T1 a, T2 b, T3 x, const ``__Policy``&); template BOOST_MATH_GPU_ENABLED ``__sf_result`` beta(T1 a, T2 b, T3 x); @@ -78,6 +90,22 @@ Returns the normalised complement of the incomplete beta function of a, b and x: [equation ibeta4] + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` libeta(T1 a, T2 b, T3 x); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` libeta(T1 a, T2 b, T3 x, const ``__Policy``&); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` libetac(T1 a, T2 b, T3 x); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` libetac(T1 a, T2 b, T3 x, const ``__Policy``&); + +Return the natural logarithms of `ibeta(a, b, x)` and `ibetac(a, b, x)`. They stay finite and accurate far out in the tails, +where `ibeta` or `ibetac` underflows: for example `libeta(10000, 10000, 0.25)` is about -2882 in double precision, where `log(ibeta(10000, 10000, 0.25))` is -infinity. +Where the result is exactly zero, its logarithm, -infinity, is reported as an __overflow_error. + template BOOST_MATH_GPU_ENABLED ``__sf_result`` beta(T1 a, T2 b, T3 x); @@ -192,6 +220,13 @@ The domains of a, b and x for which the various methods are used are identical to those described in the [@http://portal.acm.org/citation.cfm?doid=131766.131776 Didonato and Morris TOMS 708 paper]. +`libeta` and `libetac` take the logarithm of whichever of `ibeta` and `ibetac` is the smaller (using `log1p` for the other), +since these have small relative errors. Only when the smaller underflows, far out in its tail, +do they work in logarithms: the result is then the logarithm of the power terms that prefix the continued fraction above, +following the same combination of Lanczos sums and power terms but without exponentiating, minus the logarithm of the continued fraction. +When /a = 1/ the closed form /1 - (1 - x)[super b]/ is used instead. +By contrast, R's `pbeta(q, a, b, log.p = TRUE)` carries logarithms through each of the TOMS 708 methods. + [endsect][/section:ibeta_function The Incomplete Beta Function] [/ diff --git a/doc/sf/igamma.qbk b/doc/sf/igamma.qbk index 1ce33d7a76..9b1cf5d7a9 100644 --- a/doc/sf/igamma.qbk +++ b/doc/sf/igamma.qbk @@ -43,6 +43,18 @@ template BOOST_MATH_GPU_ENABLED ``__sf_result`` tgamma(T1 a, T2 z, const ``__Policy``&); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` ligamma(T1 a, T2 z); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` ligamma(T1 a, T2 z, const ``__Policy``&); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` ligamma_lower(T1 a, T2 z); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` ligamma_lower(T1 a, T2 z, const ``__Policy``&); }} // namespaces @@ -130,6 +142,22 @@ Returns the full (non-normalised) upper incomplete gamma function of a and z: [equation igamma1] + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` ligamma(T1 a, T2 z); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` ligamma(T1 a, T2 z, const ``__Policy``&); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` ligamma_lower(T1 a, T2 z); + + template + BOOST_MATH_GPU_ENABLED ``__sf_result`` ligamma_lower(T1 a, T2 z, const ``__Policy``&); + +Return the natural logarithms of `tgamma(a, z)` and `tgamma_lower(a, z)`. They stay finite and accurate where those +overflow or underflow: for example `ligamma(1000, 1000)` is about 5905 in double precision, where `log(tgamma(1000, 1000))` +raises an overflow error. Where the result is exactly zero, its logarithm, -infinity, is reported as an __overflow_error. + [h4 Accuracy] The following tables give peak and mean relative errors in over various domains of @@ -303,8 +331,16 @@ in which case an expansion, for large x, of the (non-normalised) upper incomplete gamma function is used. The return is then normalised by subtracting the log of the gamma function and adding /a log(x)-x-log(x)/. +`ligamma` and `ligamma_lower` take the logarithm of `tgamma(a, z)` or `tgamma_lower(a, z)` where that is representable. +Otherwise they add `lgamma(a)` to the logarithm of the regularized function, or of `log1p` of minus its complement when that +is the smaller, except where the regularized function underflows: then they use /a log(z) - z/ plus the logarithm of the +continued fraction (upper) or series (lower) that it multiplies, the same normalization by /z[super a]e[super -z]/ as the +G-function of Abergel and Moisan. + [h4 References] +* R. Abergel and L. Moisan, Algorithm 1006: Fast and Accurate Evaluation of a Generalized Incomplete Gamma Function, +ACM TOMS, Vol 46, No 1, 2020. * N. M. Temme, A Set of Algorithms for the Incomplete Gamma Functions, Probability in the Engineering and Informational Sciences, 8, 1994. * N. M. Temme, The Asymptotic Expansion of the Incomplete Gamma Functions, diff --git a/doc/sf/jacobi_theta.qbk b/doc/sf/jacobi_theta.qbk index 437001bc5c..c9b595f6ca 100644 --- a/doc/sf/jacobi_theta.qbk +++ b/doc/sf/jacobi_theta.qbk @@ -53,7 +53,12 @@ A more accurate computation will take advantage of [tau]: jacobi_theta1tau(x, a / boost::math::constants::pi()); -Internally, Boost implements the /q/ parameterization by taking the logarithm of /q/ and passing it to the [tau] parameterization; as such, using the [tau] parameterization directly will generally yield greater precision. +Internally, when /q/ is larger than exp(-[pi]) (that is, when [tau] is less than 1), Boost implements the /q/ parameterization by taking the logarithm of /q/ and passing it to the [tau] parameterization; as such, using the [tau] parameterization directly will generally yield greater precision in that regime. +When /q/ is smaller than exp(-[pi]), the Fourier series is summed directly in terms of /q/, and the two parameterizations are equally accurate. + +Every term of the series is an exponential whose argument is a product or quotient of [tau], [pi] and a small integer, or, in the transformed series used when [tau] < 1, the square of /z/ plus a multiple of [pi]/2. +Rounding such an argument to working precision would cost as many ulps in the term as the argument is large, so the rounding errors of [pi], of the products, of the division and of the reduction of /z/ are tracked exactly (using error-free transformations that work for any binary floating-point type) and applied as a correction factor to each term. +The [tau] parameterization is therefore accurate to a few ulps throughout, apart from the conditioning of the function itself, for /z/ up to about 1/[epsilon] (10[super 16] for `double`); beyond that the reduction of /z/ by the period loses accuracy in proportion to /z/[epsilon][super 2]. In the /q/ parameterization the rounding of log(/q/) remains, and its effect grows as /q/ approaches 1. As another example, if the complement of /q/ is known with great accuracy, then instead of: jacobi_theta1(x, 1-q_complement); @@ -64,6 +69,8 @@ It is more accurate to use `__log1p` and pass in the result to the [tau] version Additional "minus 1" versions of the third and fourth theta functions are provided. Similar in spirit to `__expm1`, these functions return one less than the evaluated function, and yield increased accuracy when /q/ is small. +All of the functions return the result of __domain_error if /z/ is not finite, if /q/ lies outside (0, 1), or if [tau] is not strictly positive. A NaN argument is treated as a domain error. + [heading Testing] Results of the theta functions are tested against Wolfram Alpha data, as well as random values computed at high precision. @@ -122,11 +129,11 @@ Fixing /x/=5 and varying /q/, the ULPs plot looks like: [graph jacobi_theta1q_float] -Accuracy tends to degenerate near /q/=1 (small [tau]). +Accuracy degrades gently as /q/ approaches 1 (small [tau]), where the rounding of log(/q/) is amplified by the size of the exponents in the transformed series; the [tau] parameterization does not have this problem. [heading Implementation] -The /q/ parameterization is implemented using the [tau] parameterization, where [tau]=-log(/q/)/[pi]. +When /q/ < exp(-[pi]) the series above is summed directly in /q/. Otherwise the /q/ parameterization is implemented using the [tau] parameterization, where [tau]=-log(/q/)/[pi]. If [tau] is greater than or equal to 1, the summation above is used as-is. However if [tau] < 1, the following identity [@https://dlmf.nist.gov/20.7#viii DLMF 20.7.30] is used, defining [tau]'=-1/[tau]: @@ -134,6 +141,8 @@ However if [tau] < 1, the following identity [@https://dlmf.nist.gov/20.7#viii D [equation jacobi_theta1_imaginary] [/ (-i\tau)^{1/2}\theta_1(x|\tau)=-i\exp(i\tau'x^2/\pi)\theta_1(x\tau'|\tau') ] This transformation of variables ensures that the function will always converge in a small number of iterations. +The transformed series is a sum of differences of Gaussians centered at [plusminus][pi](/n/+1/2), which nearly cancel as /x/ approaches zero; +each difference is therefore evaluated using `__expm1` so that full relative precision is retained for small /x/. [endsect] [/section:jacobi_theta1 Jacobi Theta Function [theta][sub 1]] @@ -189,11 +198,11 @@ Fixing /x/=0.4 and varying /q/, the ULPs plot looks like: [graph jacobi_theta2q_float] -Accuracy tends to degenerate near /q/=1 (small [tau]). +Accuracy degrades gently as /q/ approaches 1 (small [tau]), where the rounding of log(/q/) is amplified by the size of the exponents in the transformed series; the [tau] parameterization does not have this problem. [heading Implementation] -The /q/ parameterization is implemented using the [tau] parameterization, where [tau]=-log(/q/)/[pi]. +When /q/ < exp(-[pi]) the series above is summed directly in /q/. Otherwise the /q/ parameterization is implemented using the [tau] parameterization, where [tau]=-log(/q/)/[pi]. If [tau] is greater than or equal to 1, the summation above is used as-is. However if [tau] < 1, the following identity [@https://dlmf.nist.gov/20.7#viii DLMF 20.7.31] is used, defining [tau]'=-1/[tau]: @@ -271,11 +280,11 @@ Fixing /x/=0.4 and varying /q/, the ULPs plot looks like: [graph jacobi_theta3q_float] -Accuracy tends to degenerate near /q/=1 (small [tau]). +Accuracy degrades gently as /q/ approaches 1 (small [tau]), where the rounding of log(/q/) is amplified by the size of the exponents in the transformed series; the [tau] parameterization does not have this problem. [heading Implementation] -The /q/ parameterization is implemented using the [tau] parameterization, where [tau]=-log(/q/)/[pi]. +When /q/ < exp(-[pi]) the series above is summed directly in /q/. Otherwise the /q/ parameterization is implemented using the [tau] parameterization, where [tau]=-log(/q/)/[pi]. If [tau] is greater than or equal to 1, the summation above is used as-is. However if [tau] < 1, the following identity [@https://dlmf.nist.gov/20.7#viii DLMF 20.7.32] is used, defining [tau]'=-1/[tau]: @@ -353,11 +362,11 @@ Fixing /x/=5 and varying /q/, the ULPs plot looks like: [graph jacobi_theta4q_float] -Accuracy tends to degenerate near /q/=1 (small [tau]). +Accuracy degrades gently as /q/ approaches 1 (small [tau]), where the rounding of log(/q/) is amplified by the size of the exponents in the transformed series; the [tau] parameterization does not have this problem. [heading Implementation] -The /q/ parameterization is implemented using the [tau] parameterization, where [tau]=-log(/q/)/[pi]. +When /q/ < exp(-[pi]) the series above is summed directly in /q/. Otherwise the /q/ parameterization is implemented using the [tau] parameterization, where [tau]=-log(/q/)/[pi]. If [tau] is greater than or equal to 1, the summation above is used as-is. However if [tau] < 1, the following identity [@https://dlmf.nist.gov/20.7#viii DLMF 20.7.33] is used, defining [tau]'=-1/[tau]: diff --git a/doc/sf/number_series.qbk b/doc/sf/number_series.qbk index c47cc877f6..bdd2931411 100644 --- a/doc/sf/number_series.qbk +++ b/doc/sf/number_series.qbk @@ -259,7 +259,225 @@ Passing a value greater than `max_prime` results in a __domain_error being raise This function is `constexpr` only if the compiler supports C++14 constexpr functions. -[endsect] [/section:primes] +[endsect] [/section:primes Prime Numbers] + +[section:prime_sieve Prime Sieve] + +[h4 Synopsis] + +`` +#include +`` + + namespace boost { namespace math { + + namespace execution { + struct cuda_policy {}; + inline constexpr cuda_policy cuda {}; + } + + enum class prime_range_strategy { automatic, full_sieve, test_survivors }; + + struct prime_sieve_options + { + std::size_t l1d_bytes {0}; // 0 = detect + std::size_t l2_bytes {0}; // 0 = detect (per core) + std::size_t sieve_bytes {0}; // 0 = derive from sqrt(upper) and the caches; clamped to [16 KiB, 8 MiB] + unsigned max_threads {0}; // 0 = std::thread::hardware_concurrency() + std::size_t chunk_primes {1u << 19}; // primes per parallel chunk when storing output + prime_range_strategy range_strategy {prime_range_strategy::automatic}; + bool probable_prime_only {false}; // beyond 2^64: Baillie-PSW only, skip the pseudosquares test + }; + + // primes in [2, upper_bound) + template + OutputIterator prime_sieve(ExecutionPolicy&& policy, Integer upper_bound, OutputIterator out, const prime_sieve_options& options = {}); + template + OutputIterator prime_sieve(Integer upper_bound, OutputIterator out, const prime_sieve_options& options = {}); + template + void prime_sieve(ExecutionPolicy&& policy, Integer upper_bound, std::vector& out, const prime_sieve_options& options = {}); + template + void prime_sieve(Integer upper_bound, std::vector& out, const prime_sieve_options& options = {}); + + // primes in [lower_bound, upper_bound); the bounds may have different integer types + template + OutputIterator prime_range(ExecutionPolicy&& policy, Lower lower_bound, Upper upper_bound, OutputIterator out, const prime_sieve_options& options = {}); + template + OutputIterator prime_range(Lower lower_bound, Upper upper_bound, OutputIterator out, const prime_sieve_options& options = {}); + template + void prime_range(ExecutionPolicy&& policy, Lower lower_bound, Upper upper_bound, std::vector& out, const prime_sieve_options& options = {}); + template + void prime_range(Lower lower_bound, Upper upper_bound, std::vector& out, const prime_sieve_options& options = {}); + + // number of primes in [2, upper_bound) and in [lower_bound, upper_bound) + template + std::uint64_t prime_count(ExecutionPolicy&& policy, Integer upper_bound, const prime_sieve_options& options = {}); + template + std::uint64_t prime_count(ExecutionPolicy&& policy, Lower lower_bound, Upper upper_bound, const prime_sieve_options& options = {}); + template + std::uint64_t prime_count(Integer upper_bound, const prime_sieve_options& options = {}); + template + std::uint64_t prime_count(Lower lower_bound, Upper upper_bound, const prime_sieve_options& options = {}); + + // reserves room for all primes below upper_bound + template + void prime_reserve(Integer upper_bound, std::vector& primes); + + }} // namespaces + +[h4 Description] + +These functions require C++17. + +`prime_sieve` produces the primes in the half-open range \[2, `upper_bound`), `prime_range` the primes in +\[`lower_bound`, `upper_bound`), and `prime_count` returns how many primes such a range contains without +storing them. Output is always in ascending order. The overloads taking a `std::vector` append to it +and are the fastest way to store the primes; the output iterator overloads return the advanced iterator. +A `lower_bound` below 2 is treated as 2, negative bounds as 0, and an empty range produces nothing. +A negative bound is clamped in its own type, so mixing a signed and an unsigned bound is safe. + +`Integer` may be any builtin integer type or a Boost.Multiprecision integer such as `cpp_int` or `mpz_int`. +Bounds that fit in 64 bits are sieved with a segmented sieve of Eratosthenes in the style of +[@https://github.com/kimwalisch/primesieve primesieve]: one byte represents 30 integers (the eight residues +coprime to 30), multiples of the primes up to 163 are removed by pre-computed periodic patterns, and the +sieving primes are split into three classes (many multiples per segment, a few, or at most one) that use a +mod 30 wheel with unrolled loops, lists sorted by wheel position, and Oliveira e Silva's bucket sieve +(fixed 8 KiB buckets from a memory pool) respectively. Segments are sized to the L1 and L2 data caches, +which are detected on Linux and macOS and can be overridden through `prime_sieve_options`; when big +primes are present the largest segment (8 MiB) is used. The wheel tables and the 16 pre-sieve +patterns (123 KB) are computed at compile time with `constexpr` on GCC and Clang; MSVC and nvcc, whose +constexpr step limits are lower, generate the patterns on first use (define +`BOOST_MATH_PRIME_SIEVE_RUNTIME_PRESIEVE` to force that everywhere). + +Short intervals at large magnitudes (roughly when the interval is narrower than `sqrt(upper_bound) / ln(upper_bound)`) +switch automatically to a window method: the interval is sieved by the primes up to a modest depth and the +survivors are tested with a Baillie-PSW test in Montgomery arithmetic, which is deterministic below 2[super 64]. +`prime_range_strategy` forces either method. + +Bounds beyond 2[super 64] use the same window method with the Lukes-Patterson-Williams pseudosquares test +(Sorenson, ['The pseudosquares prime sieve], 2006), which is deterministic while `upper_bound` divided by the +sieving depth stays below the largest tabulated pseudosquare (about 2.95 * 10[super 23]), and Baillie-PSW beyond +that, for which no counterexample is known. Setting `probable_prime_only` uses Baillie-PSW everywhere and is +roughly ten times faster. This path is intended for windows of up to about 10[super 8] integers; the +head of a range that straddles 2[super 64] is still processed by the 64-bit engine. + +[h4 Execution policies] + +The policy overloads accept the `std::execution` policies and `boost::math::execution::cuda`: + +[table +[[Policy][Effect]] +[[`std::execution::seq`, `std::execution::unseq`, or no policy][Single threaded.]] +[[`std::execution::par`, `std::execution::par_unseq`][The range is cut into chunks of about 200 * sqrt(`upper_bound`) integers that are handed to `max_threads` worker threads through an atomic counter; each worker owns its sieve and shares the read-only sieving primes. Output is committed in order, so the result is identical to the sequential one.]] +[[`boost::math::execution::cuda`][When the translation unit is compiled by nvcc with `BOOST_MATH_ENABLE_CUDA` defined, the range is sieved on the GPU (`BOOST_MATH_HAS_CUDA_PRIME_SIEVE` is defined in that case). Otherwise the call runs on the CPU with the parallel policy.]] +] + +The `std::execution` overloads are available when the standard library provides the policy types +(libstdc++ 9 and later, MSVC, and libc++ with `-fexperimental-library`); no parallel algorithms and +therefore no TBB are required. Threads are never used when Boost.Math is configured without thread support. + +[h4 Examples] + + #include + #include + #include + #include + #include + #include + #include + + // All primes below one billion, using every core + std::vector primes; + boost::math::prime_reserve(1'000'000'000, primes); + boost::math::prime_sieve(std::execution::par, 1'000'000'000, primes); + + // Count the primes in [10^18, 10^18 + 10^9) on one thread + std::uint64_t n = boost::math::prime_count(1'000'000'000'000'000'000ull, 1'000'000'001'000'000'000ull); + + // Primes just above 2^64 with an arbitrary precision type + using boost::multiprecision::cpp_int; + std::vector big; + boost::math::prime_range(cpp_int(1) << 64, (cpp_int(1) << 64) + 1'000'000, big); + + // A range through any output iterator + std::list small; + boost::math::prime_range(100, 1000, std::back_inserter(small)); + +[h4 Performance] + +Measured with the Google Benchmark harness in `reporting/performance/prime_sieve_performance.cpp` on an +Apple M4 Max (12 performance and 4 efficiency cores, 128 KiB L1D), Apple clang 17, `-O3 -march=native`, +against primesieve 12.16 built from source on the same machine. Times are wall clock in milliseconds. + +[table +[[Task][`boost::math`, 1 thread][primesieve, 1 thread][`boost::math`, 16 threads][primesieve, 16 threads]] +[[count primes below 10[super 8]][2.6][3.2][0.8][]] +[[count primes below 10[super 9]][37][44][5.4][5]] +[[count primes below 10[super 10]][495][566][63][56]] +[[count primes below 10[super 11]][6660][7620][744][654]] +[[store primes below 10[super 9]][89][84][23][]] +[[store primes below 10[super 10]][1051][1027][286][]] +[[count a 10[super 9] window at 10[super 12]][91][108][][]] +[[count a 10[super 9] window at 10[super 15]][167][267][][]] +[[count a 10[super 9] window at 10[super 18]][619][732][][]] +] + +The same comparison on an Intel Core i9-11900K (8 cores, 48 KiB L1D, 512 KiB L2 per core) with GCC 13, +`-O3 -march=native`, primesieve 12.16 built from source there: + +[table +[[Task][`boost::math`, 1 thread][primesieve, 1 thread][`boost::math`, 16 threads][primesieve, 16 threads]] +[[count primes below 10[super 9]][53][51][][]] +[[count primes below 10[super 10]][655][640][124][146]] +[[count primes below 10[super 11]][][8392][1767][1865]] +[[store primes below 10[super 9]][79][70][][]] +[[count a 10[super 9] window at 10[super 12]][128][124][][]] +[[count a 10[super 9] window at 10[super 15]][273][224][][]] +[[count a 10[super 9] window at 10[super 18]][1037][796][][]] +] + +Single threaded this library is 10 to 15 percent ahead on Apple silicon and within 2 to 3 percent of +primesieve on x86 for whole ranges, while primesieve keeps a lead of 20 to 30 percent on x86 for +windows at 10[super 15] and beyond (the bucket sieve is memory bound there and the Intel machine has +a third of the memory bandwidth). With all cores this library is ahead on both machines. When compiled with +AVX-512 VBMI2 support (`-march=native` on Ice Lake or Zen 4 and later) primes are extracted from the +sieve with byte compression instructions; define `BOOST_MATH_PRIME_SIEVE_NO_SIMD` to keep the portable loop. + +Both sieves are O(n log log n) in time and use O(sqrt(n)) memory for the sieving primes (about +four bytes per prime here) plus the segment; the multithreaded path additionally buffers at most +2 * `max_threads` * `chunk_primes` output values. + +The CUDA backend was measured on an NVIDIA GeForce RTX 3060 (CUDA 13.1, `nvcc -O3 -arch=sm_86`) +against the same code running with `std::execution::par` on that machine's Intel Core i9-11900K +(8 cores, 16 threads). It stores 16 bytes per sieving prime on the device, so ranges up to 2[super 64] +need about 3.3 GB of device memory. + +[table +[[Task][`execution::cuda`, RTX 3060][`std::execution::par`, i9-11900K]] +[[count primes below 10[super 9]][8][11]] +[[count primes below 10[super 10]][72][136]] +[[count primes below 10[super 11]][1077][1786]] +[[count a 10[super 9] window at 10[super 12]][13][29]] +[[count a 10[super 9] window at 10[super 15]][75][136]] +[[count a 10[super 9] window at 10[super 18]][656][691]] +[[count a 2[super 30] window below 2[super 64]][2371][2995]] +[[store primes below 10[super 10]][1485][430]] +] + +Counting is where the GPU pays off; storing primes is dominated by the transfer and compaction +of the output (3.6 GB for the primes below 10[super 10]) and is faster on the CPU. Windows near +2[super 64] are dominated by generating the 203 million sieving primes on the host. + +[h4 References] + +* Kim Walisch, [@https://github.com/kimwalisch/primesieve primesieve] and its [@https://github.com/kimwalisch/primesieve/blob/master/doc/ALGORITHMS.md algorithm notes]. +* Tomas Oliveira e Silva, [@https://sweet.ua.pt/tos/software/prime_sieve.html Fast implementation of the segmented sieve of Eratosthenes]. +* Jonathan Sorenson, [@https://link.springer.com/chapter/10.1007/11792086_15 The pseudosquares prime sieve], ANTS VII, 2006. +* Pierre Dusart, [@https://arxiv.org/abs/1002.0442 Estimates of some functions over primes without R.H.], 2010 (the bound used by `prime_reserve`). +* Robert Baillie and Samuel S. Wagstaff Jr., Lucas pseudoprimes, Mathematics of Computation 35 (1980). + +[endsect] [/section:prime_sieve Prime Sieve] + [section:fibonacci_numbers Fibonacci Numbers] diff --git a/doc/sf/polygamma.qbk b/doc/sf/polygamma.qbk index 1e5e0eabfb..7500d4beb3 100644 --- a/doc/sf/polygamma.qbk +++ b/doc/sf/polygamma.qbk @@ -66,7 +66,7 @@ has the general form: [equation polygamma3] The coefficients of the cosine terms can be calculated iteratively starting -from ['C[sub 1,0] = -1] and then using +from ['C[sub 0,1] = -1] and then using [equation polygamma7] diff --git a/doc/sf/pow1p.qbk b/doc/sf/pow1p.qbk new file mode 100644 index 0000000000..38774833e3 --- /dev/null +++ b/doc/sf/pow1p.qbk @@ -0,0 +1,51 @@ +[/ + Copyright Matt Borland 2024 + 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). +] + +[section:pow1p pow1p] + +[h4 Synopsis] + + #include + + namespace boost { + namespace math { + + template + BOOST_MATH_GPU_ENABLED tools::promote_args_t + pow1p(const T1 x, const T2 y, const Policy& pol) + + template + BOOST_MATH_GPU_ENABLED tools::promote_args_t + pow1p(const T1 x, const T2 y) + + }} // namespaces + + +The function `pow1p` computes (1 + x)[super y ] where x and y are real numbers. +This function is particularly useful for scenarios where adding 1 to x before raising it to the power of y is required. +It provides a more numerically stable and efficient way to perform this computation, especially for small values of x. +When x is very small, directly computing (1 + x)[super y ] using standard arithmetic operations can lead to a loss of precision due to floating-point arithmetic limitations. +The pow1p function helps mitigate this issue by internally handling such cases more accurately. + +The type `T` must provide an `fma` function, found either as `std::fma` or by argument dependent lookup. + +[h4 Accuracy] + +In random testing against a 100 digit reference, the error is at most 3 ULP for `float` and `double`, +including tiny /x/ with huge /y/, where `pow(1 + x, y)` loses all precision. +In the plots below, pow1p is shown in blue and `pow(1 + x, y)` in orange; +red points are errors that exceed 100 ULP. + +[$../graphs/pow1p_ulps_y1000.svg] +[$../graphs/pow1p_ulps_y2e20.svg] + +[warning pow1p relies on error-free transforms and IEEE overflow behavior. +Compiling with value-unsafe floating-point optimizations (`-ffast-math`, `/fp:fast`, or icpx's default `-fp-model=fast`) +can make results for small /x/ and large /y/ completely wrong. +With icpx, use `-fp-model=precise`.] + +[endsect] diff --git a/doc/sf/powers.qbk b/doc/sf/powers.qbk index 0f2055039d..68bdfa9e6f 100644 --- a/doc/sf/powers.qbk +++ b/doc/sf/powers.qbk @@ -345,6 +345,7 @@ Otherwise the result is given by: [endsect] [/section:hypot hypot] +[include pow1p.qbk] [include pow.qbk] [include rsqrt.qbk] [include logaddexp.qbk] diff --git a/doc/statistics/chatterjee_correlation.qbk b/doc/statistics/chatterjee_correlation.qbk index 520ab0cc6b..d506407f09 100644 --- a/doc/statistics/chatterjee_correlation.qbk +++ b/doc/statistics/chatterjee_correlation.qbk @@ -72,3 +72,83 @@ Of course, random numbers are not used internally, but the result is not guarant [endsect] [/section:chatterjee_correlation Chatterjee Correlation] + +[section:chatterjee_correlation_mnn Chatterjee Correlation (M nearest neighbours)] + +[heading Synopsis] + +`` +#include + +namespace boost::math::statistics { + + C++17: + template + auto chatterjee_correlation_mnn(ExecutionPolicy&& exec, const Container& u, const Container& v, std::size_t M); + + C++11: + template + auto chatterjee_correlation_mnn(const Container& u, const Container& v, std::size_t M); +} +`` + +[heading Description] + +`chatterjee_correlation_mnn` computes the revised Chatterjee rank correlation of Lin and Han (2021), which +generalises Chatterjee's coefficient by incorporating the `M` right nearest neighbours of each point rather +than only the single right neighbour. +The statistic still consistently estimates the same measure of dependence (between 0 and 1; zero if and only +if X and Y are independent, unity if and only if Y is a measurable function of X), but its use of additional +neighbours boosts the power of the associated independence test. + +The original coefficient `chatterjee_correlation` has a statistical detection boundary of n[super -1/4] for +testing independence, which is substantially weaker than the parametric n[super -1/2] rate. +By letting `M` grow with the sample size (with M/n -> 0), the revised statistic can approach near-parametric +efficiency. + +Let X and Y be random variables, where Y is not constant, and let (X_i, Y_i) be samples sorted so that +X_(0) < X_(1) < ... < X_(n-1). Writing R_i for the rank of Y_i and j_m(i) for the index of the m-th right +nearest neighbour of X_i, the statistic is + +`` + xi_{n,M} = -2 + 6 * sum_i sum_{m=1}^{M} min(R_i, R_{j_m(i)}) / ((n + 1) * (n*M + M*(M + 1) / 4)) +`` + +The complexity is O(n log n + n M). For `M` of order O(1) or O(poly-log n) this is nearly linear; as `M` +approaches `n` it tends to O(n[super 2]). + +An example is given below: + + std::vector X{1,2,3,4,5}; + std::vector Y{1,2,3,4,5}; + using boost::math::statistics::chatterjee_correlation_mnn; + std::size_t M = 2; + double coeff = chatterjee_correlation_mnn(X, Y, M); + +/Nota bene:/ If the input is an integer type the output will be a double precision type. + +[heading Choice of M] + +The asymptotic null variance of the statistic is minimised when `M` is of order sqrt(n), which is a reasonable +default for users who want improved power without the quadratic cost of large `M`. Pushing `M` closer to `n` +increases the power of the independence test against smooth alternatives at the cost of additional computation. +The choice is left to the caller; `M` must satisfy 1 <= M <= n. + +/Nota bene:/ Even at `M` = 1 this statistic is not identical to `chatterjee_correlation`: it uses +min(R_i, R_j) in place of |R_i - R_j| and a different normalisation, so the two agree only up to a term of +order 1/n. Use `chatterjee_correlation` when the original coefficient is required. + +[heading Invariants] + +The function expects at least two samples, a non-constant vector Y, the same number of X's as Y's, and +1 <= M <= n. +If Y is constant, the result is a quiet NaN. +The data set must be sorted by X values. +If there are ties in the values of X, then the statistic is random due to the random breaking of ties. + +[heading References] + +* Lin, Zhexiao, and Fang Han. "On boosting the power of Chatterjee's rank correlation." Biometrika 110.2 (2023): 283-299. [@https://arxiv.org/abs/2108.06828 arXiv:2108.06828]. + +[endsect] +[/section:chatterjee_correlation_mnn Chatterjee Correlation (M nearest neighbours)] \ No newline at end of file diff --git a/doc/statistics/univariate_statistics.qbk b/doc/statistics/univariate_statistics.qbk index 67931e1cf7..e3cc6151c7 100644 --- a/doc/statistics/univariate_statistics.qbk +++ b/doc/statistics/univariate_statistics.qbk @@ -288,7 +288,7 @@ This function simply subtracts 3 from the kurtosis, but it makes eminently clear [heading First four moments] -Simultaneously computes the first four [@https://en.wikipedia.org/wiki/Central_moment central moments] in a single pass through the data: +Simultaneously computes the mean and the second, third, and fourth [@https://en.wikipedia.org/wiki/Central_moment central moments] in a single pass through the data: std::vector v{1,2,3,4,5}; auto [M1, M2, M3, M4] = boost::math::statistics::first_four_moments(v); diff --git a/example/.temps/boost-no-inspect b/example/.temps/boost-no-inspect deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/example/.temps/nonfinite_XML_archive_test.txt b/example/.temps/nonfinite_XML_archive_test.txt deleted file mode 100644 index ef3855685a..0000000000 --- a/example/.temps/nonfinite_XML_archive_test.txt +++ /dev/null @@ -1,21 +0,0 @@ - - - - - 3.141592741e+00 - 3.14159265358979312e+00 - - - -inf - -inf - - - inf - inf - - - nan - nan - - - diff --git a/example/.temps/nonfinite_archive_test.txt b/example/.temps/nonfinite_archive_test.txt deleted file mode 100644 index ca406e223b..0000000000 --- a/example/.temps/nonfinite_archive_test.txt +++ /dev/null @@ -1 +0,0 @@ -22 serialization::archive 17 0 0 3.141592741e+00 3.14159265358979312e+00 -inf -inf inf inf nan nan diff --git a/example/.temps/test.txt b/example/.temps/test.txt deleted file mode 100644 index d6b618ce29..0000000000 --- a/example/.temps/test.txt +++ /dev/null @@ -1 +0,0 @@ -22 serialization::archive 17 inf diff --git a/example/HSO3SO4.cpp b/example/HSO3SO4.cpp index c4462c7932..a07923babb 100644 --- a/example/HSO3SO4.cpp +++ b/example/HSO3SO4.cpp @@ -349,6 +349,10 @@ void test_SO4_spherical() ::std::cout << "Testing spherical:" << ::std::endl; ::std::cout << ::std::endl; + // Six nested loops: the SO3 grid size would mean 5^6 round trips. A coarser grid still + // visits every combination of the six angles' ranges. + const int number_of_intervals = 3; + const float rho1 = 1.0f; const float rho2 = 1.0f; diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 01e97c2f9c..79a87b2713 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -34,8 +34,6 @@ project msvc:/wd4305 msvc:/wd4459 msvc:/wd4456 # declaration of hides previous local declaration. - #-msvc:/Za # nonfinite Serialization examples fail link if disable MS extensions, - # because serialization library is built with MS extensions enabled (default). clang:-Wno-unknown-pragmas clang:-Wno-language-extension-token @@ -95,11 +93,9 @@ test-suite examples : [ run nonfinite_num_facet.cpp ] [ run nonfinite_facet_simple.cpp ] - #[ run nonfinite_num_facet_serialization.cpp /boost/serialization//boost_serialization : : : off:no gcc-mingw:static ] #[ # run lexical_cast_native.cpp ] # Expected to fail on some (but not all) platforms. [ run lexical_cast_nonfinite_facets.cpp ] [ run nonfinite_loopback_ok.cpp ] - #[ run nonfinite_serialization_archives.cpp /boost/serialization//boost_serialization : : : off:no gcc-mingw:static ] [ run nonfinite_facet_sstream.cpp ] [ run constants_eg1.cpp ] diff --git a/example/airy_ulps_plot.cpp b/example/airy_ulps_plot.cpp index 1beccadb99..3ebde29798 100644 --- a/example/airy_ulps_plot.cpp +++ b/example/airy_ulps_plot.cpp @@ -48,6 +48,8 @@ int main() { //plot.title(title); plot.vertical_lines(6); plot.add_fn(ai_coarse); + // The points and the envelope are drawn into PNGs embedded in the SVG if you define BOOST_MATH_USE_LODEPNG + // before including ulps_plot.hpp (link lodepng.cpp), or pass an encoder to png_encoder; otherwise the plot is pure SVG. // You can write the plot to a stream: //std::cout << plot; // Or to a file: diff --git a/example/bernoulli_example.cpp b/example/bernoulli_example.cpp index 5a2c589696..020c678c8a 100644 --- a/example/bernoulli_example.cpp +++ b/example/bernoulli_example.cpp @@ -7,8 +7,10 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifdef _MSC_VER #pragma warning (disable : 4100) // unreferenced formal parameter. #pragma warning (disable : 4127) // conditional expression is constant. +#endif //#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error diff --git a/example/big_seventh.cpp b/example/big_seventh.cpp index bf9835afbf..bec478a6a1 100644 --- a/example/big_seventh.cpp +++ b/example/big_seventh.cpp @@ -60,7 +60,6 @@ void no_et() typedef number, et_on> cpp_bin_float_quad_et_on; typedef number, et_off> cpp_bin_float_quad_et_off; - typedef number, et_off> cpp_bin_float_oct; cpp_bin_float_quad x("42."); diff --git a/example/binomial_coinflip_example.cpp b/example/binomial_coinflip_example.cpp index 5f1826b94a..be66d0a539 100644 --- a/example/binomial_coinflip_example.cpp +++ b/example/binomial_coinflip_example.cpp @@ -162,7 +162,7 @@ The last (0 to 10 heads) must, of course, be 100% probability. */ double probability = 0.3; double q = quantile(flip, probability); - std::cout << "Quantile (flip, " << probability << ") = " << q << std::endl; // Quantile (flip, 0.3) = 3 + std::cout << "Quantile (flip, " << probability << ") = " << q << std::endl; // Quantile (flip, 0.3) = 4 probability = 0.6; q = quantile(flip, probability); std::cout << "Quantile (flip, " << probability << ") = " << q << std::endl; // Quantile (flip, 0.6) = 5 diff --git a/example/binomial_quiz_example.cpp b/example/binomial_quiz_example.cpp index f0b04db458..e85e56863c 100644 --- a/example/binomial_quiz_example.cpp +++ b/example/binomial_quiz_example.cpp @@ -329,14 +329,16 @@ The quantiles (percentiles or percentage points) for a few probability levels: cout << "If guessing then percentiles 1 to 99% will get " << quantile(quiz, 0.01) << " to " << quantile(complement(quiz, 0.01)) << " right." << endl; /*` -Notice that these output integral values because the default policy is `integer_round_outwards`. +Notice that these output integral values because the default policy is `integer_round_up`: +the lower value is the smallest k with `cdf(quiz, k) >= p`, and the upper +the smallest k with `cdf(complement(quiz, k)) <= p`. [pre -Quartiles 2 to 5 -1 standard deviation 2 to 5 -Deciles 1 to 6 -5 to 95% 0 to 7 -2.5 to 97.5% 0 to 8 -2 to 98% 0 to 8 +Quartiles 3 to 5 +1 standard deviation 3 to 5 +Deciles 2 to 6 +5 to 95% 1 to 7 +2.5 to 97.5% 1 to 8 +2 to 98% 1 to 8 ] */ @@ -345,8 +347,7 @@ Deciles 1 to 6 //[discrete_quantile_real /*` Quantiles values are controlled by the __understand_dis_quant quantile policy chosen. -The default is `integer_round_outwards`, -so the lower quantile is rounded down, and the upper quantile is rounded up. +The default is `integer_round_up`, so both quantiles are rounded up. But we might believe that the real values tell us a little more - see __math_discrete. @@ -363,7 +364,6 @@ Or we can now create a (typedef for) policy that has discrete quantiles real using boost::math::policies::policy; using boost::math::policies::discrete_quantile; using boost::math::policies::real; - using boost::math::policies::integer_round_outwards; // Default. typedef boost::math::policies::policy > real_quantile_policy; /*` Add a custom binomial distribution called ``real_quantile_binomial`` that uses ``real_quantile_policy`` @@ -377,8 +377,8 @@ Construct an object of this custom distribution: /*` And use this to show some quantiles - that now have real rather than integer values. */ - cout << "Quartiles " << quantile(quiz, 0.25) << " to " - << quantile(complement(quiz_real, 0.25)) << endl; // Quartiles 2 to 4.6212 + cout << "Quartiles " << quantile(quiz_real, 0.25) << " to " + << quantile(complement(quiz_real, 0.25)) << endl; // Quartiles 2.2821 to 4.6212 cout << "1 standard deviation " << quantile(quiz_real, 0.33) << " to " << quantile(quiz_real, 0.67) << endl; // 1 sd 2.6654 4.194 cout << "Deciles " << quantile(quiz_real, 0.1) << " to " @@ -395,7 +395,7 @@ And use this to show some quantiles - that now have real rather than integer val /*` [pre Real Quantiles -Quartiles 2 to 4.621 +Quartiles 2.282 to 4.621 1 standard deviation 2.665 to 4.194 Deciles 1.349 to 5.758 5 to 95% 0.8374 to 6.456 @@ -506,14 +506,14 @@ Standard deviation is 1.732 So about 2/3 will lie within 1 standard deviation and get between 3 and 5 correct. Mode (the most frequent) is 4 Skewness is 0.2887 -Quartiles 2 to 5 -1 standard deviation 2 to 5 -Deciles 1 to 6 -5 to 95% 0 to 7 -2.5 to 97.5% 0 to 8 -2 to 98% 0 to 8 +Quartiles 3 to 5 +1 standard deviation 3 to 5 +Deciles 2 to 6 +5 to 95% 1 to 7 +2.5 to 97.5% 1 to 8 +2 to 98% 1 to 8 If guessing then percentiles 1 to 99% will get 0 to 8 right. -Quartiles 2 to 4.621 +Quartiles 2.282 to 4.621 1 standard deviation 2.665 to 4.194 Deciles 1.349 to 5.758 5 to 95% 0.8374 to 6.456 diff --git a/example/color_maps_example.cpp b/example/color_maps_example.cpp index 22bb0ed78a..6b890cb4a7 100644 --- a/example/color_maps_example.cpp +++ b/example/color_maps_example.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/example/cstdfloat_example.cpp b/example/cstdfloat_example.cpp index 29af3a2543..e24c75fe66 100644 --- a/example/cstdfloat_example.cpp +++ b/example/cstdfloat_example.cpp @@ -45,7 +45,7 @@ Also provides the correct result for Visual Studio 2010 namespace boost { template -const int max_digits10() +int max_digits10() { // Since max_digits10 is not defined (or wrong) on older systems, define a local max_digits10. // Usage: int m = max_digits10(); diff --git a/example/daubechies_wavelets/find_best_daubechies_interpolator.cpp b/example/daubechies_wavelets/find_best_daubechies_interpolator.cpp index 56c5ed3cba..381ec85218 100644 --- a/example/daubechies_wavelets/find_best_daubechies_interpolator.cpp +++ b/example/daubechies_wavelets/find_best_daubechies_interpolator.cpp @@ -4,6 +4,7 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) +#include #include #include #include @@ -153,11 +154,14 @@ void find_best_interpolator() } { - auto phi_copy = phi; - auto phi_prime_copy = phi_prime; - auto mh = boost::math::detail::matched_holder(std::move(phi_copy), std::move(phi_prime_copy), r, Real(0)); + std::vector> data(phi.size()); + for (size_t i = 0; i < phi.size(); ++i) + { + data[i] = {phi[i], phi_prime[i]}; + } + auto mh = boost::math::detail::matched_holder_aos(std::move(data), r, Real(0)); Real sup = 0; - // call to matched_holder is unchecked, so only go to phi_dense.size() -1. + // call to matched_holder_aos is unchecked, so only go to phi_dense.size() -1. for (size_t i = 0; i < phi_dense.size() - 1; ++i) { Real x = i*dx_dense; diff --git a/example/geometric_examples.cpp b/example/geometric_examples.cpp index 92ea28e565..84e8778341 100644 --- a/example/geometric_examples.cpp +++ b/example/geometric_examples.cpp @@ -23,7 +23,7 @@ For this simple example, we want to avoid throwing an exception (the default policy) and just return infinity. We want to treat the distribution as if it was continuous, so we choose a discrete_quantile policy of real, -rather than the default policy integer_round_outwards. +rather than the default policy integer_round_up. */ #define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error #define BOOST_MATH_DISCRETE_QUANTILE_POLICY real diff --git a/example/gradient_descent_example.cpp b/example/gradient_descent_example.cpp index 25a7ad4dae..158a984928 100755 --- a/example/gradient_descent_example.cpp +++ b/example/gradient_descent_example.cpp @@ -90,7 +90,7 @@ std::vector> init_theta_phi_uniform(size_t N, unsigned seed = return u; } -int main(int argc, char* argv[]) +int main() { /* if (argc != 2) { diff --git a/example/negative_binomial_example1.cpp b/example/negative_binomial_example1.cpp index 92fe48ce27..88fee55cb4 100644 --- a/example/negative_binomial_example1.cpp +++ b/example/negative_binomial_example1.cpp @@ -43,7 +43,7 @@ For this simple example, we want to avoid throwing an exception (the default policy) and just return infinity. We want to treat the distribution as if it was continuous, so we choose a discrete_quantile policy of real, -rather than the default policy integer_round_outwards. +rather than the default policy integer_round_up. */ #define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error #define BOOST_MATH_DISCRETE_QUANTILE_POLICY real diff --git a/example/nonfinite_num_facet_serialization.cpp b/example/nonfinite_num_facet_serialization.cpp deleted file mode 100644 index e2972a10fd..0000000000 --- a/example/nonfinite_num_facet_serialization.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/** nonfinite_num_facet_serialization.cpp - * - * Copyright (c) 2011 Francois Mauger - * Copyright (c) 2011 Paul A. Bristow - * - * 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) - * - * This sample program by Francois Mauger illustrates how to use the - * `boost/math/nonfinite_num_facets.hpp' material from the original - * Floating Point Utilities contribution by Johan Rade. Here it is - * shown how non finite floating number can be serialized and - * deserialized from I/O streams and/or Boost text/XML archives. It - * produces two archives stored in `test.txt' and `test.xml' files. - * - * Tested with Boost 1.44, gcc 4.4.1, Linux/i686 (32bits). - * Tested with Boost.1.46.1 MSVC 10.0 32 bit. - */ - -#ifdef _MSC_VER -# pragma warning(push) -//# pragma warning(disable : 4100) // unreferenced formal parameter. -#endif - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -// from the Floating Point Utilities : -#include - -static const char sep = ','; // Separator of bracketed float and double values. - -// Use max_digits10 (or equivalent) to obtain -// all potentially significant decimal digits for the floating-point types. - -#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS - std::streamsize max_digits10_float = 2 + std::numeric_limits::digits * 30103UL / 100000UL; - std::streamsize max_digits10_double = 2 + std::numeric_limits::digits * 30103UL / 100000UL; -#else - // Can use new C++0X max_digits10 (the maximum potentially significant digits). - std::streamsize max_digits10_float = std::numeric_limits::max_digits10; - std::streamsize max_digits10_double = std::numeric_limits::max_digits10; -#endif - - -/* A class with a float and a double */ -struct foo -{ - foo () : fvalue (3.1415927F), dvalue (3.1415926535897931) - { // Construct using 32 and 64-bit max_digits10 decimal digits value of pi. - } - // Set the values at -infinity : - void minus_infinity () - { - fvalue = -std::numeric_limits::infinity (); - dvalue = -std::numeric_limits::infinity (); - return; - } - // Set the values at +infinity : - void plus_infinity () - { - fvalue = +std::numeric_limits::infinity (); - dvalue = +std::numeric_limits::infinity (); - return; - } - // Set the values at NaN : - void nan () - { - fvalue = +std::numeric_limits::quiet_NaN (); - dvalue = +std::numeric_limits::quiet_NaN (); - return; - } - // Print : - void print (std::ostream & a_out, const std::string & a_title) - { - if (a_title.empty ()) a_out << "foo"; - else a_out << a_title; - a_out << " : " << std::endl; - a_out << "|-- " << "fvalue = "; - a_out.precision (7); - a_out << fvalue << std::endl; - a_out << "`-- " << "dvalue = "; - a_out.precision (15); - a_out << dvalue << std::endl; - return; - } - - // I/O operators : - friend std::ostream & operator<< (std::ostream & a_out, const foo & a_foo); - friend std::istream & operator>> (std::istream & a_in, foo & a_foo); - - // Boost serialization : - template - void serialize (Archive & ar, int /*version*/) - { - ar & BOOST_SERIALIZATION_NVP (fvalue); - ar & BOOST_SERIALIZATION_NVP (dvalue); - return; - } - - // Attributes : - float fvalue; // Single precision floating-point number. - double dvalue; // Double precision floating-point number. -}; - -std::ostream & operator<< (std::ostream & a_out, const foo & a_foo) -{ // Output bracketed FPs, for example "(3.1415927,3.1415926535897931)" - a_out.precision (max_digits10_float); - a_out << "(" << a_foo.fvalue << sep ; - a_out.precision (max_digits10_double); - a_out << a_foo.dvalue << ")"; - return a_out; -} - -std::istream & operator>> (std::istream & a_in, foo & a_foo) -{ // Input bracketed floating-point values into a foo structure, - // for example from "(3.1415927,3.1415926535897931)" - char c = 0; - a_in.get (c); - if (c != '(') - { - std::cerr << "ERROR: operator>> No ( " << std::endl; - a_in.setstate(std::ios::failbit); - return a_in; - } - float f; - a_in >> std::ws >> f; - if (! a_in) - { - return a_in; - } - a_in >> std::ws; - a_in.get (c); - if (c != sep) - { - std::cerr << "ERROR: operator>> c='" << c << "'" << std::endl; - std::cerr << "ERROR: operator>> No '" << sep << "'" << std::endl; - a_in.setstate(std::ios::failbit); - return a_in; - } - double d; - a_in >> std::ws >> d; - if (! a_in) - { - return a_in; - } - a_in >> std::ws; - a_in.get (c); - if (c != ')') - { - std::cerr << "ERROR: operator>> No ) " << std::endl; - a_in.setstate(std::ios::failbit); - return a_in; - } - a_foo.fvalue = f; - a_foo.dvalue = d; - return a_in; -} - -int main (void) -{ - std::clog << std::endl - << "Nonfinite_serialization.cpp' example program." << std::endl; - -#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS - std::cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined, so no max_digits10 available either," - "using our own version instead." << std::endl; -#endif - std::cout << "std::numeric_limits::max_digits10 is " << max_digits10_float << std::endl; - std::cout << "std::numeric_limits::max_digits10 is " << max_digits10_double << std::endl; - - std::locale the_default_locale (std::locale::classic (), - new boost::archive::codecvt_null); - - // Demonstrate use of nonfinite facets with stringstreams. - { - std::clog << "Construct some foo structures with a finite and nonfinites." << std::endl; - foo f0; - foo f1; f1.minus_infinity (); - foo f2; f2.plus_infinity (); - foo f3; f3.nan (); - // Display them. - f0.print (std::clog, "f0"); - f1.print (std::clog, "f1"); - f2.print (std::clog, "f2"); - f3.print (std::clog, "f3"); - std::clog << " Write to a string buffer." << std::endl; - - std::ostringstream oss; - std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put); - oss.imbue (the_out_locale); - oss.precision (max_digits10_double); - oss << f0 << f1 << f2 << f3; - std::clog << "Output is: `" << oss.str () << "'" << std::endl; - std::clog << "Done output to ostringstream." << std::endl; - } - - { - std::clog << "Read foo structures from a string buffer." << std::endl; - - std::string the_string = "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)"; - std::clog << "Input is: `" << the_string << "'" << std::endl; - - std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get); - std::istringstream iss (the_string); - iss.imbue (the_in_locale); - - foo f0, f1, f2, f3; - iss >> f0 >> f1 >> f2 >> f3; - if (! iss) - { - std::cerr << "Format error !" << std::endl; - } - else - { - std::cerr << "Read OK." << std::endl; - f0.print (std::clog, "f0"); - f1.print (std::clog, "f1"); - f2.print (std::clog, "f2"); - f3.print (std::clog, "f3"); - } - std::clog << "Done input from istringstream." << std::endl; - } - - { // Demonstrate use of nonfinite facets for Serialization with Boost text archives. - std::clog << "Serialize (using Boost text archive)." << std::endl; - // Construct some foo structures with a finite and nonfinites. - foo f0; - foo f1; f1.minus_infinity (); - foo f2; f2.plus_infinity (); - foo f3; f3.nan (); - // Display them. - f0.print (std::clog, "f0"); - f1.print (std::clog, "f1"); - f2.print (std::clog, "f2"); - f3.print (std::clog, "f3"); - - std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put); - // Use a temporary folder .temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). - std::ofstream fout ("./.temps/nonfinite_archive_test.txt"); - fout.imbue (the_out_locale); - boost::archive::text_oarchive toar (fout, boost::archive::no_codecvt); - // Write to archive. - toar & f0; - toar & f1; - toar & f2; - toar & f3; - std::clog << "Done." << std::endl; - } - - { - std::clog << "Deserialize (Boost text archive)..." << std::endl; - std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get); - // Use a temporary folder .temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). - std::ifstream fin ("./.temps/nonfinite_archive_test.txt"); - fin.imbue (the_in_locale); - boost::archive::text_iarchive tiar (fin, boost::archive::no_codecvt); - foo f0, f1, f2, f3; - // Read from archive. - tiar & f0; - tiar & f1; - tiar & f2; - tiar & f3; - // Display foos. - f0.print (std::clog, "f0"); - f1.print (std::clog, "f1"); - f2.print (std::clog, "f2"); - f3.print (std::clog, "f3"); - - std::clog << "Done." << std::endl; - } - - { // Demonstrate use of nonfinite facets for Serialization with Boost XML Archive. - std::clog << "Serialize (Boost XML archive)..." << std::endl; - // Construct some foo structures with a finite and nonfinites. - foo f0; - foo f1; f1.minus_infinity (); - foo f2; f2.plus_infinity (); - foo f3; f3.nan (); - // Display foos. - f0.print (std::clog, "f0"); - f1.print (std::clog, "f1"); - f2.print (std::clog, "f2"); - f3.print (std::clog, "f3"); - - std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put); - // Use a temporary folder /.temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). - std::ofstream fout ("./.temps/nonfinite_XML_archive_test.txt"); - fout.imbue (the_out_locale); - boost::archive::xml_oarchive xoar (fout, boost::archive::no_codecvt); - - xoar & BOOST_SERIALIZATION_NVP (f0); - xoar & BOOST_SERIALIZATION_NVP (f1); - xoar & BOOST_SERIALIZATION_NVP (f2); - xoar & BOOST_SERIALIZATION_NVP (f3); - std::clog << "Done." << std::endl; - } - - { - std::clog << "Deserialize (Boost XML archive)..." << std::endl; - std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get); - // Use a temporary folder /.temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). - std::ifstream fin ("./.temps/nonfinite_XML_archive_test.txt"); // Previously written above. - fin.imbue (the_in_locale); - boost::archive::xml_iarchive xiar (fin, boost::archive::no_codecvt); - foo f0, f1, f2, f3; - - xiar & BOOST_SERIALIZATION_NVP (f0); - xiar & BOOST_SERIALIZATION_NVP (f1); - xiar & BOOST_SERIALIZATION_NVP (f2); - xiar & BOOST_SERIALIZATION_NVP (f3); - - f0.print (std::clog, "f0"); - f1.print (std::clog, "f1"); - f2.print (std::clog, "f2"); - f3.print (std::clog, "f3"); - - std::clog << "Done." << std::endl; - } - - std::clog << "End nonfinite_serialization.cpp' example program." << std::endl; - return 0; -} - -/* - -Output: - - Nonfinite_serialization.cpp' example program. - std::numeric_limits::max_digits10 is 8 - std::numeric_limits::max_digits10 is 17 - Construct some foo structures with a finite and nonfinites. - f0 : - |-- fvalue = 3.141593 - `-- dvalue = 3.14159265358979 - f1 : - |-- fvalue = -1.#INF - `-- dvalue = -1.#INF - f2 : - |-- fvalue = 1.#INF - `-- dvalue = 1.#INF - f3 : - |-- fvalue = 1.#QNAN - `-- dvalue = 1.#QNAN - Write to a string buffer. - Output is: `(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)' - Done output to ostringstream. - Read foo structures from a string buffer. - Input is: `(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)' - Read OK. - f0 : - |-- fvalue = 3.141593 - `-- dvalue = 3.14159265358979 - f1 : - |-- fvalue = -1.#INF - `-- dvalue = -1.#INF - f2 : - |-- fvalue = 1.#INF - `-- dvalue = 1.#INF - f3 : - |-- fvalue = 1.#QNAN - `-- dvalue = 1.#QNAN - Done input from istringstream. - Serialize (using Boost text archive). - f0 : - |-- fvalue = 3.141593 - `-- dvalue = 3.14159265358979 - f1 : - |-- fvalue = -1.#INF - `-- dvalue = -1.#INF - f2 : - |-- fvalue = 1.#INF - `-- dvalue = 1.#INF - f3 : - |-- fvalue = 1.#QNAN - `-- dvalue = 1.#QNAN - Done. - Deserialize (Boost text archive)... - f0 : - |-- fvalue = 3.141593 - `-- dvalue = 3.14159265358979 - f1 : - |-- fvalue = -1.#INF - `-- dvalue = -1.#INF - f2 : - |-- fvalue = 1.#INF - `-- dvalue = 1.#INF - f3 : - |-- fvalue = 1.#QNAN - `-- dvalue = 1.#QNAN - Done. - Serialize (Boost XML archive)... - f0 : - |-- fvalue = 3.141593 - `-- dvalue = 3.14159265358979 - f1 : - |-- fvalue = -1.#INF - `-- dvalue = -1.#INF - f2 : - |-- fvalue = 1.#INF - `-- dvalue = 1.#INF - f3 : - |-- fvalue = 1.#QNAN - `-- dvalue = 1.#QNAN - Done. - Deserialize (Boost XML archive)... - f0 : - |-- fvalue = 3.141593 - `-- dvalue = 3.14159265358979 - f1 : - |-- fvalue = -1.#INF - `-- dvalue = -1.#INF - f2 : - |-- fvalue = 1.#INF - `-- dvalue = 1.#INF - f3 : - |-- fvalue = 1.#QNAN - `-- dvalue = 1.#QNAN - Done. - End nonfinite_serialization.cpp' example program. - - */ diff --git a/example/nonfinite_serialization_archives.cpp b/example/nonfinite_serialization_archives.cpp deleted file mode 100644 index 0cb53ff0c0..0000000000 --- a/example/nonfinite_serialization_archives.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/** nonfinite_serialization_archives.cpp -* -* Copyright (c) 2011 Paul A. Bristow -* -* 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) -* -* This very simple program illustrates how to use the -* `boost/math/nonfinite_num_facets.hpp' to obtain C99 -* representation of infinity and NaN. -* From the original Floating Point Utilities contribution by Johan Rade. -* Floating Point Utility library has been accepted into Boost, -* but the utilities are incorporated into Boost.Math library. -* -\file - -\brief A simple example of using non_finite_num facet for -C99 standard output of infinity and NaN in serialization archives. - -\detail This example shows how to create a C99 non-finite locale, -and imbue input and output streams with the non_finite_num put and get facets. -This allow output and input of infinity and NaN in a Standard portable way, -This permits 'loop-back' of output back into input (and portably across different system too). -This is particularly useful when used with Boost.Serialization so that non-finite NaNs and infinity -values in text and xml archives can be handled correctly and portably. - -*/ - - -#ifdef _MSC_VER -# pragma warning(disable : 4127) // conditional expression is constant. -#endif - - -#include -using boost::archive::text_oarchive; -#include -using boost::archive::codecvt_null; -using boost::archive::no_codecvt; - -#include -using boost::math::nonfinite_num_get; -using boost::math::nonfinite_num_put; - -#include -using std::cout; -using std::endl; -using std::cerr; - -#include -using std::setw; -using std::left; -using std::right; -using std::internal; - -#include -using std::string; - -#include -using std::istringstream; - -#include -using std::ofstream; - -#include -using std::numeric_limits; - -#include -using std::locale; - - -/* -Use with serialization archives. - -It is important that the same locale is used -when an archive is saved and when it is loaded. -Otherwise, loading the archive may fail. - -By default, archives are saved and loaded with a classic C locale with a -`boost::archive::codecvt_null` facet added. -Normally you do not have to worry about that. -The constructors for the archive classes, as a side-effect, -imbue the stream with such a locale. - -However, if you want to use the facets `nonfinite_num_put` and `nonfinite_num_get` -with archives,`then you have to manage the locale manually. - -That is done by calling the archive constructor with the flag `boost::archive::no_codecvt`. -Then the archive constructor will not imbue the stream with a new locale. - -The following code shows how to use `nonfinite_num_put` with a `text_oarchive`: - -*/ - -int main() -{ - - if((std::numeric_limits::has_infinity == false) || (std::numeric_limits::infinity() == 0)) - { - std::cout << "Infinity not supported on this platform." << std::endl; - return 0; - } - - if((std::numeric_limits::has_quiet_NaN == false) || (std::numeric_limits::quiet_NaN() == 0)) - { - std::cout << "NaN not supported on this platform." << std::endl; - return 0; - } - - locale default_locale(locale::classic(), new boost::archive::codecvt_null); - // codecvt_null so the archive constructor will not imbue the stream with a new locale. - - locale my_locale(default_locale, new nonfinite_num_put); - // Add nonfinite_num_put facet to locale. - - // Use a temporary folder /.temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). - ofstream ofs("./.temps/test.txt"); - ofs.imbue(my_locale); - - boost::archive::text_oarchive oa(ofs, no_codecvt); - - double x = numeric_limits::infinity(); - oa & x; - -} // int main() - - -/* The same method works with nonfinite_num_get and text_iarchive. - -If you use the trap_infinity and trap_nan flags with a serialization archive, -then you must set the exception mask of the stream. -Serialization archives do not check the stream state. - - -*/ diff --git a/example/policy_eg_8.cpp b/example/policy_eg_8.cpp index a0801d13a3..94e2208c01 100644 --- a/example/policy_eg_8.cpp +++ b/example/policy_eg_8.cpp @@ -58,14 +58,14 @@ namespace boost{ namespace math namespace policies { template - T user_domain_error(const char* function, const char* message, const T& val) + T user_domain_error(const char* /*function*/, const char* /*message*/, const T& /*val*/) { // Ignoring function, message and val for this example, perhaps unhelpfully. cerr << "Domain Error!" << endl; return std::numeric_limits::quiet_NaN(); } template - T user_pole_error(const char* function, const char* message, const T& val) + T user_pole_error(const char* /*function*/, const char* /*message*/, const T& /*val*/) { // Ignoring function, message and val for this example, perhaps unhelpfully. cerr << "Pole Error!" << endl; return std::numeric_limits::quiet_NaN(); diff --git a/example/policy_ref_snip6.cpp b/example/policy_ref_snip6.cpp index 9dc2072974..567b3247e6 100644 --- a/example/policy_ref_snip6.cpp +++ b/example/policy_ref_snip6.cpp @@ -10,13 +10,19 @@ //[policy_ref_snip6 #include -using boost::math::negative_binomial; +using boost::math::negative_binomial_distribution; + +using namespace boost::math::policies; + +typedef negative_binomial_distribution< + double, + policy > + > dist_type; -// Use the default rounding policy integer_round_outwards. // Lower quantile rounded down: -double x = quantile(negative_binomial(20, 0.3), 0.05); // rounded up 27 from 27.3898 +double x = quantile(dist_type(20, 0.3), 0.05); // 27 rounded down from 27.3898 // Upper quantile rounded up: -double y = quantile(complement(negative_binomial(20, 0.3), 0.05)); // rounded down to 69 from 68.1584 +double y = quantile(complement(dist_type(20, 0.3), 0.05)); // 69 rounded up from 68.1584 //] //[/policy_ref_snip6] @@ -25,13 +31,15 @@ using std::cout; using std::endl; int main() { - cout << "quantile(negative_binomial(20, 0.3), 0.05) = "<< x < > " << endl + << "quantile(negative_binomial(20, 0.3), 0.05) = "<< x < -inline int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +inline int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(BOOST_MATH_NAMESPACE::ntl::RR)) { return ::NTL::RR::precision(); } template <> -inline float real_cast(boost::math::ntl::RR t) +inline float real_cast(BOOST_MATH_NAMESPACE::ntl::RR t) { double r; conv(r, t.value()); return static_cast(r); } template <> -inline double real_cast(boost::math::ntl::RR t) +inline double real_cast(BOOST_MATH_NAMESPACE::ntl::RR t) { double r; conv(r, t.value()); @@ -533,40 +533,40 @@ void convert_to_long_result(NTL::RR const& r, Integer& result) } template <> -inline long double real_cast(boost::math::ntl::RR t) +inline long double real_cast(BOOST_MATH_NAMESPACE::ntl::RR t) { long double result(0); detail::convert_to_long_result(t.value(), result); return result; } template <> -inline boost::math::ntl::RR real_cast(boost::math::ntl::RR t) +inline BOOST_MATH_NAMESPACE::ntl::RR real_cast(BOOST_MATH_NAMESPACE::ntl::RR t) { return t; } template <> -inline unsigned real_cast(boost::math::ntl::RR t) +inline unsigned real_cast(BOOST_MATH_NAMESPACE::ntl::RR t) { unsigned result; detail::convert_to_long_result(t.value(), result); return result; } template <> -inline int real_cast(boost::math::ntl::RR t) +inline int real_cast(BOOST_MATH_NAMESPACE::ntl::RR t) { int result; detail::convert_to_long_result(t.value(), result); return result; } template <> -inline long real_cast(boost::math::ntl::RR t) +inline long real_cast(BOOST_MATH_NAMESPACE::ntl::RR t) { long result; detail::convert_to_long_result(t.value(), result); return result; } template <> -inline long long real_cast(boost::math::ntl::RR t) +inline long long real_cast(BOOST_MATH_NAMESPACE::ntl::RR t) { long long result; detail::convert_to_long_result(t.value(), result); @@ -574,7 +574,7 @@ inline long long real_cast(boost::math::ntl::RR } template <> -inline boost::math::ntl::RR max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +inline BOOST_MATH_NAMESPACE::ntl::RR max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(BOOST_MATH_NAMESPACE::ntl::RR)) { static bool has_init = false; static NTL::RR val; @@ -588,7 +588,7 @@ inline boost::math::ntl::RR max_value(BOOST_MATH_EXPLICIT_ } template <> -inline boost::math::ntl::RR min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +inline BOOST_MATH_NAMESPACE::ntl::RR min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(BOOST_MATH_NAMESPACE::ntl::RR)) { static bool has_init = false; static NTL::RR val; @@ -602,7 +602,7 @@ inline boost::math::ntl::RR min_value(BOOST_MATH_EXPLICIT_ } template <> -inline boost::math::ntl::RR log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +inline BOOST_MATH_NAMESPACE::ntl::RR log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(BOOST_MATH_NAMESPACE::ntl::RR)) { static bool has_init = false; static NTL::RR val; @@ -617,7 +617,7 @@ inline boost::math::ntl::RR log_max_value(BOOST_MATH_EXPLI } template <> -inline boost::math::ntl::RR log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +inline BOOST_MATH_NAMESPACE::ntl::RR log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(BOOST_MATH_NAMESPACE::ntl::RR)) { static bool has_init = false; static NTL::RR val; @@ -632,9 +632,9 @@ inline boost::math::ntl::RR log_min_value(BOOST_MATH_EXPLI } template <> -inline boost::math::ntl::RR epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +inline BOOST_MATH_NAMESPACE::ntl::RR epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(BOOST_MATH_NAMESPACE::ntl::RR)) { - return ldexp(boost::math::ntl::RR(1), 1-boost::math::policies::digits >()); + return ldexp(BOOST_MATH_NAMESPACE::ntl::RR(1), 1-BOOST_MATH_NAMESPACE::policies::digits >()); } } // namespace tools @@ -645,13 +645,13 @@ inline boost::math::ntl::RR epsilon(BOOST_MATH_EXPLICIT_TE // namespace constants{ -template<> inline boost::math::ntl::RR pi(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +template<> inline BOOST_MATH_NAMESPACE::ntl::RR pi(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(BOOST_MATH_NAMESPACE::ntl::RR)) { NTL::RR result; ComputePi(result); return result; } -template<> inline boost::math::ntl::RR e(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) +template<> inline BOOST_MATH_NAMESPACE::ntl::RR e(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(BOOST_MATH_NAMESPACE::ntl::RR)) { NTL::RR result; result = 1; @@ -674,13 +674,13 @@ namespace ntl{ { asin_root(RR const& target) : t(target){} - boost::math::tuple operator()(RR const& p) + BOOST_MATH_NAMESPACE::tuple operator()(RR const& p) { RR f0 = sin(p); RR f1 = cos(p); RR f2 = -f0; f0 -= t; - return boost::math::make_tuple(f0, f1, f2); + return BOOST_MATH_NAMESPACE::make_tuple(f0, f1, f2); } private: RR t; @@ -690,11 +690,11 @@ namespace ntl{ { double r; conv(r, z.value()); - return boost::math::tools::halley_iterate( + return BOOST_MATH_NAMESPACE::tools::halley_iterate( asin_root(z), RR(std::asin(r)), - RR(-boost::math::constants::pi()/2), - RR(boost::math::constants::pi()/2), + RR(-BOOST_MATH_NAMESPACE::constants::pi()/2), + RR(BOOST_MATH_NAMESPACE::constants::pi()/2), NTL::RR::precision()); } @@ -702,13 +702,13 @@ namespace ntl{ { acos_root(RR const& target) : t(target){} - boost::math::tuple operator()(RR const& p) + BOOST_MATH_NAMESPACE::tuple operator()(RR const& p) { RR f0 = cos(p); RR f1 = -sin(p); RR f2 = -f0; f0 -= t; - return boost::math::make_tuple(f0, f1, f2); + return BOOST_MATH_NAMESPACE::make_tuple(f0, f1, f2); } private: RR t; @@ -718,11 +718,11 @@ namespace ntl{ { double r; conv(r, z.value()); - return boost::math::tools::halley_iterate( + return BOOST_MATH_NAMESPACE::tools::halley_iterate( acos_root(z), RR(std::acos(r)), - RR(-boost::math::constants::pi()/2), - RR(boost::math::constants::pi()/2), + RR(-BOOST_MATH_NAMESPACE::constants::pi()/2), + RR(BOOST_MATH_NAMESPACE::constants::pi()/2), NTL::RR::precision()); } @@ -730,14 +730,14 @@ namespace ntl{ { atan_root(RR const& target) : t(target){} - boost::math::tuple operator()(RR const& p) + BOOST_MATH_NAMESPACE::tuple operator()(RR const& p) { RR c = cos(p); RR ta = tan(p); RR f0 = ta - t; RR f1 = 1 / (c * c); RR f2 = 2 * ta / (c * c); - return boost::math::make_tuple(f0, f1, f2); + return BOOST_MATH_NAMESPACE::make_tuple(f0, f1, f2); } private: RR t; @@ -747,11 +747,11 @@ namespace ntl{ { double r; conv(r, z.value()); - return boost::math::tools::halley_iterate( + return BOOST_MATH_NAMESPACE::tools::halley_iterate( atan_root(z), RR(std::atan(r)), - -boost::math::constants::pi()/2, - boost::math::constants::pi()/2, + -BOOST_MATH_NAMESPACE::constants::pi()/2, + BOOST_MATH_NAMESPACE::constants::pi()/2, NTL::RR::precision()); } @@ -761,9 +761,9 @@ namespace ntl{ return atan(y / x); if(x < 0) { - return y < 0 ? atan(y / x) - boost::math::constants::pi() : atan(y / x) + boost::math::constants::pi(); + return y < 0 ? atan(y / x) - BOOST_MATH_NAMESPACE::constants::pi() : atan(y / x) + BOOST_MATH_NAMESPACE::constants::pi(); } - return y < 0 ? -boost::math::constants::half_pi() : boost::math::constants::half_pi() ; + return y < 0 ? -BOOST_MATH_NAMESPACE::constants::half_pi() : BOOST_MATH_NAMESPACE::constants::half_pi() ; } inline RR sinh(RR z) @@ -868,8 +868,7 @@ ntl::RR digamma_imp(ntl::RR x, const std::integral_constant* , const Pol } // namespace detail -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_REAL_CONCEPT_HPP diff --git a/include/boost/math/ccmath/abs.hpp b/include/boost/math/ccmath/abs.hpp index db59502ab6..bdc296b1f2 100644 --- a/include/boost/math/ccmath/abs.hpp +++ b/include/boost/math/ccmath/abs.hpp @@ -18,14 +18,14 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { template constexpr T abs_impl(T x) noexcept { - if ((boost::math::ccmath::isnan)(x)) + if ((BOOST_MATH_NAMESPACE::ccmath::isnan)(x)) { return std::numeric_limits::quiet_NaN(); } @@ -44,7 +44,7 @@ constexpr T abs_impl(T x) noexcept } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr T abs(T x) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) @@ -60,7 +60,7 @@ constexpr T abs(T x) noexcept // If abs() is called with an argument of type X for which is_unsigned_v is true and if X // cannot be converted to int by integral promotion (7.3.7), the program is ill-formed. -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr T abs(T x) noexcept { if constexpr (std::is_convertible_v) @@ -76,14 +76,14 @@ constexpr T abs(T x) noexcept constexpr long int labs(long int j) noexcept { - return boost::math::ccmath::abs(j); + return BOOST_MATH_NAMESPACE::ccmath::abs(j); } constexpr long long int llabs(long long int j) noexcept { - return boost::math::ccmath::abs(j); + return BOOST_MATH_NAMESPACE::ccmath::abs(j); } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ABS diff --git a/include/boost/math/ccmath/ceil.hpp b/include/boost/math/ccmath/ceil.hpp index bc264a0be0..0243050fb7 100644 --- a/include/boost/math/ccmath/ceil.hpp +++ b/include/boost/math/ccmath/ceil.hpp @@ -17,14 +17,14 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { template inline constexpr T ceil_impl(T arg) noexcept { - T result = boost::math::ccmath::floor(arg); + T result = BOOST_MATH_NAMESPACE::ccmath::floor(arg); if(result == arg) { @@ -38,15 +38,15 @@ inline constexpr T ceil_impl(T arg) noexcept } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr Real ceil(Real arg) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? arg : - boost::math::ccmath::isinf(arg) ? arg : - boost::math::ccmath::isnan(arg) ? arg : - boost::math::ccmath::detail::ceil_impl(arg); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::detail::ceil_impl(arg); } else { @@ -55,24 +55,24 @@ inline constexpr Real ceil(Real arg) noexcept } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr double ceil(Z arg) noexcept { - return boost::math::ccmath::ceil(static_cast(arg)); + return BOOST_MATH_NAMESPACE::ccmath::ceil(static_cast(arg)); } inline constexpr float ceilf(float arg) noexcept { - return boost::math::ccmath::ceil(arg); + return BOOST_MATH_NAMESPACE::ccmath::ceil(arg); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double ceill(long double arg) noexcept { - return boost::math::ccmath::ceil(arg); + return BOOST_MATH_NAMESPACE::ccmath::ceil(arg); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_CEIL_HPP diff --git a/include/boost/math/ccmath/copysign.hpp b/include/boost/math/ccmath/copysign.hpp index e117e57faa..7637bc57cf 100644 --- a/include/boost/math/ccmath/copysign.hpp +++ b/include/boost/math/ccmath/copysign.hpp @@ -6,41 +6,43 @@ #ifndef BOOST_MATH_CCMATH_COPYSIGN_HPP #define BOOST_MATH_CCMATH_COPYSIGN_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #include #include #include #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { template constexpr T copysign_impl(const T mag, const T sgn) noexcept { - if (boost::math::ccmath::signbit(sgn)) + if (BOOST_MATH_NAMESPACE::ccmath::signbit(sgn)) { - return -boost::math::ccmath::abs(mag); + return -BOOST_MATH_NAMESPACE::ccmath::abs(mag); } else { - return boost::math::ccmath::abs(mag); + return BOOST_MATH_NAMESPACE::ccmath::abs(mag); } } } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real copysign(Real mag, Real sgn) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(mag)) { - return boost::math::ccmath::detail::copysign_impl(mag, sgn); + return BOOST_MATH_NAMESPACE::ccmath::detail::copysign_impl(mag, sgn); } else { @@ -49,13 +51,13 @@ constexpr Real copysign(Real mag, Real sgn) noexcept } } -template +BOOST_MATH_EXPORT template constexpr auto copysign(T1 mag, T2 sgn) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(mag)) { - using promoted_type = boost::math::tools::promote_args_t; - return boost::math::ccmath::copysign(static_cast(mag), static_cast(sgn)); + using promoted_type = BOOST_MATH_NAMESPACE::tools::promote_args_t; + return BOOST_MATH_NAMESPACE::ccmath::copysign(static_cast(mag), static_cast(sgn)); } else { @@ -66,16 +68,16 @@ constexpr auto copysign(T1 mag, T2 sgn) noexcept constexpr float copysignf(float mag, float sgn) noexcept { - return boost::math::ccmath::copysign(mag, sgn); + return BOOST_MATH_NAMESPACE::ccmath::copysign(mag, sgn); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double copysignl(long double mag, long double sgn) noexcept { - return boost::math::ccmath::copysign(mag, sgn); + return BOOST_MATH_NAMESPACE::ccmath::copysign(mag, sgn); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_COPYSIGN_HPP diff --git a/include/boost/math/ccmath/detail/config.hpp b/include/boost/math/ccmath/detail/config.hpp index 097d69a16b..4304f4a374 100644 --- a/include/boost/math/ccmath/detail/config.hpp +++ b/include/boost/math/ccmath/detail/config.hpp @@ -8,9 +8,11 @@ #ifndef BOOST_MATH_CCMATH_DETAIL_CONFIG #define BOOST_MATH_CCMATH_DETAIL_CONFIG +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include diff --git a/include/boost/math/ccmath/detail/swap.hpp b/include/boost/math/ccmath/detail/swap.hpp index ccca9601ce..7aa804ea02 100644 --- a/include/boost/math/ccmath/detail/swap.hpp +++ b/include/boost/math/ccmath/detail/swap.hpp @@ -6,7 +6,9 @@ #ifndef BOOST_MATH_CCMATH_DETAIL_SWAP_HPP #define BOOST_MATH_CCMATH_DETAIL_SWAP_HPP -namespace boost::math::ccmath::detail { +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath::detail { template inline constexpr void swap(T& x, T& y) noexcept @@ -16,6 +18,6 @@ inline constexpr void swap(T& x, T& y) noexcept y = temp; } -} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_DETAIL_SWAP_HPP diff --git a/include/boost/math/ccmath/div.hpp b/include/boost/math/ccmath/div.hpp index 613a22f3f5..46f66e788e 100644 --- a/include/boost/math/ccmath/div.hpp +++ b/include/boost/math/ccmath/div.hpp @@ -6,15 +6,18 @@ #ifndef BOOST_MATH_CCMATH_DIV_HPP #define BOOST_MATH_CCMATH_DIV_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#include #include +#endif #include #ifdef BOOST_MATH_NO_CCMATH #error "The header can only be used in C++17 and later." #endif -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -34,14 +37,14 @@ inline constexpr ReturnType div_impl(const Z x, const Z y) noexcept } // Namespace detail // Used for types other than built-ins (e.g. boost multiprecision) -template +BOOST_MATH_EXPORT template struct div_t { Z quot; Z rem; }; -template +BOOST_MATH_EXPORT template inline constexpr auto div(Z x, Z y) noexcept { if constexpr (std::is_same_v) @@ -62,7 +65,7 @@ inline constexpr auto div(Z x, Z y) noexcept } else { - return detail::div_impl>(x, y); + return detail::div_impl>(x, y); } } @@ -81,6 +84,6 @@ inline constexpr std::imaxdiv_t imaxdiv(std::intmax_t x, std::intmax_t y) noexce return detail::div_impl(x, y); } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_DIV_HPP diff --git a/include/boost/math/ccmath/fabs.hpp b/include/boost/math/ccmath/fabs.hpp index 02191db3d1..e8082895bc 100644 --- a/include/boost/math/ccmath/fabs.hpp +++ b/include/boost/math/ccmath/fabs.hpp @@ -16,26 +16,26 @@ #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template inline constexpr auto fabs(T x) noexcept { - return boost::math::ccmath::abs(x); + return BOOST_MATH_NAMESPACE::ccmath::abs(x); } inline constexpr float fabsf(float x) noexcept { - return boost::math::ccmath::abs(x); + return BOOST_MATH_NAMESPACE::ccmath::abs(x); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double fabsl(long double x) noexcept { - return boost::math::ccmath::abs(x); + return BOOST_MATH_NAMESPACE::ccmath::abs(x); } #endif -} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_FABS diff --git a/include/boost/math/ccmath/fdim.hpp b/include/boost/math/ccmath/fdim.hpp index d6b4e25cec..9e8d736da2 100644 --- a/include/boost/math/ccmath/fdim.hpp +++ b/include/boost/math/ccmath/fdim.hpp @@ -15,7 +15,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -38,21 +38,21 @@ constexpr T fdim_impl(const T x, const T y) noexcept } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real fdim(Real x, Real y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::isnan(x)) + if (BOOST_MATH_NAMESPACE::ccmath::isnan(x)) { return x; } - else if (boost::math::ccmath::isnan(y)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return y; } - return boost::math::ccmath::detail::fdim_impl(x, y); + return BOOST_MATH_NAMESPACE::ccmath::detail::fdim_impl(x, y); } else { @@ -61,13 +61,13 @@ constexpr Real fdim(Real x, Real y) noexcept } } -template +BOOST_MATH_EXPORT template constexpr auto fdim(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_t; - return boost::math::ccmath::fdim(promoted_type(x), promoted_type(y)); + using promoted_type = BOOST_MATH_NAMESPACE::tools::promote_args_t; + return BOOST_MATH_NAMESPACE::ccmath::fdim(promoted_type(x), promoted_type(y)); } else { @@ -78,16 +78,16 @@ constexpr auto fdim(T1 x, T2 y) noexcept constexpr float fdimf(float x, float y) noexcept { - return boost::math::ccmath::fdim(x, y); + return BOOST_MATH_NAMESPACE::ccmath::fdim(x, y); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double fdiml(long double x, long double y) noexcept { - return boost::math::ccmath::fdim(x, y); + return BOOST_MATH_NAMESPACE::ccmath::fdim(x, y); } #endif -} // Namespace boost::math::ccmath +} BOOST_MATH_NAMESPACE_END // Namespace boost::math::ccmath #endif // BOOST_MATH_CCMATH_FDIM_HPP diff --git a/include/boost/math/ccmath/floor.hpp b/include/boost/math/ccmath/floor.hpp index 5afed7d0ca..c4d31636f3 100644 --- a/include/boost/math/ccmath/floor.hpp +++ b/include/boost/math/ccmath/floor.hpp @@ -15,9 +15,11 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -91,15 +93,15 @@ inline constexpr T floor_impl(T arg) noexcept } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr Real floor(Real arg) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? arg : - boost::math::ccmath::isinf(arg) ? arg : - boost::math::ccmath::isnan(arg) ? arg : - boost::math::ccmath::detail::floor_impl(arg); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::detail::floor_impl(arg); } else { @@ -108,24 +110,24 @@ inline constexpr Real floor(Real arg) noexcept } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr double floor(Z arg) noexcept { - return boost::math::ccmath::floor(static_cast(arg)); + return BOOST_MATH_NAMESPACE::ccmath::floor(static_cast(arg)); } inline constexpr float floorf(float arg) noexcept { - return boost::math::ccmath::floor(arg); + return BOOST_MATH_NAMESPACE::ccmath::floor(arg); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double floorl(long double arg) noexcept { - return boost::math::ccmath::floor(arg); + return BOOST_MATH_NAMESPACE::ccmath::floor(arg); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_FLOOR_HPP diff --git a/include/boost/math/ccmath/fma.hpp b/include/boost/math/ccmath/fma.hpp index c4d16c8ae5..4bec162905 100644 --- a/include/boost/math/ccmath/fma.hpp +++ b/include/boost/math/ccmath/fma.hpp @@ -15,7 +15,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -43,33 +43,33 @@ constexpr T fma_imp(const T x, const T y, const T z) noexcept } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real fma(Real x, Real y, Real z) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (x == 0 && boost::math::ccmath::isinf(y)) + if (x == 0 && BOOST_MATH_NAMESPACE::ccmath::isinf(y)) { return std::numeric_limits::quiet_NaN(); } - else if (y == 0 && boost::math::ccmath::isinf(x)) + else if (y == 0 && BOOST_MATH_NAMESPACE::ccmath::isinf(x)) { return std::numeric_limits::quiet_NaN(); } - else if (boost::math::ccmath::isnan(x)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(x)) { return std::numeric_limits::quiet_NaN(); } - else if (boost::math::ccmath::isnan(y)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return std::numeric_limits::quiet_NaN(); } - else if (boost::math::ccmath::isnan(z)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(z)) { return std::numeric_limits::quiet_NaN(); } - return boost::math::ccmath::detail::fma_imp(x, y, z); + return BOOST_MATH_NAMESPACE::ccmath::detail::fma_imp(x, y, z); } else { @@ -78,7 +78,7 @@ constexpr Real fma(Real x, Real y, Real z) noexcept } } -template +BOOST_MATH_EXPORT template constexpr auto fma(T1 x, T2 y, T3 z) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) @@ -104,7 +104,7 @@ constexpr auto fma(T1 x, T2 y, T3 z) noexcept >>>; #endif - return boost::math::ccmath::fma(promoted_type(x), promoted_type(y), promoted_type(z)); + return BOOST_MATH_NAMESPACE::ccmath::fma(promoted_type(x), promoted_type(y), promoted_type(z)); } else { @@ -115,16 +115,16 @@ constexpr auto fma(T1 x, T2 y, T3 z) noexcept constexpr float fmaf(float x, float y, float z) noexcept { - return boost::math::ccmath::fma(x, y, z); + return BOOST_MATH_NAMESPACE::ccmath::fma(x, y, z); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double fmal(long double x, long double y, long double z) noexcept { - return boost::math::ccmath::fma(x, y, z); + return BOOST_MATH_NAMESPACE::ccmath::fma(x, y, z); } #endif -} // Namespace boost::math::ccmath +} BOOST_MATH_NAMESPACE_END // Namespace boost::math::ccmath #endif // BOOST_MATH_CCMATH_FMA_HPP diff --git a/include/boost/math/ccmath/fmax.hpp b/include/boost/math/ccmath/fmax.hpp index 8a0d17d03e..98a6ba389c 100644 --- a/include/boost/math/ccmath/fmax.hpp +++ b/include/boost/math/ccmath/fmax.hpp @@ -15,7 +15,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -34,21 +34,21 @@ constexpr T fmax_impl(const T x, const T y) noexcept } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real fmax(Real x, Real y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::isnan(x)) + if (BOOST_MATH_NAMESPACE::ccmath::isnan(x)) { return y; } - else if (boost::math::ccmath::isnan(y)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return x; } - return boost::math::ccmath::detail::fmax_impl(x, y); + return BOOST_MATH_NAMESPACE::ccmath::detail::fmax_impl(x, y); } else { @@ -57,13 +57,13 @@ constexpr Real fmax(Real x, Real y) noexcept } } -template +BOOST_MATH_EXPORT template constexpr auto fmax(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_t; - return boost::math::ccmath::fmax(static_cast(x), static_cast(y)); + using promoted_type = BOOST_MATH_NAMESPACE::tools::promote_args_t; + return BOOST_MATH_NAMESPACE::ccmath::fmax(static_cast(x), static_cast(y)); } else { @@ -74,16 +74,16 @@ constexpr auto fmax(T1 x, T2 y) noexcept constexpr float fmaxf(float x, float y) noexcept { - return boost::math::ccmath::fmax(x, y); + return BOOST_MATH_NAMESPACE::ccmath::fmax(x, y); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double fmaxl(long double x, long double y) noexcept { - return boost::math::ccmath::fmax(x, y); + return BOOST_MATH_NAMESPACE::ccmath::fmax(x, y); } #endif -} // Namespace boost::math::ccmath +} BOOST_MATH_NAMESPACE_END // Namespace boost::math::ccmath #endif // BOOST_MATH_CCMATH_FMAX_HPP diff --git a/include/boost/math/ccmath/fmin.hpp b/include/boost/math/ccmath/fmin.hpp index 29885b69c8..496eb9ae7b 100644 --- a/include/boost/math/ccmath/fmin.hpp +++ b/include/boost/math/ccmath/fmin.hpp @@ -15,7 +15,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -34,21 +34,21 @@ constexpr T fmin_impl(const T x, const T y) noexcept } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real fmin(Real x, Real y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::isnan(x)) + if (BOOST_MATH_NAMESPACE::ccmath::isnan(x)) { return y; } - else if (boost::math::ccmath::isnan(y)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return x; } - return boost::math::ccmath::detail::fmin_impl(x, y); + return BOOST_MATH_NAMESPACE::ccmath::detail::fmin_impl(x, y); } else { @@ -57,13 +57,13 @@ constexpr Real fmin(Real x, Real y) noexcept } } -template +BOOST_MATH_EXPORT template constexpr auto fmin(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_t; - return boost::math::ccmath::fmin(static_cast(x), static_cast(y)); + using promoted_type = BOOST_MATH_NAMESPACE::tools::promote_args_t; + return BOOST_MATH_NAMESPACE::ccmath::fmin(static_cast(x), static_cast(y)); } else { @@ -74,16 +74,16 @@ constexpr auto fmin(T1 x, T2 y) noexcept constexpr float fminf(float x, float y) noexcept { - return boost::math::ccmath::fmin(x, y); + return BOOST_MATH_NAMESPACE::ccmath::fmin(x, y); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double fminl(long double x, long double y) noexcept { - return boost::math::ccmath::fmin(x, y); + return BOOST_MATH_NAMESPACE::ccmath::fmin(x, y); } #endif -} // Namespace boost::math::ccmath +} BOOST_MATH_NAMESPACE_END // Namespace boost::math::ccmath #endif // BOOST_MATH_CCMATH_FMIN_HPP diff --git a/include/boost/math/ccmath/fmod.hpp b/include/boost/math/ccmath/fmod.hpp index ba61cc95a2..8772184342 100644 --- a/include/boost/math/ccmath/fmod.hpp +++ b/include/boost/math/ccmath/fmod.hpp @@ -12,14 +12,16 @@ #error "The header can only be used in C++17 and later." #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -43,37 +45,37 @@ constexpr T fmod_impl(T x, T y) } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real fmod(Real x, Real y) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::abs(x) == static_cast(0) && y != static_cast(0)) + if (BOOST_MATH_NAMESPACE::ccmath::abs(x) == static_cast(0) && y != static_cast(0)) { return x; } - else if (boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(y)) + else if (BOOST_MATH_NAMESPACE::ccmath::isinf(x) && !BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return std::numeric_limits::quiet_NaN(); } - else if (boost::math::ccmath::abs(y) == static_cast(0) && !boost::math::ccmath::isnan(x)) + else if (BOOST_MATH_NAMESPACE::ccmath::abs(y) == static_cast(0) && !BOOST_MATH_NAMESPACE::ccmath::isnan(x)) { return std::numeric_limits::quiet_NaN(); } - else if (boost::math::ccmath::isinf(y) && boost::math::ccmath::isfinite(x)) + else if (BOOST_MATH_NAMESPACE::ccmath::isinf(y) && BOOST_MATH_NAMESPACE::ccmath::isfinite(x)) { return x; } - else if (boost::math::ccmath::isnan(x)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(x)) { return x; } - else if (boost::math::ccmath::isnan(y)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return y; } - return boost::math::ccmath::detail::fmod_impl(x, y); + return BOOST_MATH_NAMESPACE::ccmath::detail::fmod_impl(x, y); } else { @@ -82,13 +84,13 @@ constexpr Real fmod(Real x, Real y) } } -template +BOOST_MATH_EXPORT template constexpr auto fmod(T1 x, T2 y) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_t; - return boost::math::ccmath::fmod(promoted_type(x), promoted_type(y)); + using promoted_type = BOOST_MATH_NAMESPACE::tools::promote_args_t; + return BOOST_MATH_NAMESPACE::ccmath::fmod(promoted_type(x), promoted_type(y)); } else { @@ -99,16 +101,16 @@ constexpr auto fmod(T1 x, T2 y) constexpr float fmodf(float x, float y) { - return boost::math::ccmath::fmod(x, y); + return BOOST_MATH_NAMESPACE::ccmath::fmod(x, y); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double fmodl(long double x, long double y) { - return boost::math::ccmath::fmod(x, y); + return BOOST_MATH_NAMESPACE::ccmath::fmod(x, y); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_FMOD_HPP diff --git a/include/boost/math/ccmath/fpclassify.hpp b/include/boost/math/ccmath/fpclassify.hpp index ce0728a277..3cc1963037 100644 --- a/include/boost/math/ccmath/fpclassify.hpp +++ b/include/boost/math/ccmath/fpclassify.hpp @@ -18,31 +18,31 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr int fpclassify BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - return (boost::math::ccmath::isnan)(x) ? FP_NAN : - (boost::math::ccmath::isinf)(x) ? FP_INFINITE : - boost::math::ccmath::abs(x) == T(0) ? FP_ZERO : - boost::math::ccmath::abs(x) > 0 && boost::math::ccmath::abs(x) < (std::numeric_limits::min)() ? FP_SUBNORMAL : FP_NORMAL; + return (BOOST_MATH_NAMESPACE::ccmath::isnan)(x) ? FP_NAN : + (BOOST_MATH_NAMESPACE::ccmath::isinf)(x) ? FP_INFINITE : + BOOST_MATH_NAMESPACE::ccmath::abs(x) == T(0) ? FP_ZERO : + BOOST_MATH_NAMESPACE::ccmath::abs(x) > 0 && BOOST_MATH_NAMESPACE::ccmath::abs(x) < (std::numeric_limits::min)() ? FP_SUBNORMAL : FP_NORMAL; } else { - using boost::math::fpclassify; + using BOOST_MATH_NAMESPACE::fpclassify; return (fpclassify)(x); } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr int fpclassify(Z x) { - return boost::math::ccmath::fpclassify(static_cast(x)); + return BOOST_MATH_NAMESPACE::ccmath::fpclassify(static_cast(x)); } -} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_FPCLASSIFY diff --git a/include/boost/math/ccmath/frexp.hpp b/include/boost/math/ccmath/frexp.hpp index 6c200cb641..aaf07fab97 100644 --- a/include/boost/math/ccmath/frexp.hpp +++ b/include/boost/math/ccmath/frexp.hpp @@ -17,7 +17,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -60,16 +60,16 @@ inline constexpr Real frexp_impl(Real arg, int* exp) } // namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr Real frexp(Real arg, int* exp) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { return arg == Real(0) ? detail::frexp_zero_impl(arg, exp) : arg == Real(-0) ? detail::frexp_zero_impl(arg, exp) : - boost::math::ccmath::isinf(arg) ? detail::frexp_zero_impl(arg, exp) : - boost::math::ccmath::isnan(arg) ? detail::frexp_zero_impl(arg, exp) : - boost::math::ccmath::detail::frexp_impl(arg, exp); + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? detail::frexp_zero_impl(arg, exp) : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? detail::frexp_zero_impl(arg, exp) : + BOOST_MATH_NAMESPACE::ccmath::detail::frexp_impl(arg, exp); } else { @@ -78,24 +78,24 @@ inline constexpr Real frexp(Real arg, int* exp) } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr double frexp(Z arg, int* exp) { - return boost::math::ccmath::frexp(static_cast(arg), exp); + return BOOST_MATH_NAMESPACE::ccmath::frexp(static_cast(arg), exp); } inline constexpr float frexpf(float arg, int* exp) { - return boost::math::ccmath::frexp(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::frexp(arg, exp); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double frexpl(long double arg, int* exp) { - return boost::math::ccmath::frexp(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::frexp(arg, exp); } #endif -} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_FREXP_HPP diff --git a/include/boost/math/ccmath/hypot.hpp b/include/boost/math/ccmath/hypot.hpp index 34dd5ab2c0..6e788bd462 100644 --- a/include/boost/math/ccmath/hypot.hpp +++ b/include/boost/math/ccmath/hypot.hpp @@ -13,28 +13,31 @@ #error "The header can only be used in C++17 and later." #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include #include #include #include +#include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { template constexpr T hypot_impl(T x, T y) noexcept { - x = boost::math::ccmath::abs(x); - y = boost::math::ccmath::abs(y); + x = BOOST_MATH_NAMESPACE::ccmath::abs(x); + y = BOOST_MATH_NAMESPACE::ccmath::abs(y); if (y > x) { - boost::math::ccmath::detail::swap(x, y); + BOOST_MATH_NAMESPACE::ccmath::detail::swap(x, y); } if(x * std::numeric_limits::epsilon() >= y) @@ -43,39 +46,57 @@ constexpr T hypot_impl(T x, T y) noexcept } T rat = y / x; - return x * boost::math::ccmath::sqrt(1 + rat * rat); + return x * BOOST_MATH_NAMESPACE::ccmath::sqrt(1 + rat * rat); +} + +template +constexpr T hypot_impl(T x, T y, T z) noexcept +{ + x = BOOST_MATH_NAMESPACE::ccmath::abs(x); + y = BOOST_MATH_NAMESPACE::ccmath::abs(y); + z = BOOST_MATH_NAMESPACE::ccmath::abs(z); + + T a = BOOST_MATH_NAMESPACE::ccmath::fmax(BOOST_MATH_NAMESPACE::ccmath::fmax(x, y), z); + if (a == 0) + { + return a; + } + + return a * BOOST_MATH_NAMESPACE::ccmath::sqrt((x / a) * (x / a) + + (y / a) * (y / a) + + (z / a) * (z / a)); } } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real hypot(Real x, Real y) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::abs(x) == static_cast(0)) + if (BOOST_MATH_NAMESPACE::ccmath::abs(x) == static_cast(0)) { - return boost::math::ccmath::abs(y); + return BOOST_MATH_NAMESPACE::ccmath::abs(y); } - else if (boost::math::ccmath::abs(y) == static_cast(0)) + else if (BOOST_MATH_NAMESPACE::ccmath::abs(y) == static_cast(0)) { - return boost::math::ccmath::abs(x); + return BOOST_MATH_NAMESPACE::ccmath::abs(x); } // Return +inf even if the other argument is NaN - else if (boost::math::ccmath::isinf(x) || boost::math::ccmath::isinf(y)) + else if (BOOST_MATH_NAMESPACE::ccmath::isinf(x) || BOOST_MATH_NAMESPACE::ccmath::isinf(y)) { return std::numeric_limits::infinity(); } - else if (boost::math::ccmath::isnan(x)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(x)) { return x; } - else if (boost::math::ccmath::isnan(y)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return y; } - return boost::math::ccmath::detail::hypot_impl(x, y); + return BOOST_MATH_NAMESPACE::ccmath::detail::hypot_impl(x, y); } else { @@ -84,13 +105,13 @@ constexpr Real hypot(Real x, Real y) noexcept } } -template +BOOST_MATH_EXPORT template constexpr auto hypot(T1 x, T2 y) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_t; - return boost::math::ccmath::hypot(static_cast(x), static_cast(y)); + using promoted_type = BOOST_MATH_NAMESPACE::tools::promote_args_t; + return BOOST_MATH_NAMESPACE::ccmath::hypot(static_cast(x), static_cast(y)); } else { @@ -101,16 +122,64 @@ constexpr auto hypot(T1 x, T2 y) noexcept constexpr float hypotf(float x, float y) noexcept { - return boost::math::ccmath::hypot(x, y); + return BOOST_MATH_NAMESPACE::ccmath::hypot(x, y); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double hypotl(long double x, long double y) noexcept { - return boost::math::ccmath::hypot(x, y); + return BOOST_MATH_NAMESPACE::ccmath::hypot(x, y); } #endif -} // Namespaces +BOOST_MATH_EXPORT template , bool> = true> +constexpr Real hypot(Real x, Real y, Real z) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + if (BOOST_MATH_NAMESPACE::ccmath::isinf(x) || BOOST_MATH_NAMESPACE::ccmath::isinf(y) || BOOST_MATH_NAMESPACE::ccmath::isinf(z)) + { + return std::numeric_limits::infinity(); + } + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(x)) + { + return x; + } + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(y)) + { + return y; + } + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(z)) + { + return z; + } + + return detail::hypot_impl(x, y, z); + } + else + { + using std::hypot; + return hypot(x, y, z); + } +} + +BOOST_MATH_EXPORT template +constexpr auto hypot(T1 x, T2 y, T3 z) noexcept +{ + if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) + { + using promoted_type = tools::promote_args_t; + return BOOST_MATH_NAMESPACE::ccmath::hypot(static_cast(x), + static_cast(y), + static_cast(z)); + } + else + { + using std::hypot; + return hypot(x, y, z); + } +} + +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_HYPOT_HPP diff --git a/include/boost/math/ccmath/ilogb.hpp b/include/boost/math/ccmath/ilogb.hpp index 6ec6fca9aa..cf229e7aa6 100644 --- a/include/boost/math/ccmath/ilogb.hpp +++ b/include/boost/math/ccmath/ilogb.hpp @@ -17,18 +17,18 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { // If arg is not zero, infinite, or NaN, the value returned is exactly equivalent to static_cast(std::logb(arg)) -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr int ilogb(Real arg) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? FP_ILOGB0 : - boost::math::ccmath::isinf(arg) ? INT_MAX : - boost::math::ccmath::isnan(arg) ? FP_ILOGBNAN : - static_cast(boost::math::ccmath::logb(arg)); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? FP_ILOGB0 : + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? INT_MAX : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? FP_ILOGBNAN : + static_cast(BOOST_MATH_NAMESPACE::ccmath::logb(arg)); } else { @@ -37,24 +37,24 @@ inline constexpr int ilogb(Real arg) noexcept } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr int ilogb(Z arg) noexcept { - return boost::math::ccmath::ilogb(static_cast(arg)); + return BOOST_MATH_NAMESPACE::ccmath::ilogb(static_cast(arg)); } inline constexpr int ilogbf(float arg) noexcept { - return boost::math::ccmath::ilogb(arg); + return BOOST_MATH_NAMESPACE::ccmath::ilogb(arg); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr int ilogbl(long double arg) noexcept { - return boost::math::ccmath::ilogb(arg); + return BOOST_MATH_NAMESPACE::ccmath::ilogb(arg); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ILOGB_HPP diff --git a/include/boost/math/ccmath/isfinite.hpp b/include/boost/math/ccmath/isfinite.hpp index 328742ccad..9ea7562ecc 100644 --- a/include/boost/math/ccmath/isfinite.hpp +++ b/include/boost/math/ccmath/isfinite.hpp @@ -15,9 +15,9 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template inline constexpr bool isfinite(T x) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) @@ -26,11 +26,11 @@ inline constexpr bool isfinite(T x) // equivalent to casting the integral argument arg to double (e.g. static_cast(arg)) if constexpr (std::is_integral_v) { - return !boost::math::ccmath::isinf(static_cast(x)) && !boost::math::ccmath::isnan(static_cast(x)); + return !BOOST_MATH_NAMESPACE::ccmath::isinf(static_cast(x)) && !BOOST_MATH_NAMESPACE::ccmath::isnan(static_cast(x)); } else { - return !boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(x); + return !BOOST_MATH_NAMESPACE::ccmath::isinf(x) && !BOOST_MATH_NAMESPACE::ccmath::isnan(x); } } else @@ -48,6 +48,6 @@ inline constexpr bool isfinite(T x) } } -} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ISFINITE diff --git a/include/boost/math/ccmath/isgreater.hpp b/include/boost/math/ccmath/isgreater.hpp index 7b29f9bffe..c7902982c1 100644 --- a/include/boost/math/ccmath/isgreater.hpp +++ b/include/boost/math/ccmath/isgreater.hpp @@ -14,14 +14,14 @@ #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template inline constexpr bool isgreater(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y)) + if (BOOST_MATH_NAMESPACE::ccmath::isnan(x) || BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return false; } @@ -37,6 +37,6 @@ inline constexpr bool isgreater(T1 x, T2 y) noexcept } } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ISGREATER_HPP diff --git a/include/boost/math/ccmath/isgreaterequal.hpp b/include/boost/math/ccmath/isgreaterequal.hpp index d6586a95d8..ad4a8a9222 100644 --- a/include/boost/math/ccmath/isgreaterequal.hpp +++ b/include/boost/math/ccmath/isgreaterequal.hpp @@ -14,14 +14,14 @@ #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template inline constexpr bool isgreaterequal(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y)) + if (BOOST_MATH_NAMESPACE::ccmath::isnan(x) || BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return false; } @@ -37,6 +37,6 @@ inline constexpr bool isgreaterequal(T1 x, T2 y) noexcept } } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ISGREATEREQUAL_HPP diff --git a/include/boost/math/ccmath/isinf.hpp b/include/boost/math/ccmath/isinf.hpp index f1b0e7c726..5c53d31154 100644 --- a/include/boost/math/ccmath/isinf.hpp +++ b/include/boost/math/ccmath/isinf.hpp @@ -13,9 +13,9 @@ #error "The header can only be used in C++17 and later." #endif -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template constexpr bool isinf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) @@ -43,7 +43,7 @@ constexpr bool isinf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) noexcept } else { - using boost::math::isinf; + using BOOST_MATH_NAMESPACE::isinf; if constexpr (!std::is_integral_v) { @@ -56,6 +56,6 @@ constexpr bool isinf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) noexcept } } -} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ISINF diff --git a/include/boost/math/ccmath/isless.hpp b/include/boost/math/ccmath/isless.hpp index bf923e6f80..b2960934d8 100644 --- a/include/boost/math/ccmath/isless.hpp +++ b/include/boost/math/ccmath/isless.hpp @@ -14,14 +14,14 @@ #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template inline constexpr bool isless(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y)) + if (BOOST_MATH_NAMESPACE::ccmath::isnan(x) || BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return false; } @@ -37,6 +37,6 @@ inline constexpr bool isless(T1 x, T2 y) noexcept } } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ISLESS_HPP diff --git a/include/boost/math/ccmath/islessequal.hpp b/include/boost/math/ccmath/islessequal.hpp index 075d4cad67..a7b31ad6c1 100644 --- a/include/boost/math/ccmath/islessequal.hpp +++ b/include/boost/math/ccmath/islessequal.hpp @@ -14,14 +14,14 @@ #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template inline constexpr bool islessequal(T1 x, T2 y) noexcept { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y)) + if (BOOST_MATH_NAMESPACE::ccmath::isnan(x) || BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return false; } @@ -37,6 +37,6 @@ inline constexpr bool islessequal(T1 x, T2 y) noexcept } } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ISLESSEQUAL_HPP diff --git a/include/boost/math/ccmath/isnan.hpp b/include/boost/math/ccmath/isnan.hpp index 753f2079b2..4ffcc22e68 100644 --- a/include/boost/math/ccmath/isnan.hpp +++ b/include/boost/math/ccmath/isnan.hpp @@ -13,9 +13,9 @@ #error "The header can only be used in C++17 and later." #endif -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template inline constexpr bool isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) @@ -24,7 +24,7 @@ inline constexpr bool isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) } else { - using boost::math::isnan; + using BOOST_MATH_NAMESPACE::isnan; if constexpr (!std::is_integral_v) { @@ -37,6 +37,6 @@ inline constexpr bool isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) } } -} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ISNAN diff --git a/include/boost/math/ccmath/isnormal.hpp b/include/boost/math/ccmath/isnormal.hpp index cf5a4d1536..3d4e10237c 100644 --- a/include/boost/math/ccmath/isnormal.hpp +++ b/include/boost/math/ccmath/isnormal.hpp @@ -16,17 +16,17 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template inline constexpr bool isnormal(T x) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { return x == T(0) ? false : - boost::math::ccmath::isinf(x) ? false : - boost::math::ccmath::isnan(x) ? false : - boost::math::ccmath::abs(x) < (std::numeric_limits::min)() ? false : true; + BOOST_MATH_NAMESPACE::ccmath::isinf(x) ? false : + BOOST_MATH_NAMESPACE::ccmath::isnan(x) ? false : + BOOST_MATH_NAMESPACE::ccmath::abs(x) < (std::numeric_limits::min)() ? false : true; } else { @@ -42,6 +42,6 @@ inline constexpr bool isnormal(T x) } } } -} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ISNORMAL_HPP diff --git a/include/boost/math/ccmath/isunordered.hpp b/include/boost/math/ccmath/isunordered.hpp index 9d55db0d38..35f1f6eb57 100644 --- a/include/boost/math/ccmath/isunordered.hpp +++ b/include/boost/math/ccmath/isunordered.hpp @@ -14,14 +14,14 @@ #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template +BOOST_MATH_EXPORT template inline constexpr bool isunordered(const T x, const T y) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - return boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y); + return BOOST_MATH_NAMESPACE::ccmath::isnan(x) || BOOST_MATH_NAMESPACE::ccmath::isnan(y); } else { @@ -30,6 +30,6 @@ inline constexpr bool isunordered(const T x, const T y) noexcept } } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ISUNORDERED_HPP diff --git a/include/boost/math/ccmath/ldexp.hpp b/include/boost/math/ccmath/ldexp.hpp index 3e2cd3610f..e65228f0d1 100644 --- a/include/boost/math/ccmath/ldexp.hpp +++ b/include/boost/math/ccmath/ldexp.hpp @@ -13,12 +13,14 @@ #error "The header can only be used in C++17 and later." #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -41,15 +43,15 @@ inline constexpr Real ldexp_impl(Real arg, int exp) noexcept } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr Real ldexp(Real arg, int exp) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? arg : - (boost::math::ccmath::isinf)(arg) ? arg : - (boost::math::ccmath::isnan)(arg) ? arg : - boost::math::ccmath::detail::ldexp_impl(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? arg : + (BOOST_MATH_NAMESPACE::ccmath::isinf)(arg) ? arg : + (BOOST_MATH_NAMESPACE::ccmath::isnan)(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::detail::ldexp_impl(arg, exp); } else { @@ -58,24 +60,24 @@ inline constexpr Real ldexp(Real arg, int exp) noexcept } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr double ldexp(Z arg, int exp) noexcept { - return boost::math::ccmath::ldexp(static_cast(arg), exp); + return BOOST_MATH_NAMESPACE::ccmath::ldexp(static_cast(arg), exp); } inline constexpr float ldexpf(float arg, int exp) noexcept { - return boost::math::ccmath::ldexp(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::ldexp(arg, exp); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double ldexpl(long double arg, int exp) noexcept { - return boost::math::ccmath::ldexp(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::ldexp(arg, exp); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_LDEXP_HPP diff --git a/include/boost/math/ccmath/logb.hpp b/include/boost/math/ccmath/logb.hpp index 9a0c4a1c02..49498f0b79 100644 --- a/include/boost/math/ccmath/logb.hpp +++ b/include/boost/math/ccmath/logb.hpp @@ -17,7 +17,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -29,32 +29,32 @@ template constexpr T logb_impl(T arg) noexcept { int exp = 0; - boost::math::ccmath::frexp(arg, &exp); + BOOST_MATH_NAMESPACE::ccmath::frexp(arg, &exp); return static_cast(exp - 1); } } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real logb(Real arg) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - if (boost::math::ccmath::abs(arg) == Real(0)) + if (BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0)) { return -std::numeric_limits::infinity(); } - else if (boost::math::ccmath::isinf(arg)) + else if (BOOST_MATH_NAMESPACE::ccmath::isinf(arg)) { return std::numeric_limits::infinity(); } - else if (boost::math::ccmath::isnan(arg)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(arg)) { return arg; } - return boost::math::ccmath::detail::logb_impl(arg); + return BOOST_MATH_NAMESPACE::ccmath::detail::logb_impl(arg); } else { @@ -63,24 +63,24 @@ constexpr Real logb(Real arg) noexcept } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr double logb(Z arg) noexcept { - return boost::math::ccmath::logb(static_cast(arg)); + return BOOST_MATH_NAMESPACE::ccmath::logb(static_cast(arg)); } constexpr float logbf(float arg) noexcept { - return boost::math::ccmath::logb(arg); + return BOOST_MATH_NAMESPACE::ccmath::logb(arg); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double logbl(long double arg) noexcept { - return boost::math::ccmath::logb(arg); + return BOOST_MATH_NAMESPACE::ccmath::logb(arg); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_LOGB_HPP diff --git a/include/boost/math/ccmath/modf.hpp b/include/boost/math/ccmath/modf.hpp index 87b6a4b508..797cb5aa2a 100644 --- a/include/boost/math/ccmath/modf.hpp +++ b/include/boost/math/ccmath/modf.hpp @@ -17,7 +17,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -25,7 +25,7 @@ template inline constexpr Real modf_error_impl(Real x, Real* iptr) { *iptr = x; - return boost::math::ccmath::abs(x) == Real(0) ? x : + return BOOST_MATH_NAMESPACE::ccmath::abs(x) == Real(0) ? x : x > Real(0) ? Real(0) : -Real(0); } @@ -39,21 +39,21 @@ inline constexpr Real modf_nan_impl(Real x, Real* iptr) template inline constexpr Real modf_impl(Real x, Real* iptr) { - *iptr = boost::math::ccmath::trunc(x); + *iptr = BOOST_MATH_NAMESPACE::ccmath::trunc(x); return (x - *iptr); } } // Namespace detail -template +BOOST_MATH_EXPORT template inline constexpr Real modf(Real x, Real* iptr) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - return boost::math::ccmath::abs(x) == Real(0) ? detail::modf_error_impl(x, iptr) : - boost::math::ccmath::isinf(x) ? detail::modf_error_impl(x, iptr) : - boost::math::ccmath::isnan(x) ? detail::modf_nan_impl(x, iptr) : - boost::math::ccmath::detail::modf_impl(x, iptr); + return BOOST_MATH_NAMESPACE::ccmath::abs(x) == Real(0) ? detail::modf_error_impl(x, iptr) : + BOOST_MATH_NAMESPACE::ccmath::isinf(x) ? detail::modf_error_impl(x, iptr) : + BOOST_MATH_NAMESPACE::ccmath::isnan(x) ? detail::modf_nan_impl(x, iptr) : + BOOST_MATH_NAMESPACE::ccmath::detail::modf_impl(x, iptr); } else { @@ -64,16 +64,16 @@ inline constexpr Real modf(Real x, Real* iptr) inline constexpr float modff(float x, float* iptr) { - return boost::math::ccmath::modf(x, iptr); + return BOOST_MATH_NAMESPACE::ccmath::modf(x, iptr); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double modfl(long double x, long double* iptr) { - return boost::math::ccmath::modf(x, iptr); + return BOOST_MATH_NAMESPACE::ccmath::modf(x, iptr); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_MODF_HPP diff --git a/include/boost/math/ccmath/next.hpp b/include/boost/math/ccmath/next.hpp index f03fe5cfa8..14c8ef909b 100644 --- a/include/boost/math/ccmath/next.hpp +++ b/include/boost/math/ccmath/next.hpp @@ -13,9 +13,11 @@ #error "The header can only be used in C++17 and later." #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include @@ -32,7 +34,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -76,10 +78,10 @@ constexpr T normalize_value(const T& val, const std::true_type&) static_assert(std::numeric_limits::is_specialized, "Type T must be specialized."); static_assert(std::numeric_limits::radix != 2, "Type T must be specialized."); - std::intmax_t shift = static_cast(std::numeric_limits::digits) - static_cast(boost::math::ccmath::ilogb(val)) - 1; - T result = boost::math::ccmath::scalbn(val, shift); - result = boost::math::ccmath::round(result); - return boost::math::ccmath::scalbn(result, -shift); + std::intmax_t shift = static_cast(std::numeric_limits::digits) - static_cast(BOOST_MATH_NAMESPACE::ccmath::ilogb(val)) - 1; + T result = BOOST_MATH_NAMESPACE::ccmath::scalbn(val, shift); + result = BOOST_MATH_NAMESPACE::ccmath::round(result); + return BOOST_MATH_NAMESPACE::ccmath::scalbn(result, -shift); } template @@ -109,7 +111,7 @@ constexpr T get_smallest_value() template constexpr T calc_min_shifted(const std::true_type&) { - return boost::math::ccmath::ldexp(tools::min_value(), tools::digits() + 1); + return BOOST_MATH_NAMESPACE::ccmath::ldexp(tools::min_value(), tools::digits() + 1); } template @@ -118,7 +120,7 @@ constexpr T calc_min_shifted(const std::false_type&) static_assert(std::numeric_limits::is_specialized, "Type T must be specialized."); static_assert(std::numeric_limits::radix != 2, "Type T must be specialized."); - return boost::math::ccmath::scalbn(tools::min_value(), std::numeric_limits::digits + 1); + return BOOST_MATH_NAMESPACE::ccmath::scalbn(tools::min_value(), std::numeric_limits::digits + 1); } template @@ -128,7 +130,7 @@ constexpr T get_min_shift_value() return val; } -template > +template > struct exponent_type { using type = int; @@ -140,7 +142,7 @@ struct exponent_type using type = typename T::backend_type::exponent_type; }; -template > +template > using exponent_type_t = typename exponent_type::type; template @@ -150,7 +152,7 @@ constexpr T float_next_imp(const T& val, const std::true_type&) exponent_type expon {}; - int fpclass = boost::math::ccmath::fpclassify(val); + int fpclass = BOOST_MATH_NAMESPACE::ccmath::fpclassify(val); if (fpclass == FP_NAN) { @@ -171,7 +173,7 @@ constexpr T float_next_imp(const T& val, const std::true_type&) } if ((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) - && (boost::math::ccmath::fabs(val) < detail::get_min_shift_value()) + && (BOOST_MATH_NAMESPACE::ccmath::fabs(val) < detail::get_min_shift_value()) && (val != -tools::min_value())) { // @@ -179,14 +181,14 @@ constexpr T float_next_imp(const T& val, const std::true_type&) // would not be a denorm, then shift the input, increment, and shift back. // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set. // - return boost::math::ccmath::ldexp(boost::math::ccmath::detail::float_next(static_cast(boost::math::ccmath::ldexp(val, 2 * tools::digits()))), -2 * tools::digits()); + return BOOST_MATH_NAMESPACE::ccmath::ldexp(BOOST_MATH_NAMESPACE::ccmath::detail::float_next(static_cast(BOOST_MATH_NAMESPACE::ccmath::ldexp(val, 2 * tools::digits()))), -2 * tools::digits()); } - if (-0.5f == boost::math::ccmath::frexp(val, &expon)) + if (-0.5f == BOOST_MATH_NAMESPACE::ccmath::frexp(val, &expon)) { --expon; // reduce exponent when val is a power of two, and negative. } - T diff = boost::math::ccmath::ldexp(static_cast(1), expon - tools::digits()); + T diff = BOOST_MATH_NAMESPACE::ccmath::ldexp(static_cast(1), expon - tools::digits()); if(diff == 0) { diff = detail::get_smallest_value(); @@ -207,7 +209,7 @@ constexpr T float_next_imp(const T& val, const std::false_type&) exponent_type expon {}; - int fpclass = boost::math::ccmath::fpclassify(val); + int fpclass = BOOST_MATH_NAMESPACE::ccmath::fpclassify(val); if (fpclass == FP_NAN) { @@ -228,7 +230,7 @@ constexpr T float_next_imp(const T& val, const std::false_type&) } if ((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) - && (boost::math::ccmath::fabs(val) < detail::get_min_shift_value()) + && (BOOST_MATH_NAMESPACE::ccmath::fabs(val) < detail::get_min_shift_value()) && (val != -tools::min_value())) { // @@ -236,16 +238,16 @@ constexpr T float_next_imp(const T& val, const std::false_type&) // would not be a denorm, then shift the input, increment, and shift back. // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set. // - return boost::math::ccmath::scalbn(boost::math::ccmath::detail::float_next(static_cast(boost::math::ccmath::scalbn(val, 2 * std::numeric_limits::digits))), -2 * std::numeric_limits::digits); + return BOOST_MATH_NAMESPACE::ccmath::scalbn(BOOST_MATH_NAMESPACE::ccmath::detail::float_next(static_cast(BOOST_MATH_NAMESPACE::ccmath::scalbn(val, 2 * std::numeric_limits::digits))), -2 * std::numeric_limits::digits); } - expon = 1 + boost::math::ccmath::ilogb(val); - if(-1 == boost::math::ccmath::scalbn(val, -expon) * std::numeric_limits::radix) + expon = 1 + BOOST_MATH_NAMESPACE::ccmath::ilogb(val); + if(-1 == BOOST_MATH_NAMESPACE::ccmath::scalbn(val, -expon) * std::numeric_limits::radix) { --expon; // reduce exponent when val is a power of base, and negative. } - T diff = boost::math::ccmath::scalbn(static_cast(1), expon - std::numeric_limits::digits); + T diff = BOOST_MATH_NAMESPACE::ccmath::scalbn(static_cast(1), expon - std::numeric_limits::digits); if(diff == 0) { diff = detail::get_smallest_value(); @@ -267,7 +269,7 @@ constexpr T float_prior_imp(const T& val, const std::true_type&) exponent_type expon {}; - int fpclass = boost::math::ccmath::fpclassify(val); + int fpclass = BOOST_MATH_NAMESPACE::ccmath::fpclassify(val); if (fpclass == FP_NAN) { @@ -288,7 +290,7 @@ constexpr T float_prior_imp(const T& val, const std::true_type&) } if ((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) - && (boost::math::ccmath::fabs(val) < detail::get_min_shift_value()) + && (BOOST_MATH_NAMESPACE::ccmath::fabs(val) < detail::get_min_shift_value()) && (val != tools::min_value())) { // @@ -296,15 +298,15 @@ constexpr T float_prior_imp(const T& val, const std::true_type&) // would not be a denorm, then shift the input, increment, and shift back. // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set. // - return boost::math::ccmath::ldexp(boost::math::ccmath::detail::float_prior(static_cast(boost::math::ccmath::ldexp(val, 2 * tools::digits()))), -2 * tools::digits()); + return BOOST_MATH_NAMESPACE::ccmath::ldexp(BOOST_MATH_NAMESPACE::ccmath::detail::float_prior(static_cast(BOOST_MATH_NAMESPACE::ccmath::ldexp(val, 2 * tools::digits()))), -2 * tools::digits()); } - if(T remain = boost::math::ccmath::frexp(val, &expon); remain == 0.5f) + if(T remain = BOOST_MATH_NAMESPACE::ccmath::frexp(val, &expon); remain == 0.5f) { --expon; // when val is a power of two we must reduce the exponent } - T diff = boost::math::ccmath::ldexp(static_cast(1), expon - tools::digits()); + T diff = BOOST_MATH_NAMESPACE::ccmath::ldexp(static_cast(1), expon - tools::digits()); if(diff == 0) { diff = detail::get_smallest_value(); @@ -326,7 +328,7 @@ constexpr T float_prior_imp(const T& val, const std::false_type&) exponent_type expon {}; - int fpclass = boost::math::ccmath::fpclassify(val); + int fpclass = BOOST_MATH_NAMESPACE::ccmath::fpclassify(val); if (fpclass == FP_NAN) { @@ -347,7 +349,7 @@ constexpr T float_prior_imp(const T& val, const std::false_type&) } if ((fpclass != FP_SUBNORMAL) && (fpclass != FP_ZERO) - && (boost::math::ccmath::fabs(val) < detail::get_min_shift_value()) + && (BOOST_MATH_NAMESPACE::ccmath::fabs(val) < detail::get_min_shift_value()) && (val != tools::min_value())) { // @@ -355,17 +357,17 @@ constexpr T float_prior_imp(const T& val, const std::false_type&) // would not be a denorm, then shift the input, increment, and shift back. // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set. // - return boost::math::ccmath::scalbn(boost::math::ccmath::detail::float_prior(static_cast(boost::math::ccmath::scalbn(val, 2 * std::numeric_limits::digits))), -2 * std::numeric_limits::digits); + return BOOST_MATH_NAMESPACE::ccmath::scalbn(BOOST_MATH_NAMESPACE::ccmath::detail::float_prior(static_cast(BOOST_MATH_NAMESPACE::ccmath::scalbn(val, 2 * std::numeric_limits::digits))), -2 * std::numeric_limits::digits); } - expon = 1 + boost::math::ccmath::ilogb(val); + expon = 1 + BOOST_MATH_NAMESPACE::ccmath::ilogb(val); - if (T remain = boost::math::ccmath::scalbn(val, -expon); remain * std::numeric_limits::radix == 1) + if (T remain = BOOST_MATH_NAMESPACE::ccmath::scalbn(val, -expon); remain * std::numeric_limits::radix == 1) { --expon; // when val is a power of two we must reduce the exponent } - T diff = boost::math::ccmath::scalbn(static_cast(1), expon - std::numeric_limits::digits); + T diff = BOOST_MATH_NAMESPACE::ccmath::scalbn(static_cast(1), expon - std::numeric_limits::digits); if (diff == 0) { diff = detail::get_smallest_value(); @@ -381,22 +383,22 @@ constexpr result_type float_prior(const T& val) } // namespace detail -template > +BOOST_MATH_EXPORT template > constexpr result_type nextafter(const T& val, const U& direction) { if (BOOST_MATH_IS_CONSTANT_EVALUATED(val)) { - if (boost::math::ccmath::isnan(val)) + if (BOOST_MATH_NAMESPACE::ccmath::isnan(val)) { return val; } - else if (boost::math::ccmath::isnan(direction)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(direction)) { return direction; } else if (val < direction) { - return boost::math::ccmath::detail::float_next(val); + return BOOST_MATH_NAMESPACE::ccmath::detail::float_next(val); } else if (val == direction) { @@ -406,7 +408,7 @@ constexpr result_type nextafter(const T& val, const U& direction) return direction; } - return boost::math::ccmath::detail::float_prior(val); + return BOOST_MATH_NAMESPACE::ccmath::detail::float_prior(val); } else { @@ -417,22 +419,22 @@ constexpr result_type nextafter(const T& val, const U& direction) constexpr float nextafterf(float val, float direction) { - return boost::math::ccmath::nextafter(val, direction); + return BOOST_MATH_NAMESPACE::ccmath::nextafter(val, direction); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double nextafterl(long double val, long double direction) { - return boost::math::ccmath::nextafter(val, direction); + return BOOST_MATH_NAMESPACE::ccmath::nextafter(val, direction); } -template , typename return_type = std::conditional_t, double, T>> +BOOST_MATH_EXPORT template , typename return_type = std::conditional_t, double, T>> constexpr return_type nexttoward(T val, long double direction) { if (BOOST_MATH_IS_CONSTANT_EVALUATED(val)) { - return static_cast(boost::math::ccmath::nextafter(static_cast(val), direction)); + return static_cast(BOOST_MATH_NAMESPACE::ccmath::nextafter(static_cast(val), direction)); } else { @@ -443,16 +445,16 @@ constexpr return_type nexttoward(T val, long double direction) constexpr float nexttowardf(float val, long double direction) { - return boost::math::ccmath::nexttoward(val, direction); + return BOOST_MATH_NAMESPACE::ccmath::nexttoward(val, direction); } constexpr long double nexttowardl(long double val, long double direction) { - return boost::math::ccmath::nexttoward(val, direction); + return BOOST_MATH_NAMESPACE::ccmath::nexttoward(val, direction); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_NEXT_HPP diff --git a/include/boost/math/ccmath/remainder.hpp b/include/boost/math/ccmath/remainder.hpp index b57420b879..613b915bab 100644 --- a/include/boost/math/ccmath/remainder.hpp +++ b/include/boost/math/ccmath/remainder.hpp @@ -12,7 +12,9 @@ #error "The header can only be used in C++17 and later." #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include @@ -20,7 +22,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -29,7 +31,7 @@ constexpr T remainder_impl(const T x, const T y) { T n = 0; - if (T fractional_part = boost::math::ccmath::modf((x / y), &n); fractional_part > static_cast(1.0/2)) + if (T fractional_part = BOOST_MATH_NAMESPACE::ccmath::modf((x / y), &n); fractional_part > static_cast(1.0/2)) { ++n; } @@ -43,29 +45,29 @@ constexpr T remainder_impl(const T x, const T y) } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real remainder(Real x, Real y) { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(y)) + if (BOOST_MATH_NAMESPACE::ccmath::isinf(x) && !BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return std::numeric_limits::quiet_NaN(); } - else if (boost::math::ccmath::abs(y) == static_cast(0) && !boost::math::ccmath::isnan(x)) + else if (BOOST_MATH_NAMESPACE::ccmath::abs(y) == static_cast(0) && !BOOST_MATH_NAMESPACE::ccmath::isnan(x)) { return std::numeric_limits::quiet_NaN(); } - else if (boost::math::ccmath::isnan(x)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(x)) { return x; } - else if (boost::math::ccmath::isnan(y)) + else if (BOOST_MATH_NAMESPACE::ccmath::isnan(y)) { return y; } - return boost::math::ccmath::detail::remainder_impl(x, y); + return BOOST_MATH_NAMESPACE::ccmath::detail::remainder_impl(x, y); } else { @@ -74,13 +76,13 @@ constexpr Real remainder(Real x, Real y) } } -template +BOOST_MATH_EXPORT template constexpr auto remainder(T1 x, T2 y) { if (BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - using promoted_type = boost::math::tools::promote_args_t; - return boost::math::ccmath::remainder(promoted_type(x), promoted_type(y)); + using promoted_type = BOOST_MATH_NAMESPACE::tools::promote_args_t; + return BOOST_MATH_NAMESPACE::ccmath::remainder(promoted_type(x), promoted_type(y)); } else { @@ -91,16 +93,16 @@ constexpr auto remainder(T1 x, T2 y) constexpr float remainderf(float x, float y) { - return boost::math::ccmath::remainder(x, y); + return BOOST_MATH_NAMESPACE::ccmath::remainder(x, y); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS constexpr long double remainderl(long double x, long double y) { - return boost::math::ccmath::remainder(x, y); + return BOOST_MATH_NAMESPACE::ccmath::remainder(x, y); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_REMAINDER_HPP diff --git a/include/boost/math/ccmath/round.hpp b/include/boost/math/ccmath/round.hpp index 776f341c5c..55afdaaaf9 100644 --- a/include/boost/math/ccmath/round.hpp +++ b/include/boost/math/ccmath/round.hpp @@ -6,7 +6,9 @@ #ifndef BOOST_MATH_CCMATH_ROUND_HPP #define BOOST_MATH_CCMATH_ROUND_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #ifdef BOOST_MATH_NO_CCMATH @@ -18,7 +20,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -28,14 +30,14 @@ template inline constexpr T round_impl(T arg) noexcept { T iptr = 0; - const T x = boost::math::ccmath::modf(arg, &iptr); + const T x = BOOST_MATH_NAMESPACE::ccmath::modf(arg, &iptr); constexpr T half = T(1)/2; if(x >= half && iptr >= 0) { return iptr + 1; } - else if(boost::math::ccmath::abs(x) >= half && iptr <= 0) + else if(BOOST_MATH_NAMESPACE::ccmath::abs(x) >= half && iptr <= 0) { return iptr - 1; } @@ -69,15 +71,15 @@ inline constexpr ReturnType int_round_impl(T arg) } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr Real round(Real arg) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? arg : - boost::math::ccmath::isinf(arg) ? arg : - boost::math::ccmath::isnan(arg) ? arg : - boost::math::ccmath::detail::round_impl(arg); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::detail::round_impl(arg); } else { @@ -86,33 +88,33 @@ inline constexpr Real round(Real arg) noexcept } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr double round(Z arg) noexcept { - return boost::math::ccmath::round(static_cast(arg)); + return BOOST_MATH_NAMESPACE::ccmath::round(static_cast(arg)); } inline constexpr float roundf(float arg) noexcept { - return boost::math::ccmath::round(arg); + return BOOST_MATH_NAMESPACE::ccmath::round(arg); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double roundl(long double arg) noexcept { - return boost::math::ccmath::round(arg); + return BOOST_MATH_NAMESPACE::ccmath::round(arg); } #endif -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr long lround(Real arg) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? 0l : - boost::math::ccmath::isinf(arg) ? 0l : - boost::math::ccmath::isnan(arg) ? 0l : - boost::math::ccmath::detail::int_round_impl(arg); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? 0l : + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? 0l : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? 0l : + BOOST_MATH_NAMESPACE::ccmath::detail::int_round_impl(arg); } else { @@ -121,33 +123,33 @@ inline constexpr long lround(Real arg) } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr long lround(Z arg) { - return boost::math::ccmath::lround(static_cast(arg)); + return BOOST_MATH_NAMESPACE::ccmath::lround(static_cast(arg)); } inline constexpr long lroundf(float arg) { - return boost::math::ccmath::lround(arg); + return BOOST_MATH_NAMESPACE::ccmath::lround(arg); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long lroundl(long double arg) { - return boost::math::ccmath::lround(arg); + return BOOST_MATH_NAMESPACE::ccmath::lround(arg); } #endif -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr long long llround(Real arg) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? 0ll : - boost::math::ccmath::isinf(arg) ? 0ll : - boost::math::ccmath::isnan(arg) ? 0ll : - boost::math::ccmath::detail::int_round_impl(arg); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? 0ll : + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? 0ll : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? 0ll : + BOOST_MATH_NAMESPACE::ccmath::detail::int_round_impl(arg); } else { @@ -156,24 +158,24 @@ inline constexpr long long llround(Real arg) } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr long llround(Z arg) { - return boost::math::ccmath::llround(static_cast(arg)); + return BOOST_MATH_NAMESPACE::ccmath::llround(static_cast(arg)); } inline constexpr long long llroundf(float arg) { - return boost::math::ccmath::llround(arg); + return BOOST_MATH_NAMESPACE::ccmath::llround(arg); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long long llroundl(long double arg) { - return boost::math::ccmath::llround(arg); + return BOOST_MATH_NAMESPACE::ccmath::llround(arg); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_ROUND_HPP diff --git a/include/boost/math/ccmath/scalbln.hpp b/include/boost/math/ccmath/scalbln.hpp index 2321f14c89..47bae89ab9 100644 --- a/include/boost/math/ccmath/scalbln.hpp +++ b/include/boost/math/ccmath/scalbln.hpp @@ -12,23 +12,25 @@ #error "The header can only be used in C++17 and later." #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr Real scalbln(Real arg, long exp) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? arg : - boost::math::ccmath::isinf(arg) ? arg : - boost::math::ccmath::isnan(arg) ? arg : - boost::math::ccmath::detail::scalbn_impl(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::detail::scalbn_impl(arg, exp); } else { @@ -37,24 +39,24 @@ inline constexpr Real scalbln(Real arg, long exp) noexcept } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr double scalbln(Z arg, long exp) noexcept { - return boost::math::ccmath::scalbln(static_cast(arg), exp); + return BOOST_MATH_NAMESPACE::ccmath::scalbln(static_cast(arg), exp); } inline constexpr float scalblnf(float arg, long exp) noexcept { - return boost::math::ccmath::scalbln(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::scalbln(arg, exp); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double scalblnl(long double arg, long exp) noexcept { - return boost::math::ccmath::scalbln(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::scalbln(arg, exp); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_SCALBLN_HPP diff --git a/include/boost/math/ccmath/scalbn.hpp b/include/boost/math/ccmath/scalbn.hpp index 2026822525..4145cda00d 100644 --- a/include/boost/math/ccmath/scalbn.hpp +++ b/include/boost/math/ccmath/scalbn.hpp @@ -13,12 +13,14 @@ #error "The header can only be used in C++17 and later." #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -41,15 +43,15 @@ inline constexpr Real scalbn_impl(Real arg, Z exp) noexcept } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr Real scalbn(Real arg, int exp) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? arg : - boost::math::ccmath::isinf(arg) ? arg : - boost::math::ccmath::isnan(arg) ? arg : - boost::math::ccmath::detail::scalbn_impl(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::detail::scalbn_impl(arg, exp); } else { @@ -58,24 +60,24 @@ inline constexpr Real scalbn(Real arg, int exp) noexcept } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr double scalbn(Z arg, int exp) noexcept { - return boost::math::ccmath::scalbn(static_cast(arg), exp); + return BOOST_MATH_NAMESPACE::ccmath::scalbn(static_cast(arg), exp); } inline constexpr float scalbnf(float arg, int exp) noexcept { - return boost::math::ccmath::scalbn(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::scalbn(arg, exp); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double scalbnl(long double arg, int exp) noexcept { - return boost::math::ccmath::scalbn(arg, exp); + return BOOST_MATH_NAMESPACE::ccmath::scalbn(arg, exp); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_SCALBN_HPP diff --git a/include/boost/math/ccmath/signbit.hpp b/include/boost/math/ccmath/signbit.hpp index 87f4cc7c9f..b063d9ec3c 100644 --- a/include/boost/math/ccmath/signbit.hpp +++ b/include/boost/math/ccmath/signbit.hpp @@ -12,14 +12,18 @@ #error "The header can only be used in C++17 and later." #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include #ifdef __has_include # if __has_include() +#ifndef BOOST_MATH_BUILD_MODULE # include +#endif # if __cpp_lib_bit_cast >= 201806L # define BOOST_MATH_BIT_CAST(T, x) std::bit_cast(x) # endif @@ -49,7 +53,7 @@ ccmath_signbit_test.cpp:32:19: error: static_assert expression is not an integra # undef BOOST_MATH_BIT_CAST #endif -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -165,8 +169,8 @@ constexpr bool signbit_impl(T arg) #endif else { - BOOST_MATH_ASSERT_MSG(!boost::math::ccmath::isnan(arg), "NAN is not supported with this type or platform"); - BOOST_MATH_ASSERT_MSG(boost::math::ccmath::abs(arg) != 0, "Signed 0 is not support with this type or platform"); + BOOST_MATH_ASSERT_MSG(!BOOST_MATH_NAMESPACE::ccmath::isnan(arg), "NAN is not supported with this type or platform"); + BOOST_MATH_ASSERT_MSG(BOOST_MATH_NAMESPACE::ccmath::abs(arg) != 0, "Signed 0 is not support with this type or platform"); return arg < static_cast(0); } @@ -182,8 +186,8 @@ constexpr bool signbit_impl(T arg) template constexpr bool signbit_impl(T arg) { - BOOST_MATH_ASSERT_MSG(!boost::math::ccmath::isnan(arg), "NAN is not supported without __builtin_bit_cast or std::bit_cast"); - BOOST_MATH_ASSERT_MSG(boost::math::ccmath::abs(arg) != 0, "Signed 0 is not support without __builtin_bit_cast or std::bit_cast"); + BOOST_MATH_ASSERT_MSG(!BOOST_MATH_NAMESPACE::ccmath::isnan(arg), "NAN is not supported without __builtin_bit_cast or std::bit_cast"); + BOOST_MATH_ASSERT_MSG(BOOST_MATH_NAMESPACE::ccmath::abs(arg) != 0, "Signed 0 is not support without __builtin_bit_cast or std::bit_cast"); return arg < static_cast(0); } @@ -193,12 +197,12 @@ constexpr bool signbit_impl(T arg) } // Return value: true if arg is negative, false if arg is 0, NAN, or positive -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr bool signbit(Real arg) { if (BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::detail::signbit_impl(arg); + return BOOST_MATH_NAMESPACE::ccmath::detail::signbit_impl(arg); } else { @@ -207,12 +211,12 @@ constexpr bool signbit(Real arg) } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr bool signbit(Z arg) { - return boost::math::ccmath::signbit(static_cast(arg)); + return BOOST_MATH_NAMESPACE::ccmath::signbit(static_cast(arg)); } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_SIGNBIT_HPP diff --git a/include/boost/math/ccmath/sqrt.hpp b/include/boost/math/ccmath/sqrt.hpp index 3639610700..9c2242cc2e 100644 --- a/include/boost/math/ccmath/sqrt.hpp +++ b/include/boost/math/ccmath/sqrt.hpp @@ -19,7 +19,7 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { @@ -43,19 +43,19 @@ constexpr Real sqrt_impl(Real x) } // namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr Real sqrt(Real x) { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) { - if (boost::math::ccmath::isnan(x) || - (boost::math::ccmath::isinf(x) && x > 0) || - boost::math::ccmath::abs(x) == Real(0)) + if (BOOST_MATH_NAMESPACE::ccmath::isnan(x) || + (BOOST_MATH_NAMESPACE::ccmath::isinf(x) && x > 0) || + BOOST_MATH_NAMESPACE::ccmath::abs(x) == Real(0)) { return x; } // Domain error is implementation defined so return NAN - else if (boost::math::ccmath::isinf(x) && x < 0) + else if (BOOST_MATH_NAMESPACE::ccmath::isinf(x) && x < 0) { return std::numeric_limits::quiet_NaN(); } @@ -69,12 +69,12 @@ constexpr Real sqrt(Real x) } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> constexpr double sqrt(Z x) { return detail::sqrt_impl(static_cast(x)); } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_SQRT diff --git a/include/boost/math/ccmath/trunc.hpp b/include/boost/math/ccmath/trunc.hpp index 7d30fd8b4c..725361e935 100644 --- a/include/boost/math/ccmath/trunc.hpp +++ b/include/boost/math/ccmath/trunc.hpp @@ -18,27 +18,27 @@ #include #include -namespace boost::math::ccmath { +BOOST_MATH_NAMESPACE_BEGIN namespace ccmath { namespace detail { template inline constexpr T trunc_impl(T arg) noexcept { - return (arg > 0) ? boost::math::ccmath::floor(arg) : boost::math::ccmath::ceil(arg); + return (arg > 0) ? BOOST_MATH_NAMESPACE::ccmath::floor(arg) : BOOST_MATH_NAMESPACE::ccmath::ceil(arg); } } // Namespace detail -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr Real trunc(Real arg) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg)) { - return boost::math::ccmath::abs(arg) == Real(0) ? arg : - boost::math::ccmath::isinf(arg) ? arg : - boost::math::ccmath::isnan(arg) ? arg : - boost::math::ccmath::detail::trunc_impl(arg); + return BOOST_MATH_NAMESPACE::ccmath::abs(arg) == Real(0) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isinf(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::isnan(arg) ? arg : + BOOST_MATH_NAMESPACE::ccmath::detail::trunc_impl(arg); } else { @@ -47,24 +47,24 @@ inline constexpr Real trunc(Real arg) noexcept } } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> inline constexpr double trunc(Z arg) noexcept { - return boost::math::ccmath::trunc(static_cast(arg)); + return BOOST_MATH_NAMESPACE::ccmath::trunc(static_cast(arg)); } inline constexpr float truncf(float arg) noexcept { - return boost::math::ccmath::trunc(arg); + return BOOST_MATH_NAMESPACE::ccmath::trunc(arg); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS inline constexpr long double truncl(long double arg) noexcept { - return boost::math::ccmath::trunc(arg); + return BOOST_MATH_NAMESPACE::ccmath::trunc(arg); } #endif -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CCMATH_TRUNC_HPP diff --git a/include/boost/math/common_factor_ct.hpp b/include/boost/math/common_factor_ct.hpp index 145d16fdd9..debf956eb2 100644 --- a/include/boost/math/common_factor_ct.hpp +++ b/include/boost/math/common_factor_ct.hpp @@ -11,22 +11,19 @@ #define BOOST_MATH_COMMON_FACTOR_CT_HPP #ifndef BOOST_MATH_STANDALONE +#include #include #include BOOST_MATH_HEADER_DEPRECATED(""); -namespace boost -{ -namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN using boost::integer::static_gcd; using boost::integer::static_lcm; using boost::integer::static_gcd_type; -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else #error Common factor is not available in standalone mode because it requires boost.integer. #endif // BOOST_MATH_STANDALONE diff --git a/include/boost/math/common_factor_rt.hpp b/include/boost/math/common_factor_rt.hpp index 6cc425437b..8510e2c532 100644 --- a/include/boost/math/common_factor_rt.hpp +++ b/include/boost/math/common_factor_rt.hpp @@ -8,21 +8,20 @@ #define BOOST_MATH_COMMON_FACTOR_RT_HPP #ifndef BOOST_MATH_STANDALONE +#include #include #include BOOST_MATH_HEADER_DEPRECATED(""); -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN using boost::integer::gcd; using boost::integer::lcm; using boost::integer::gcd_range; using boost::integer::lcm_range; using boost::integer::gcd_evaluator; using boost::integer::lcm_evaluator; - } -} + BOOST_MATH_NAMESPACE_END #else #error Common factor is not available in standalone mode because it requires boost.integer. #endif // BOOST_MATH_STANDALONE diff --git a/include/boost/math/complex/acos.hpp b/include/boost/math/complex/acos.hpp index 91df777414..0844806ff0 100644 --- a/include/boost/math/complex/acos.hpp +++ b/include/boost/math/complex/acos.hpp @@ -17,9 +17,9 @@ namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; } #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template [[deprecated("Replaced by C++11")]] std::complex acos(const std::complex& z) { // @@ -39,9 +39,9 @@ template static const T half = static_cast(0.5L); static const T a_crossover = static_cast(10); static const T b_crossover = static_cast(0.6417L); - static const T s_pi = boost::math::constants::pi(); + static const T s_pi = BOOST_MATH_NAMESPACE::constants::pi(); static const T half_pi = s_pi / 2; - static const T log_two = boost::math::constants::ln_two(); + static const T log_two = BOOST_MATH_NAMESPACE::constants::ln_two(); static const T quarter_pi = s_pi / 4; #ifdef _MSC_VER @@ -63,14 +63,14 @@ template // but doing it this way prevents overflow/underflow arithmetic // in the main body of the logic, which may trip up some machines: // - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) { - if((boost::math::isinf)(y)) + if((BOOST_MATH_NAMESPACE::isinf)(y)) { real = quarter_pi; imag = std::numeric_limits::infinity(); } - else if((boost::math::isnan)(y)) + else if((BOOST_MATH_NAMESPACE::isnan)(y)) { return std::complex(y, -std::numeric_limits::infinity()); } @@ -81,18 +81,18 @@ template imag = std::numeric_limits::infinity(); } } - else if((boost::math::isnan)(x)) + else if((BOOST_MATH_NAMESPACE::isnan)(x)) { - if((boost::math::isinf)(y)) - return std::complex(x, ((boost::math::signbit)(z.imag())) ? std::numeric_limits::infinity() : -std::numeric_limits::infinity()); + if((BOOST_MATH_NAMESPACE::isinf)(y)) + return std::complex(x, ((BOOST_MATH_NAMESPACE::signbit)(z.imag())) ? std::numeric_limits::infinity() : -std::numeric_limits::infinity()); return std::complex(x, x); } - else if((boost::math::isinf)(y)) + else if((BOOST_MATH_NAMESPACE::isinf)(y)) { real = half_pi; imag = std::numeric_limits::infinity(); } - else if((boost::math::isnan)(y)) + else if((BOOST_MATH_NAMESPACE::isnan)(y)) { return std::complex((x == 0) ? half_pi : y, y); } @@ -103,7 +103,7 @@ template // begin with the special case for real numbers: // if((y == 0) && (x <= one)) - return std::complex((x == 0) ? half_pi : std::acos(z.real()), (boost::math::changesign)(z.imag())); + return std::complex((x == 0) ? half_pi : std::acos(z.real()), (BOOST_MATH_NAMESPACE::changesign)(z.imag())); // // Figure out if our input is within the "safe area" identified by Hull et al. // This would be more efficient with portable floating point exception handling; @@ -152,7 +152,7 @@ template { am1 = half * (yy/(r + xp1) + (s + xm1)); } - imag = boost::math::log1p(am1 + std::sqrt(am1 * (a + one))); + imag = BOOST_MATH_NAMESPACE::log1p(am1 + std::sqrt(am1 * (a + one))); } else { @@ -178,7 +178,7 @@ template { // xp1 * xm1 won't overflow: real = y / std::sqrt(xm1*xp1); - imag = boost::math::log1p(xm1 + std::sqrt(xp1*xm1)); + imag = BOOST_MATH_NAMESPACE::log1p(xm1 + std::sqrt(xp1*xm1)); } else { @@ -215,13 +215,13 @@ template { real = std::atan(y/x); T xoy = x/y; - imag = log_two + std::log(y) + half * boost::math::log1p(xoy*xoy); + imag = log_two + std::log(y) + half * BOOST_MATH_NAMESPACE::log1p(xoy*xoy); } else { real = half_pi; T a = std::sqrt(one + y*y); - imag = half * boost::math::log1p(static_cast(2)*y*(y+a)); + imag = half * BOOST_MATH_NAMESPACE::log1p(static_cast(2)*y*(y+a)); } } } @@ -229,10 +229,10 @@ template // // Finish off by working out the sign of the result: // - if((boost::math::signbit)(z.real())) + if((BOOST_MATH_NAMESPACE::signbit)(z.real())) real = s_pi - real; - if(!(boost::math::signbit)(z.imag())) - imag = (boost::math::changesign)(imag); + if(!(BOOST_MATH_NAMESPACE::signbit)(z.imag())) + imag = (BOOST_MATH_NAMESPACE::changesign)(imag); return std::complex(real, imag); #ifdef _MSC_VER @@ -240,6 +240,6 @@ template #endif } -} } // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_COMPLEX_ACOS_INCLUDED diff --git a/include/boost/math/complex/acosh.hpp b/include/boost/math/complex/acosh.hpp index c5b52826e5..4d5b0a699c 100644 --- a/include/boost/math/complex/acosh.hpp +++ b/include/boost/math/complex/acosh.hpp @@ -13,9 +13,9 @@ # include #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template [[deprecated("Replaced by C++11")]] inline std::complex acosh(const std::complex& z) { // @@ -23,12 +23,12 @@ template // Choosing the sign of multiplier to give real(acosh(z)) >= 0 // as well as compatibility with C99. // - std::complex result = boost::math::acos(z); - if(!(boost::math::isnan)(result.imag()) && signbit(result.imag())) + std::complex result = BOOST_MATH_NAMESPACE::acos(z); + if(!(BOOST_MATH_NAMESPACE::isnan)(result.imag()) && signbit(result.imag())) return detail::mult_i(result); return detail::mult_minus_i(result); } -} } // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_COMPLEX_ACOSH_INCLUDED diff --git a/include/boost/math/complex/asin.hpp b/include/boost/math/complex/asin.hpp index d1fbc2f164..e27c24c07d 100644 --- a/include/boost/math/complex/asin.hpp +++ b/include/boost/math/complex/asin.hpp @@ -17,9 +17,9 @@ namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; } #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template [[deprecated("Replaced by C++11")]] inline std::complex asin(const std::complex& z) { // @@ -39,9 +39,9 @@ template static const T half = static_cast(0.5L); static const T a_crossover = static_cast(10); static const T b_crossover = static_cast(0.6417L); - static const T s_pi = boost::math::constants::pi(); + static const T s_pi = BOOST_MATH_NAMESPACE::constants::pi(); static const T half_pi = s_pi / 2; - static const T log_two = boost::math::constants::ln_two(); + static const T log_two = BOOST_MATH_NAMESPACE::constants::ln_two(); static const T quarter_pi = s_pi / 4; #ifdef _MSC_VER #pragma warning(push) @@ -61,11 +61,11 @@ template // below, but handling it as a special case prevents overflow/underflow // arithmetic which may trip up some machines: // - if((boost::math::isnan)(x)) + if((BOOST_MATH_NAMESPACE::isnan)(x)) { - if((boost::math::isnan)(y)) + if((BOOST_MATH_NAMESPACE::isnan)(y)) return std::complex(x, x); - if((boost::math::isinf)(y)) + if((BOOST_MATH_NAMESPACE::isinf)(y)) { real = x; imag = std::numeric_limits::infinity(); @@ -73,14 +73,14 @@ template else return std::complex(x, x); } - else if((boost::math::isnan)(y)) + else if((BOOST_MATH_NAMESPACE::isnan)(y)) { if(x == 0) { real = 0; imag = y; } - else if((boost::math::isinf)(x)) + else if((BOOST_MATH_NAMESPACE::isinf)(x)) { real = y; imag = std::numeric_limits::infinity(); @@ -88,9 +88,9 @@ template else return std::complex(y, y); } - else if((boost::math::isinf)(x)) + else if((BOOST_MATH_NAMESPACE::isinf)(x)) { - if((boost::math::isinf)(y)) + if((BOOST_MATH_NAMESPACE::isinf)(y)) { real = quarter_pi; imag = std::numeric_limits::infinity(); @@ -101,7 +101,7 @@ template imag = std::numeric_limits::infinity(); } } - else if((boost::math::isinf)(y)) + else if((BOOST_MATH_NAMESPACE::isinf)(y)) { real = 0; imag = std::numeric_limits::infinity(); @@ -161,7 +161,7 @@ template { am1 = half * (yy/(r + xp1) + (s + xm1)); } - imag = boost::math::log1p(am1 + std::sqrt(am1 * (a + one))); + imag = BOOST_MATH_NAMESPACE::log1p(am1 + std::sqrt(am1 * (a + one))); } else { @@ -186,7 +186,7 @@ template if(((std::numeric_limits::max)() / xp1) > xm1) { // xp1 * xm1 won't overflow: - imag = boost::math::log1p(xm1 + std::sqrt(xp1*xm1)); + imag = BOOST_MATH_NAMESPACE::log1p(xm1 + std::sqrt(xp1*xm1)); } else { @@ -222,13 +222,13 @@ template { real = std::atan(x/y); T xoy = x/y; - imag = log_two + std::log(y) + half * boost::math::log1p(xoy*xoy); + imag = log_two + std::log(y) + half * BOOST_MATH_NAMESPACE::log1p(xoy*xoy); } else { T a = std::sqrt(one + y*y); real = x/a; // This can underflow! - imag = half * boost::math::log1p(static_cast(2)*y*(y+a)); + imag = half * BOOST_MATH_NAMESPACE::log1p(static_cast(2)*y*(y+a)); } } } @@ -236,10 +236,10 @@ template // // Finish off by working out the sign of the result: // - if((boost::math::signbit)(z.real())) - real = (boost::math::changesign)(real); - if((boost::math::signbit)(z.imag())) - imag = (boost::math::changesign)(imag); + if((BOOST_MATH_NAMESPACE::signbit)(z.real())) + real = (BOOST_MATH_NAMESPACE::changesign)(real); + if((BOOST_MATH_NAMESPACE::signbit)(z.imag())) + imag = (BOOST_MATH_NAMESPACE::changesign)(imag); return std::complex(real, imag); #ifdef _MSC_VER @@ -247,6 +247,6 @@ template #endif } -} } // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_COMPLEX_ASIN_INCLUDED diff --git a/include/boost/math/complex/asinh.hpp b/include/boost/math/complex/asinh.hpp index 1c9a42eb07..f60efb32d6 100644 --- a/include/boost/math/complex/asinh.hpp +++ b/include/boost/math/complex/asinh.hpp @@ -13,9 +13,9 @@ # include #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template [[deprecated("Replaced by C++11")]] inline std::complex asinh(const std::complex& x) { // @@ -24,9 +24,9 @@ template // to say asin is specified in terms of asinh), this is consistent // with C99 though: // - return ::boost::math::detail::mult_i(::boost::math::asin(::boost::math::detail::mult_minus_i(x))); + return ::BOOST_MATH_NAMESPACE::detail::mult_i(::BOOST_MATH_NAMESPACE::asin(::BOOST_MATH_NAMESPACE::detail::mult_minus_i(x))); } -} } // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_COMPLEX_ASINH_INCLUDED diff --git a/include/boost/math/complex/atan.hpp b/include/boost/math/complex/atan.hpp index a11ea41ee5..65a3197c54 100644 --- a/include/boost/math/complex/atan.hpp +++ b/include/boost/math/complex/atan.hpp @@ -13,9 +13,9 @@ # include #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template [[deprecated("Replaced by C++11")]] std::complex atan(const std::complex& x) { // @@ -28,9 +28,9 @@ template if(x.imag() == -1) return std::complex(0, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -static_cast(HUGE_VAL)); } - return ::boost::math::detail::mult_minus_i(::boost::math::atanh(::boost::math::detail::mult_i(x))); + return ::BOOST_MATH_NAMESPACE::detail::mult_minus_i(::BOOST_MATH_NAMESPACE::atanh(::BOOST_MATH_NAMESPACE::detail::mult_i(x))); } -} } // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_COMPLEX_ATAN_INCLUDED diff --git a/include/boost/math/complex/atanh.hpp b/include/boost/math/complex/atanh.hpp index 5b7dc90108..d4049c3372 100644 --- a/include/boost/math/complex/atanh.hpp +++ b/include/boost/math/complex/atanh.hpp @@ -18,9 +18,9 @@ namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; } #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template [[deprecated("Replaced by C++11")]] std::complex atanh(const std::complex& z) { // @@ -39,13 +39,13 @@ template // See also: https://svn.boost.org/trac/boost/ticket/7291 // - static const T pi = boost::math::constants::pi(); + static const T pi = BOOST_MATH_NAMESPACE::constants::pi(); static const T half_pi = pi / 2; static const T one = static_cast(1.0L); static const T two = static_cast(2.0L); static const T four = static_cast(4.0L); static const T zero = static_cast(0); - static const T log_two = boost::math::constants::ln_two(); + static const T log_two = BOOST_MATH_NAMESPACE::constants::ln_two(); #ifdef _MSC_VER #pragma warning(push) @@ -63,20 +63,20 @@ template // // Begin by handling the special cases specified in C99: // - if((boost::math::isnan)(x)) + if((BOOST_MATH_NAMESPACE::isnan)(x)) { - if((boost::math::isnan)(y)) + if((BOOST_MATH_NAMESPACE::isnan)(y)) return std::complex(x, x); - else if((boost::math::isinf)(y)) - return std::complex(0, ((boost::math::signbit)(z.imag()) ? -half_pi : half_pi)); + else if((BOOST_MATH_NAMESPACE::isinf)(y)) + return std::complex(0, ((BOOST_MATH_NAMESPACE::signbit)(z.imag()) ? -half_pi : half_pi)); else return std::complex(x, x); } - else if((boost::math::isnan)(y)) + else if((BOOST_MATH_NAMESPACE::isnan)(y)) { if(x == 0) return std::complex(x, y); - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) return std::complex(0, y); else return std::complex(y, y); @@ -91,15 +91,15 @@ template // // real(atanh(z)) == log1p(4*x / ((x-1)*(x-1) + y^2)) // - real = boost::math::log1p(four * x / (mxm1*mxm1 + yy)); + real = BOOST_MATH_NAMESPACE::log1p(four * x / (mxm1*mxm1 + yy)); real /= four; - if((boost::math::signbit)(z.real())) - real = (boost::math::changesign)(real); + if((BOOST_MATH_NAMESPACE::signbit)(z.real())) + real = (BOOST_MATH_NAMESPACE::changesign)(real); imag = std::atan2((y * two), (mxm1*(one+x) - yy)); imag /= two; if(z.imag() < 0) - imag = (boost::math::changesign)(imag); + imag = (BOOST_MATH_NAMESPACE::changesign)(imag); } else { @@ -115,24 +115,24 @@ template if(x >= safe_upper) { // x-1 = x to machine precision: - if((boost::math::isinf)(x) || (boost::math::isinf)(y)) + if((BOOST_MATH_NAMESPACE::isinf)(x) || (BOOST_MATH_NAMESPACE::isinf)(y)) { real = 0; } else if(y >= safe_upper) { // Big x and y: divide through by x*y: - real = boost::math::log1p((four/y) / (x/y + y/x)); + real = BOOST_MATH_NAMESPACE::log1p((four/y) / (x/y + y/x)); } else if(y > one) { // Big x: divide through by x: - real = boost::math::log1p(four / (x + y*y/x)); + real = BOOST_MATH_NAMESPACE::log1p(four / (x + y*y/x)); } else { // Big x small y, as above but neglect y^2/x: - real = boost::math::log1p(four/x); + real = BOOST_MATH_NAMESPACE::log1p(four/x); } } else if(y >= safe_upper) @@ -140,7 +140,7 @@ template if(x > one) { // Big y, medium x, divide through by y: - real = boost::math::log1p((four*x/y) / (y + mxm1*mxm1/y)); + real = BOOST_MATH_NAMESPACE::log1p((four*x/y) / (y + mxm1*mxm1/y)); } else { @@ -154,14 +154,14 @@ template T div = mxm1*mxm1; if(y > safe_lower) div += y*y; - real = boost::math::log1p(four*x/div); + real = BOOST_MATH_NAMESPACE::log1p(four*x/div); } else - real = boost::math::changesign(two * (std::log(y) - log_two)); + real = BOOST_MATH_NAMESPACE::changesign(two * (std::log(y) - log_two)); real /= four; - if((boost::math::signbit)(z.real())) - real = (boost::math::changesign)(real); + if((BOOST_MATH_NAMESPACE::signbit)(z.real())) + real = (BOOST_MATH_NAMESPACE::changesign)(real); // // Now handle imaginary part, this is much easier, @@ -200,8 +200,8 @@ template imag = std::atan2(two*y, mxm1*(one+x)); } imag /= two; - if((boost::math::signbit)(z.imag())) - imag = (boost::math::changesign)(imag); + if((BOOST_MATH_NAMESPACE::signbit)(z.imag())) + imag = (BOOST_MATH_NAMESPACE::changesign)(imag); } return std::complex(real, imag); #ifdef _MSC_VER @@ -209,6 +209,6 @@ template #endif } -} } // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_COMPLEX_ATANH_INCLUDED diff --git a/include/boost/math/complex/details.hpp b/include/boost/math/complex/details.hpp index 0a3d35347d..b0fbedd651 100644 --- a/include/boost/math/complex/details.hpp +++ b/include/boost/math/complex/details.hpp @@ -11,19 +11,21 @@ // that we need to implement all these functions. // +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template inline T mult_minus_one(const T& t) { - return (boost::math::isnan)(t) ? t : (boost::math::changesign)(t); + return (BOOST_MATH_NAMESPACE::isnan)(t) ? t : (BOOST_MATH_NAMESPACE::changesign)(t); } template @@ -62,7 +64,7 @@ inline long double safe_min(long double t) return std::sqrt((std::numeric_limits::min)()) * t; } -} } } // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_COMPLEX_DETAILS_INCLUDED diff --git a/include/boost/math/complex/fabs.hpp b/include/boost/math/complex/fabs.hpp index 5eb8b3bd80..7d231c79a5 100644 --- a/include/boost/math/complex/fabs.hpp +++ b/include/boost/math/complex/fabs.hpp @@ -10,14 +10,14 @@ # include #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template inline T fabs(const std::complex& z) { - return ::boost::math::hypot(z.real(), z.imag()); + return ::BOOST_MATH_NAMESPACE::hypot(z.real(), z.imag()); } -} } // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_COMPLEX_FABS_INCLUDED diff --git a/include/boost/math/concepts/distributions.hpp b/include/boost/math/concepts/distributions.hpp index 7f9af2dd5a..140c342013 100644 --- a/include/boost/math/concepts/distributions.hpp +++ b/include/boost/math/concepts/distributions.hpp @@ -28,8 +28,7 @@ #endif #include -namespace boost{ -namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace concepts { @@ -123,8 +122,8 @@ struct DistributionConcept void constraints() { - function_requires >(); - function_requires >(); + boost::function_requires >(); + boost::function_requires >(); const Distribution& dist = DistributionConcept::get_object(); @@ -250,27 +249,27 @@ struct DistributionConcept static void test_extra_members(const D&) {} template - static void test_extra_members(const boost::math::bernoulli_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::bernoulli_distribution& d) { value_type r = d.success_fraction(); (void)r; // warning suppression } template - static void test_extra_members(const boost::math::beta_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::beta_distribution& d) { value_type r1 = d.alpha(); value_type r2 = d.beta(); - r1 = boost::math::beta_distribution::find_alpha(r1, r2); + r1 = BOOST_MATH_NAMESPACE::beta_distribution::find_alpha(r1, r2); suppress_unused_variable_warning(r1); - r1 = boost::math::beta_distribution::find_beta(r1, r2); + r1 = BOOST_MATH_NAMESPACE::beta_distribution::find_beta(r1, r2); suppress_unused_variable_warning(r1); - r1 = boost::math::beta_distribution::find_alpha(r1, r2, r1); + r1 = BOOST_MATH_NAMESPACE::beta_distribution::find_alpha(r1, r2, r1); suppress_unused_variable_warning(r1); - r1 = boost::math::beta_distribution::find_beta(r1, r2, r1); + r1 = BOOST_MATH_NAMESPACE::beta_distribution::find_beta(r1, r2, r1); suppress_unused_variable_warning(r1); } template - static void test_extra_members(const boost::math::binomial_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::binomial_distribution& d) { value_type r = d.success_fraction(); r = d.trials(); @@ -285,14 +284,14 @@ struct DistributionConcept suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::cauchy_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::cauchy_distribution& d) { value_type r = d.location(); r = d.scale(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::chi_squared_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::chi_squared_distribution& d) { value_type r = d.degrees_of_freedom(); r = Distribution::find_degrees_of_freedom(r, r, r, r); @@ -300,48 +299,48 @@ struct DistributionConcept suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::exponential_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::exponential_distribution& d) { value_type r = d.lambda(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::extreme_value_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::extreme_value_distribution& d) { value_type r = d.scale(); r = d.location(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::fisher_f_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::fisher_f_distribution& d) { value_type r = d.degrees_of_freedom1(); r = d.degrees_of_freedom2(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::gamma_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::gamma_distribution& d) { value_type r = d.scale(); r = d.shape(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::inverse_chi_squared_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::inverse_chi_squared_distribution& d) { value_type r = d.scale(); r = d.degrees_of_freedom(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::inverse_gamma_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::inverse_gamma_distribution& d) { value_type r = d.scale(); r = d.shape(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::hypergeometric_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::hypergeometric_distribution& d) { std::uint64_t u = d.defective(); u = d.sample_count(); @@ -349,28 +348,28 @@ struct DistributionConcept suppress_unused_variable_warning(u); } template - static void test_extra_members(const boost::math::laplace_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::laplace_distribution& d) { value_type r = d.scale(); r = d.location(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::logistic_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::logistic_distribution& d) { value_type r = d.scale(); r = d.location(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::lognormal_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::lognormal_distribution& d) { value_type r = d.scale(); r = d.location(); suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::negative_binomial_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::negative_binomial_distribution& d) { value_type r = d.success_fraction(); r = d.successes(); @@ -381,7 +380,7 @@ struct DistributionConcept suppress_unused_variable_warning(r); } template - static void test_extra_members(const boost::math::non_central_beta_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::non_central_beta_distribution& d) { value_type r1 = d.alpha(); value_type r2 = d.beta(); @@ -390,18 +389,18 @@ struct DistributionConcept (void)r2; // warning suppression } template - static void test_extra_members(const boost::math::non_central_chi_squared_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::non_central_chi_squared_distribution& d) { value_type r = d.degrees_of_freedom(); r = d.non_centrality(); r = Distribution::find_degrees_of_freedom(r, r, r); - r = Distribution::find_degrees_of_freedom(boost::math::complement(r, r, r)); + r = Distribution::find_degrees_of_freedom(BOOST_MATH_NAMESPACE::complement(r, r, r)); r = Distribution::find_non_centrality(r, r, r); - r = Distribution::find_non_centrality(boost::math::complement(r, r, r)); + r = Distribution::find_non_centrality(BOOST_MATH_NAMESPACE::complement(r, r, r)); (void)r; // warning suppression } template - static void test_extra_members(const boost::math::non_central_f_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::non_central_f_distribution& d) { value_type r = d.degrees_of_freedom1(); r = d.degrees_of_freedom2(); @@ -409,14 +408,14 @@ struct DistributionConcept (void)r; // warning suppression } template - static void test_extra_members(const boost::math::non_central_t_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::non_central_t_distribution& d) { value_type r = d.degrees_of_freedom(); r = d.non_centrality(); (void)r; // warning suppression } template - static void test_extra_members(const boost::math::normal_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::normal_distribution& d) { value_type r = d.scale(); r = d.location(); @@ -425,26 +424,26 @@ struct DistributionConcept (void)r; // warning suppression } template - static void test_extra_members(const boost::math::pareto_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::pareto_distribution& d) { value_type r = d.scale(); r = d.shape(); (void)r; // warning suppression } template - static void test_extra_members(const boost::math::poisson_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::poisson_distribution& d) { value_type r = d.mean(); (void)r; // warning suppression } template - static void test_extra_members(const boost::math::rayleigh_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::rayleigh_distribution& d) { value_type r = d.sigma(); (void)r; // warning suppression } template - static void test_extra_members(const boost::math::students_t_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::students_t_distribution& d) { value_type r = d.degrees_of_freedom(); r = d.find_degrees_of_freedom(r, r, r, r); @@ -452,7 +451,7 @@ struct DistributionConcept (void)r; // warning suppression } template - static void test_extra_members(const boost::math::triangular_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::triangular_distribution& d) { value_type r = d.lower(); r = d.mode(); @@ -460,14 +459,14 @@ struct DistributionConcept (void)r; // warning suppression } template - static void test_extra_members(const boost::math::weibull_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::weibull_distribution& d) { value_type r = d.scale(); r = d.shape(); (void)r; // warning suppression } template - static void test_extra_members(const boost::math::uniform_distribution& d) + static void test_extra_members(const BOOST_MATH_NAMESPACE::uniform_distribution& d) { value_type r = d.lower(); r = d.upper(); @@ -486,8 +485,7 @@ template Distribution* DistributionConcept::pd = 0; } // namespace concepts -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else #error This header can not be used in standalone mode. diff --git a/include/boost/math/concepts/real_concept.hpp b/include/boost/math/concepts/real_concept.hpp index 565d58e421..a9fd3ddd81 100644 --- a/include/boost/math/concepts/real_concept.hpp +++ b/include/boost/math/concepts/real_concept.hpp @@ -53,7 +53,7 @@ # endif #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace concepts { @@ -225,7 +225,7 @@ inline real_concept modf(real_concept a, real_concept* ipart) { #ifdef __MINGW32__ real_concept_base_type ip; - real_concept_base_type result = boost::math::modf(a.value(), &ip); + real_concept_base_type result = BOOST_MATH_NAMESPACE::modf(a.value(), &ip); *ipart = ip; return result; #else @@ -235,6 +235,8 @@ inline real_concept modf(real_concept a, real_concept* ipart) return result; #endif } +inline real_concept fma(real_concept a, real_concept b, real_concept c) +{ return std::fma(a.value(), b.value(), c.value()); } inline real_concept frexp(real_concept a, int* expon) { return std::frexp(a.value(), expon); } inline real_concept ldexp(real_concept a, int expon) @@ -268,17 +270,17 @@ inline real_concept tanh(real_concept a) // Note that these must not actually call the std:: versions as that precludes using this // header to test in C++03 mode, call the Boost versions instead: // -inline boost::math::concepts::real_concept asinh(boost::math::concepts::real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::real_concept asinh(BOOST_MATH_NAMESPACE::concepts::real_concept a) { - return boost::math::asinh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error())); + return BOOST_MATH_NAMESPACE::asinh(a.value(), BOOST_MATH_NAMESPACE::policies::make_policy(BOOST_MATH_NAMESPACE::policies::overflow_error())); } -inline boost::math::concepts::real_concept acosh(boost::math::concepts::real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::real_concept acosh(BOOST_MATH_NAMESPACE::concepts::real_concept a) { - return boost::math::acosh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error())); + return BOOST_MATH_NAMESPACE::acosh(a.value(), BOOST_MATH_NAMESPACE::policies::make_policy(BOOST_MATH_NAMESPACE::policies::overflow_error())); } -inline boost::math::concepts::real_concept atanh(boost::math::concepts::real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::real_concept atanh(BOOST_MATH_NAMESPACE::concepts::real_concept a) { - return boost::math::atanh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error())); + return BOOST_MATH_NAMESPACE::atanh(a.value(), BOOST_MATH_NAMESPACE::policies::make_policy(BOOST_MATH_NAMESPACE::policies::overflow_error())); } // @@ -286,37 +288,37 @@ inline boost::math::concepts::real_concept atanh(boost::math::concepts::real_con // template inline int iround(const concepts::real_concept& v, const Policy& pol) -{ return boost::math::iround(v.value(), pol); } +{ return BOOST_MATH_NAMESPACE::iround(v.value(), pol); } inline int iround(const concepts::real_concept& v) -{ return boost::math::iround(v.value(), policies::policy<>()); } +{ return BOOST_MATH_NAMESPACE::iround(v.value(), policies::policy<>()); } template inline long lround(const concepts::real_concept& v, const Policy& pol) -{ return boost::math::lround(v.value(), pol); } +{ return BOOST_MATH_NAMESPACE::lround(v.value(), pol); } inline long lround(const concepts::real_concept& v) -{ return boost::math::lround(v.value(), policies::policy<>()); } +{ return BOOST_MATH_NAMESPACE::lround(v.value(), policies::policy<>()); } template inline long long llround(const concepts::real_concept& v, const Policy& pol) -{ return boost::math::llround(v.value(), pol); } +{ return BOOST_MATH_NAMESPACE::llround(v.value(), pol); } inline long long llround(const concepts::real_concept& v) -{ return boost::math::llround(v.value(), policies::policy<>()); } +{ return BOOST_MATH_NAMESPACE::llround(v.value(), policies::policy<>()); } template inline int itrunc(const concepts::real_concept& v, const Policy& pol) -{ return boost::math::itrunc(v.value(), pol); } +{ return BOOST_MATH_NAMESPACE::itrunc(v.value(), pol); } inline int itrunc(const concepts::real_concept& v) -{ return boost::math::itrunc(v.value(), policies::policy<>()); } +{ return BOOST_MATH_NAMESPACE::itrunc(v.value(), policies::policy<>()); } template inline long ltrunc(const concepts::real_concept& v, const Policy& pol) -{ return boost::math::ltrunc(v.value(), pol); } +{ return BOOST_MATH_NAMESPACE::ltrunc(v.value(), pol); } inline long ltrunc(const concepts::real_concept& v) -{ return boost::math::ltrunc(v.value(), policies::policy<>()); } +{ return BOOST_MATH_NAMESPACE::ltrunc(v.value(), policies::policy<>()); } template inline long long lltrunc(const concepts::real_concept& v, const Policy& pol) -{ return boost::math::lltrunc(v.value(), pol); } +{ return BOOST_MATH_NAMESPACE::lltrunc(v.value(), pol); } inline long long lltrunc(const concepts::real_concept& v) -{ return boost::math::lltrunc(v.value(), policies::policy<>()); } +{ return BOOST_MATH_NAMESPACE::lltrunc(v.value(), policies::policy<>()); } // Streaming: template @@ -339,7 +341,7 @@ namespace tools { template <> -inline concepts::real_concept make_big_value(boost::math::tools::largest_float val, const char* , std::false_type const&, std::false_type const&) +inline concepts::real_concept make_big_value(BOOST_MATH_NAMESPACE::tools::largest_float val, const char* , std::false_type const&, std::false_type const&) { return val; // Can't use lexical_cast here, sometimes it fails.... } @@ -392,8 +394,7 @@ inline constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE } } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_REAL_CONCEPT_HPP diff --git a/include/boost/math/concepts/real_type_concept.hpp b/include/boost/math/concepts/real_type_concept.hpp index 2d7fe58d3d..56a0ea2f25 100644 --- a/include/boost/math/concepts/real_type_concept.hpp +++ b/include/boost/math/concepts/real_type_concept.hpp @@ -20,7 +20,7 @@ #include -namespace boost{ namespace math{ namespace concepts{ +BOOST_MATH_NAMESPACE_BEGIN namespace concepts{ template struct RealTypeConcept @@ -103,17 +103,17 @@ struct RealTypeConcept int i {}; r2 = ldexp(r, i); r2 = frexp(r, &i); - i = boost::math::tools::digits(); - r2 = boost::math::tools::max_value(); - r2 = boost::math::tools::min_value(); - r2 = boost::math::tools::log_max_value(); - r2 = boost::math::tools::log_min_value(); - r2 = boost::math::tools::epsilon(); + i = BOOST_MATH_NAMESPACE::tools::digits(); + r2 = BOOST_MATH_NAMESPACE::tools::max_value(); + r2 = BOOST_MATH_NAMESPACE::tools::min_value(); + r2 = BOOST_MATH_NAMESPACE::tools::log_max_value(); + r2 = BOOST_MATH_NAMESPACE::tools::log_min_value(); + r2 = BOOST_MATH_NAMESPACE::tools::epsilon(); } }; // struct DistributionConcept -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/concepts/std_real_concept.hpp b/include/boost/math/concepts/std_real_concept.hpp index 43f562efe1..b01c604648 100644 --- a/include/boost/math/concepts/std_real_concept.hpp +++ b/include/boost/math/concepts/std_real_concept.hpp @@ -26,7 +26,7 @@ #ifndef BOOST_MATH_STD_REAL_CONCEPT_HPP #define BOOST_MATH_STD_REAL_CONCEPT_HPP -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace concepts { @@ -156,94 +156,95 @@ inline bool operator >= (const std_real_concept& a, const std_real_concept& b) { return a.value() >= b.value(); } } // namespace concepts -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END namespace std{ // Non-member functions: -inline boost::math::concepts::std_real_concept acos(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept acos(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::acos(a.value()); } -inline boost::math::concepts::std_real_concept cos(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept cos(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::cos(a.value()); } -inline boost::math::concepts::std_real_concept asin(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept asin(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::asin(a.value()); } -inline boost::math::concepts::std_real_concept atan(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept atan(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::atan(a.value()); } -inline boost::math::concepts::std_real_concept atan2(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept atan2(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, BOOST_MATH_NAMESPACE::concepts::std_real_concept b) { return std::atan2(a.value(), b.value()); } -inline boost::math::concepts::std_real_concept ceil(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept ceil(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::ceil(a.value()); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS -inline boost::math::concepts::std_real_concept fmod(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept fmod(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, BOOST_MATH_NAMESPACE::concepts::std_real_concept b) { return fmodl(a.value(), b.value()); } #else -inline boost::math::concepts::std_real_concept fmod(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept fmod(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, BOOST_MATH_NAMESPACE::concepts::std_real_concept b) { return std::fmod(a.value(), b.value()); } #endif -inline boost::math::concepts::std_real_concept cosh(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept cosh(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::cosh(a.value()); } -inline boost::math::concepts::std_real_concept exp(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept exp(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::exp(a.value()); } -inline boost::math::concepts::std_real_concept fabs(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept fabs(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::fabs(a.value()); } -inline boost::math::concepts::std_real_concept abs(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept abs(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::abs(a.value()); } -inline boost::math::concepts::std_real_concept floor(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept floor(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::floor(a.value()); } -inline boost::math::concepts::std_real_concept modf(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept* ipart) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept modf(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, BOOST_MATH_NAMESPACE::concepts::std_real_concept* ipart) { - boost::math::concepts::std_real_concept_base_type ip; - boost::math::concepts::std_real_concept_base_type result = std::modf(a.value(), &ip); + BOOST_MATH_NAMESPACE::concepts::std_real_concept_base_type ip; + BOOST_MATH_NAMESPACE::concepts::std_real_concept_base_type result = std::modf(a.value(), &ip); *ipart = ip; return result; } -inline boost::math::concepts::std_real_concept frexp(boost::math::concepts::std_real_concept a, int* expon) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept fma(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, BOOST_MATH_NAMESPACE::concepts::std_real_concept b, BOOST_MATH_NAMESPACE::concepts::std_real_concept c) +{ return std::fma(a.value(), b.value(), c.value()); } +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept frexp(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, int* expon) { return std::frexp(a.value(), expon); } -inline boost::math::concepts::std_real_concept ldexp(boost::math::concepts::std_real_concept a, int expon) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept ldexp(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, int expon) { return std::ldexp(a.value(), expon); } -inline boost::math::concepts::std_real_concept log(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept log(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::log(a.value()); } -inline boost::math::concepts::std_real_concept log10(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept log10(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::log10(a.value()); } -inline boost::math::concepts::std_real_concept tan(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept tan(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::tan(a.value()); } -inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept pow(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, BOOST_MATH_NAMESPACE::concepts::std_real_concept b) { return std::pow(a.value(), b.value()); } #if !defined(__SUNPRO_CC) -inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, int b) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept pow(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, int b) { return std::pow(a.value(), b); } #else -inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, int b) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept pow(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, int b) { return std::pow(a.value(), static_cast(b)); } #endif -inline boost::math::concepts::std_real_concept sin(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept sin(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::sin(a.value()); } -inline boost::math::concepts::std_real_concept sinh(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept sinh(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::sinh(a.value()); } -inline boost::math::concepts::std_real_concept sqrt(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept sqrt(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::sqrt(a.value()); } -inline boost::math::concepts::std_real_concept tanh(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept tanh(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::tanh(a.value()); } -inline boost::math::concepts::std_real_concept (nextafter)(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b) -{ return (boost::math::nextafter)(a, b); } +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept (nextafter)(BOOST_MATH_NAMESPACE::concepts::std_real_concept a, BOOST_MATH_NAMESPACE::concepts::std_real_concept b) +{ return (BOOST_MATH_NAMESPACE::nextafter)(a, b); } // // C++11 ism's // Now that we only support C++11 and later, we can allow use of these: // -inline boost::math::concepts::std_real_concept asinh(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept asinh(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::asinh(a.value()); } -inline boost::math::concepts::std_real_concept acosh(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept acosh(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::acosh(a.value()); } -inline boost::math::concepts::std_real_concept atanh(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept atanh(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::atanh(a.value()); } -inline bool (isfinite)(boost::math::concepts::std_real_concept a) +inline bool (isfinite)(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { - return (boost::math::isfinite)(a.value()); + return (BOOST_MATH_NAMESPACE::isfinite)(a.value()); } -inline boost::math::concepts::std_real_concept log2(boost::math::concepts::std_real_concept a) +inline BOOST_MATH_NAMESPACE::concepts::std_real_concept log2(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::log2(a.value()); } -inline int ilogb(boost::math::concepts::std_real_concept a) +inline int ilogb(BOOST_MATH_NAMESPACE::concepts::std_real_concept a) { return std::ilogb(a.value()); } @@ -254,7 +255,7 @@ inline int ilogb(boost::math::concepts::std_real_concept a) #include #include -namespace boost{ namespace math{ namespace concepts{ +BOOST_MATH_NAMESPACE_BEGIN namespace concepts{ // // Conversion and truncation routines: @@ -262,61 +263,61 @@ namespace boost{ namespace math{ namespace concepts{ template inline int iround(const concepts::std_real_concept& v, const Policy& pol) { - return boost::math::iround(v.value(), pol); + return BOOST_MATH_NAMESPACE::iround(v.value(), pol); } inline int iround(const concepts::std_real_concept& v) { - return boost::math::iround(v.value(), policies::policy<>()); + return BOOST_MATH_NAMESPACE::iround(v.value(), policies::policy<>()); } template inline long lround(const concepts::std_real_concept& v, const Policy& pol) { - return boost::math::lround(v.value(), pol); + return BOOST_MATH_NAMESPACE::lround(v.value(), pol); } inline long lround(const concepts::std_real_concept& v) { - return boost::math::lround(v.value(), policies::policy<>()); + return BOOST_MATH_NAMESPACE::lround(v.value(), policies::policy<>()); } template inline long long llround(const concepts::std_real_concept& v, const Policy& pol) { - return boost::math::llround(v.value(), pol); + return BOOST_MATH_NAMESPACE::llround(v.value(), pol); } inline long long llround(const concepts::std_real_concept& v) { - return boost::math::llround(v.value(), policies::policy<>()); + return BOOST_MATH_NAMESPACE::llround(v.value(), policies::policy<>()); } template inline int itrunc(const concepts::std_real_concept& v, const Policy& pol) { - return boost::math::itrunc(v.value(), pol); + return BOOST_MATH_NAMESPACE::itrunc(v.value(), pol); } inline int itrunc(const concepts::std_real_concept& v) { - return boost::math::itrunc(v.value(), policies::policy<>()); + return BOOST_MATH_NAMESPACE::itrunc(v.value(), policies::policy<>()); } template inline long ltrunc(const concepts::std_real_concept& v, const Policy& pol) { - return boost::math::ltrunc(v.value(), pol); + return BOOST_MATH_NAMESPACE::ltrunc(v.value(), pol); } inline long ltrunc(const concepts::std_real_concept& v) { - return boost::math::ltrunc(v.value(), policies::policy<>()); + return BOOST_MATH_NAMESPACE::ltrunc(v.value(), policies::policy<>()); } template inline long long lltrunc(const concepts::std_real_concept& v, const Policy& pol) { - return boost::math::lltrunc(v.value(), pol); + return BOOST_MATH_NAMESPACE::lltrunc(v.value(), pol); } inline long long lltrunc(const concepts::std_real_concept& v) { - return boost::math::lltrunc(v.value(), policies::policy<>()); + return BOOST_MATH_NAMESPACE::lltrunc(v.value(), policies::policy<>()); } // Streaming: @@ -344,16 +345,16 @@ inline std::basic_istream& operator>>(std::basic_istream -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools { template <> -inline concepts::std_real_concept make_big_value(boost::math::tools::largest_float val, const char*, std::false_type const&, std::false_type const&) +inline concepts::std_real_concept make_big_value(BOOST_MATH_NAMESPACE::tools::largest_float val, const char*, std::false_type const&, std::false_type const&) { return val; // Can't use lexical_cast here, sometimes it fails.... } @@ -413,8 +414,7 @@ using concepts::lround; using concepts::llround; #endif -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END // // These must go at the end, as they include stuff that won't compile until diff --git a/include/boost/math/constants/calculate_constants.hpp b/include/boost/math/constants/calculate_constants.hpp index 95f53d9e16..18f307fdad 100644 --- a/include/boost/math/constants/calculate_constants.hpp +++ b/include/boost/math/constants/calculate_constants.hpp @@ -7,9 +7,11 @@ #ifndef BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED #define BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost{ namespace math{ namespace constants{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace constants{ namespace detail{ template template @@ -691,8 +693,8 @@ inline T constant_catalan::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((st break; } } - return boost::math::constants::pi >() - * log(2 + boost::math::constants::root_three >()) + return BOOST_MATH_NAMESPACE::constants::pi >() + * log(2 + BOOST_MATH_NAMESPACE::constants::root_three >()) / 8 + 3 * sum / 8; } @@ -756,7 +758,7 @@ T khinchin(int digits) if(term < lim) break; } - return exp(sum / boost::math::constants::ln_two >()); + return exp(sum / BOOST_MATH_NAMESPACE::constants::ln_two >()); } } @@ -862,7 +864,7 @@ template inline T zeta_series_derivative_lead_2() { // derivative of lead part at 2: - return -2 * boost::math::constants::ln_two(); + return -2 * BOOST_MATH_NAMESPACE::constants::ln_two(); } template @@ -885,9 +887,9 @@ inline T constant_glaisher::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((s int n = N ? (std::min)(N, tools::digits()) : tools::digits(); T v = detail::zeta_derivative_2(n); v *= 6; - v /= boost::math::constants::pi() * boost::math::constants::pi(); - v -= boost::math::constants::euler(); - v -= log(2 * boost::math::constants::pi()); + v /= BOOST_MATH_NAMESPACE::constants::pi() * BOOST_MATH_NAMESPACE::constants::pi(); + v -= BOOST_MATH_NAMESPACE::constants::euler(); + v -= log(2 * BOOST_MATH_NAMESPACE::constants::pi()); v /= -12; return exp(v); @@ -976,28 +978,28 @@ template template inline T constant_log2_e::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) { - return 1 / boost::math::constants::ln_two(); + return 1 / BOOST_MATH_NAMESPACE::constants::ln_two(); } template template inline T constant_quarter_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) { - return boost::math::constants::pi() / 4; + return BOOST_MATH_NAMESPACE::constants::pi() / 4; } template template inline T constant_one_div_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) { - return 1 / boost::math::constants::pi(); + return 1 / BOOST_MATH_NAMESPACE::constants::pi(); } template template inline T constant_two_div_root_pi::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC((std::integral_constant))) { - return 2 * boost::math::constants::one_div_root_pi(); + return 2 * BOOST_MATH_NAMESPACE::constants::one_div_root_pi(); } #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) @@ -1111,7 +1113,6 @@ inline T constant_laplace_limit::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SP } } -} -} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED diff --git a/include/boost/math/constants/constants.hpp b/include/boost/math/constants/constants.hpp index 3daf2d266e..db081c3607 100644 --- a/include/boost/math/constants/constants.hpp +++ b/include/boost/math/constants/constants.hpp @@ -23,8 +23,10 @@ #ifdef _MSC_VER #pragma warning(pop) #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) // @@ -36,8 +38,8 @@ #pragma GCC system_header #endif -namespace boost{ namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN + namespace constants { // To permit other calculations at about 100 decimal digits with some UDT, @@ -54,7 +56,7 @@ namespace boost{ namespace math // (This is necessary because you can't use a numeric constant // since even a long double might not have enough digits). - enum construction_method + BOOST_MATH_EXPORT enum construction_method { construct_from_float = 1, construct_from_double = 2, @@ -69,15 +71,15 @@ namespace boost{ namespace math // Traits class determines how to convert from string based on whether T has a constructor // from const char* or not: // - template + BOOST_MATH_EXPORT template struct dummy_size{}; // // Max number of binary digits in the string representations of our constants: // - static constexpr int max_string_digits = (101 * 1000L) / 301L; + BOOST_MATH_EXPORT BOOST_MATH_INLINE_CONSTEXPR int max_string_digits = (101 * 1000L) / 301L; - template + BOOST_MATH_EXPORT template struct construction_traits { private: @@ -108,7 +110,7 @@ namespace boost{ namespace math namespace detail{ - template > + template > struct constant_return { using construct_type = typename construction_traits::type; @@ -184,7 +186,7 @@ namespace boost{ namespace math /* The default implementations come next: */ \ static inline const T& get_from_string()\ {\ - static const T result(boost::math::tools::convert_from_string(y));\ + static const T result(BOOST_MATH_NAMESPACE::tools::convert_from_string(y));\ return result;\ }\ /* This one is for very high precision that is none the less known at compile time: */ \ @@ -198,10 +200,10 @@ namespace boost{ namespace math {\ static BOOST_MATH_THREAD_LOCAL int digits = 0;\ static BOOST_MATH_THREAD_LOCAL T value;\ - int current_digits = boost::math::tools::digits();\ + int current_digits = BOOST_MATH_NAMESPACE::tools::digits();\ if(digits != current_digits)\ {\ - value = current_digits > max_string_digits ? compute<0>() : T(boost::math::tools::convert_from_string(y));\ + value = current_digits > max_string_digits ? compute<0>() : T(BOOST_MATH_NAMESPACE::tools::convert_from_string(y));\ digits = current_digits; \ }\ return value;\ @@ -235,24 +237,23 @@ namespace boost{ namespace math \ \ /* The actual forwarding function: */ \ - template BOOST_MATH_GPU_ENABLED inline constexpr typename detail::constant_return::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy)) BOOST_MATH_NOEXCEPT(T)\ + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline constexpr typename detail::constant_return::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy)) BOOST_MATH_NOEXCEPT(T)\ { return detail:: BOOST_MATH_JOIN(constant_, name)::get(typename construction_traits::type()); }\ - template BOOST_MATH_GPU_ENABLED inline constexpr typename detail::constant_return::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) BOOST_MATH_NOEXCEPT(T)\ - { return name >(); }\ + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline constexpr typename detail::constant_return::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) BOOST_MATH_NOEXCEPT(T)\ + { return name >(); }\ \ \ /* Now the namespace specific versions: */ \ - } namespace float_constants{ static constexpr float name = BOOST_MATH_JOIN(x, F); }\ - namespace double_constants{ static constexpr double name = x; } \ - namespace long_double_constants{ static constexpr long double name = BOOST_MATH_JOIN(x, L); }\ + } namespace float_constants{ BOOST_MATH_EXPORT BOOST_MATH_INLINE_CONSTEXPR float name = BOOST_MATH_JOIN(x, F); }\ + namespace double_constants{ BOOST_MATH_EXPORT BOOST_MATH_INLINE_CONSTEXPR double name = x; } \ + namespace long_double_constants{ BOOST_MATH_EXPORT BOOST_MATH_INLINE_CONSTEXPR long double name = BOOST_MATH_JOIN(x, L); }\ namespace constants{ #else // NVRTC simplified macro definition #define BOOST_DEFINE_MATH_CONSTANT(name, value, str_value) template BOOST_MATH_GPU_ENABLED constexpr T name() noexcept { return static_cast(value); } -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace constants { #endif @@ -340,12 +341,11 @@ namespace constants { BOOST_DEFINE_MATH_CONSTANT(reciprocal_fibonacci, 3.35988566624317755317201130291892717968890513, "3.35988566624317755317201130291892717968890513373196848649555381532513031899668338361541621645679008729704") BOOST_DEFINE_MATH_CONSTANT(laplace_limit, 0.662743419349181580974742097109252907056233549115022417, "0.66274341934918158097474209710925290705623354911502241752039253499097185308651127724965480259895818168") -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline constexpr T tau() { return two_pi(); } } // namespace constants -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END // // We deliberately include this *after* all the declarations above, diff --git a/include/boost/math/constants/info.hpp b/include/boost/math/constants/info.hpp index b30c651e67..43f3ea8f8a 100644 --- a/include/boost/math/constants/info.hpp +++ b/include/boost/math/constants/info.hpp @@ -11,13 +11,17 @@ #define BOOST_MATH_CONSTANTS_INFO_INCLUDED #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #ifndef BOOST_MATH_NO_RTTI +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif -namespace boost{ namespace math{ namespace constants{ +BOOST_MATH_NAMESPACE_BEGIN namespace constants{ namespace detail{ @@ -84,7 +88,7 @@ void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_ os << "Unknown radix = " << std::numeric_limits::radix << "\n"; } } - typedef typename boost::math::policies::precision::type precision_type; + typedef typename BOOST_MATH_NAMESPACE::policies::precision::type precision_type; if(precision_type::value) { if (std::numeric_limits::radix == 2) @@ -109,7 +113,7 @@ void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_ "reports that there is no compile type precision available.\n" "boost::math::tools::digits<" << nameof() << ">() \n" "reports that the current runtime precision is \n" << - boost::math::tools::digits() << " binary digits.\n"; + BOOST_MATH_NAMESPACE::tools::digits() << " binary digits.\n"; } typedef typename construction_traits::type construction_type; @@ -122,7 +126,7 @@ void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_ "will be decided at runtime and results will not be cached \n" "- this may lead to poor runtime performance.\n" "Current runtime precision indicates that\n"; - if(boost::math::tools::digits() > max_string_digits) + if(BOOST_MATH_NAMESPACE::tools::digits() > max_string_digits) { os << "the constant will be recalculated on each call.\n"; } @@ -161,9 +165,9 @@ void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_ template void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) { - print_info_on_type >(os); + print_info_on_type >(os); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_CONSTANTS_INFO_INCLUDED diff --git a/include/boost/math/cstdfloat/cstdfloat_cmath.hpp b/include/boost/math/cstdfloat/cstdfloat_cmath.hpp index ae5af191f5..850a35ef97 100644 --- a/include/boost/math/cstdfloat/cstdfloat_cmath.hpp +++ b/include/boost/math/cstdfloat/cstdfloat_cmath.hpp @@ -46,8 +46,7 @@ // Here is a helper function used for raising the value of a given // floating-point type to the power of n, where n has integral type. -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace cstdfloat { namespace detail { @@ -125,8 +124,7 @@ namespace boost { } } - } -} // boost::math::cstdfloat::detail + BOOST_MATH_NAMESPACE_END // boost::math::cstdfloat::detail // We will now define preprocessor symbols representing quadruple-precision functions. #if defined(__INTEL_COMPILER) @@ -299,61 +297,61 @@ namespace boost { extern "C" int quadmath_snprintf(char*, std::size_t, const char*, ...) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LDEXP(boost::math::cstdfloat::detail::float_internal128_t, int) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FREXP(boost::math::cstdfloat::detail::float_internal128_t, int*) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FABS(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FLOOR(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CEIL(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TRUNC(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_POW(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG10(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SIN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COS(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TAN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASIN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOS(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMOD(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN2(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LGAMMA(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LDEXP(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, int) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FREXP(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, int*) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FABS(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FLOOR(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CEIL(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TRUNC(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_POW(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG10(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SIN(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COS(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TAN(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASIN(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOS(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMOD(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN2(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LGAMMA(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; // begin more functions -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMAINDER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMQUO(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t, int*) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMA(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMAX(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMIN(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FDIM(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NAN(const char*) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMAINDER(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMQUO(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, int*) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMA(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMAX(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMIN(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FDIM(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NAN(const char*) BOOST_MATH_NOTHROW; //extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP2 (boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG2(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG1P(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CBRT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_HYPOT(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERF(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERFC(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLROUND(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LROUND(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ROUND(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLRINT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LRINT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_RINT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_MODF(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t*) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBLN(boost::math::cstdfloat::detail::float_internal128_t, long int) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBN(boost::math::cstdfloat::detail::float_internal128_t, int) BOOST_MATH_NOTHROW; -extern "C" int BOOST_CSTDFLOAT_FLOAT128_ILOGB(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOGB(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG2(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG1P(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CBRT(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_HYPOT(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERF(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERFC(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLROUND(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LROUND(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ROUND(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLRINT(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LRINT(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_RINT(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_MODF(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t*) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBLN(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, long int) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBN(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, int) BOOST_MATH_NOTHROW; +extern "C" int BOOST_CSTDFLOAT_FLOAT128_ILOGB(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOGB(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; //extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" int BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" int BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; //extern "C" int BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY (boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; //extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISFINITE (boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISINF(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; -extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISNAN(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISINF(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; +extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISNAN(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; //extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ISNORMAL (boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; //extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISGREATER (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; //extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; @@ -365,29 +363,29 @@ extern "C" int BOOST_CSTDFLOAT_ #if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS) -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; -extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; +extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW; #else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS // Forward declaration of the patched exponent function, exp(x). -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x); +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x); -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(boost::math::cstdfloat::detail::float_internal128_t x) +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { // Compute exp(x) - 1 for x small. // Use an order-12 Pade approximation of the exponential function. // PadeApproximant[Exp[x] - 1, {x, 0, 12, 12}]. - typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + typedef BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t float_type; float_type sum; @@ -427,12 +425,12 @@ inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT return sum; } -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x) +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { // Patch the expq() function for a subset of broken GCC compilers // like GCC 4.7, 4.8 on MinGW. - typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + typedef BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t float_type; // Scale the argument x to the range (-ln2 < x < ln2). constexpr float_type one_over_ln2 = float_type(BOOST_FLOAT128_C(1.44269504088896340735992468100189213742664595415299)); @@ -467,7 +465,7 @@ inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x - floor_of_x) < float_type(BOOST_CSTDFLOAT_FLOAT128_EPS)) { // Return e^n for arguments very near an integer. - return boost::math::cstdfloat::detail::pown(BOOST_FLOAT128_C(2.71828182845904523536028747135266249775724709369996), static_cast(floor_of_x)); + return BOOST_MATH_NAMESPACE::cstdfloat::detail::pown(BOOST_FLOAT128_C(2.71828182845904523536028747135266249775724709369996), static_cast(floor_of_x)); } // Compute the scaled argument alpha. @@ -478,13 +476,13 @@ inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT const float_type scaled_result = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(alpha) + float_type(1); // Rescale the result and return it. - return scaled_result * boost::math::cstdfloat::detail::pown(float_type(2), n); + return scaled_result * BOOST_MATH_NAMESPACE::cstdfloat::detail::pown(float_type(2), n); } -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(boost::math::cstdfloat::detail::float_internal128_t x) +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { // Patch the sinhq() function for a subset of broken GCC compilers // like GCC 4.7, 4.8 on MinGW. - typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + typedef BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t float_type; // Here, we use the following: // Set: ex = exp(x) @@ -506,50 +504,50 @@ inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT return (ex - (float_type(1) / ex)) / 2; } } -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(boost::math::cstdfloat::detail::float_internal128_t x) +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { // Patch the coshq() function for a subset of broken GCC compilers // like GCC 4.7, 4.8 on MinGW. - typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + typedef BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t float_type; const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); return (ex + (float_type(1) / ex)) / 2; } -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(boost::math::cstdfloat::detail::float_internal128_t x) +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { // Patch the tanhq() function for a subset of broken GCC compilers // like GCC 4.7, 4.8 on MinGW. - typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + typedef BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t float_type; const float_type ex_plus = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); const float_type ex_minus = (float_type(1) / ex_plus); return (ex_plus - ex_minus) / (ex_plus + ex_minus); } -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW { // Patch the asinh() function since quadmath does not have it. - typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + typedef BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t float_type; return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + ::BOOST_CSTDFLOAT_FLOAT128_SQRT((x * x) + float_type(1))); } -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW { // Patch the acosh() function since quadmath does not have it. - typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + typedef BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t float_type; const float_type zp(x + float_type(1)); const float_type zm(x - float_type(1)); return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + (zp * ::BOOST_CSTDFLOAT_FLOAT128_SQRT(zm / zp))); } -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW { // Patch the atanh() function since quadmath does not have it. - typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + typedef BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t float_type; return (::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) + x) - ::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) - x)) / 2; } -inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW +inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) BOOST_MATH_NOTHROW { // Patch the tgammaq() function for a subset of broken GCC compilers // like GCC 4.7, 4.8 on MinGW. - typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + typedef BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t float_type; if (x > float_type(0)) { @@ -612,110 +610,109 @@ inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT // Define the quadruple-precision functions in the namespace boost::math::cstdfloat::detail. -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace cstdfloat { namespace detail { - inline boost::math::cstdfloat::detail::float_internal128_t ldexp(boost::math::cstdfloat::detail::float_internal128_t x, int n) { return ::BOOST_CSTDFLOAT_FLOAT128_LDEXP(x, n); } - inline boost::math::cstdfloat::detail::float_internal128_t frexp(boost::math::cstdfloat::detail::float_internal128_t x, int* pn) { return ::BOOST_CSTDFLOAT_FLOAT128_FREXP(x, pn); } - inline boost::math::cstdfloat::detail::float_internal128_t fabs(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); } - inline boost::math::cstdfloat::detail::float_internal128_t abs(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); } - inline boost::math::cstdfloat::detail::float_internal128_t floor(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x); } - inline boost::math::cstdfloat::detail::float_internal128_t ceil(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CEIL(x); } - inline boost::math::cstdfloat::detail::float_internal128_t sqrt(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x); } - inline boost::math::cstdfloat::detail::float_internal128_t trunc(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TRUNC(x); } - inline boost::math::cstdfloat::detail::float_internal128_t exp(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); } - inline boost::math::cstdfloat::detail::float_internal128_t expm1(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x); } - inline boost::math::cstdfloat::detail::float_internal128_t pow(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, a); } - inline boost::math::cstdfloat::detail::float_internal128_t pow(boost::math::cstdfloat::detail::float_internal128_t x, int a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, boost::math::cstdfloat::detail::float_internal128_t(a)); } - inline boost::math::cstdfloat::detail::float_internal128_t log(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x); } - inline boost::math::cstdfloat::detail::float_internal128_t log10(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG10(x); } - inline boost::math::cstdfloat::detail::float_internal128_t sin(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIN(x); } - inline boost::math::cstdfloat::detail::float_internal128_t cos(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COS(x); } - inline boost::math::cstdfloat::detail::float_internal128_t tan(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TAN(x); } - inline boost::math::cstdfloat::detail::float_internal128_t asin(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASIN(x); } - inline boost::math::cstdfloat::detail::float_internal128_t acos(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOS(x); } - inline boost::math::cstdfloat::detail::float_internal128_t atan(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN(x); } - inline boost::math::cstdfloat::detail::float_internal128_t sinh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SINH(x); } - inline boost::math::cstdfloat::detail::float_internal128_t cosh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COSH(x); } - inline boost::math::cstdfloat::detail::float_internal128_t tanh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TANH(x); } - inline boost::math::cstdfloat::detail::float_internal128_t asinh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASINH(x); } - inline boost::math::cstdfloat::detail::float_internal128_t acosh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOSH(x); } - inline boost::math::cstdfloat::detail::float_internal128_t atanh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATANH(x); } - inline boost::math::cstdfloat::detail::float_internal128_t fmod(boost::math::cstdfloat::detail::float_internal128_t a, boost::math::cstdfloat::detail::float_internal128_t b) { return ::BOOST_CSTDFLOAT_FLOAT128_FMOD(a, b); } - inline boost::math::cstdfloat::detail::float_internal128_t atan2(boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN2(y, x); } - inline boost::math::cstdfloat::detail::float_internal128_t lgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x); } - inline boost::math::cstdfloat::detail::float_internal128_t tgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t ldexp(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, int n) { return ::BOOST_CSTDFLOAT_FLOAT128_LDEXP(x, n); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t frexp(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, int* pn) { return ::BOOST_CSTDFLOAT_FLOAT128_FREXP(x, pn); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t fabs(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t abs(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t floor(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t ceil(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CEIL(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t sqrt(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t trunc(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TRUNC(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t exp(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t expm1(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t pow(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, a); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t pow(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, int a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t(a)); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t log(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t log10(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG10(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t sin(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIN(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t cos(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COS(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t tan(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TAN(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t asin(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASIN(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t acos(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOS(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t atan(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t sinh(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SINH(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t cosh(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COSH(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t tanh(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TANH(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t asinh(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASINH(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t acosh(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOSH(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t atanh(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATANH(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t fmod(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t a, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t b) { return ::BOOST_CSTDFLOAT_FLOAT128_FMOD(a, b); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t atan2(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN2(y, x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t lgamma(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t tgamma(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(x); } // begin more functions - inline boost::math::cstdfloat::detail::float_internal128_t remainder(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_REMAINDER(x, y); } - inline boost::math::cstdfloat::detail::float_internal128_t remquo(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, int* z) { return ::BOOST_CSTDFLOAT_FLOAT128_REMQUO(x, y, z); } - inline boost::math::cstdfloat::detail::float_internal128_t fma(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t z) { return BOOST_CSTDFLOAT_FLOAT128_FMA(x, y, z); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t remainder(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_REMAINDER(x, y); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t remquo(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y, int* z) { return ::BOOST_CSTDFLOAT_FLOAT128_REMQUO(x, y, z); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t fma(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t z) { return BOOST_CSTDFLOAT_FLOAT128_FMA(x, y, z); } - inline boost::math::cstdfloat::detail::float_internal128_t fmax(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t fmax(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - fmax(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + fmax(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - fmax(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); } - inline boost::math::cstdfloat::detail::float_internal128_t fmin(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + fmax(T x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t fmin(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - fmin(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + fmin(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - fmin(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + fmin(T x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); } - inline boost::math::cstdfloat::detail::float_internal128_t fdim(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FDIM(x, y); } - inline boost::math::cstdfloat::detail::float_internal128_t nanq(const char* x) { return ::BOOST_CSTDFLOAT_FLOAT128_NAN(x); } - inline boost::math::cstdfloat::detail::float_internal128_t exp2(boost::math::cstdfloat::detail::float_internal128_t x) + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t fdim(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FDIM(x, y); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t nanq(const char* x) { return ::BOOST_CSTDFLOAT_FLOAT128_NAN(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t exp2(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { - return ::BOOST_CSTDFLOAT_FLOAT128_POW(boost::math::cstdfloat::detail::float_internal128_t(2), x); + return ::BOOST_CSTDFLOAT_FLOAT128_POW(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t(2), x); } - inline boost::math::cstdfloat::detail::float_internal128_t log2(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG2(x); } - inline boost::math::cstdfloat::detail::float_internal128_t log1p(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG1P(x); } - inline boost::math::cstdfloat::detail::float_internal128_t cbrt(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CBRT(x); } - inline boost::math::cstdfloat::detail::float_internal128_t hypot(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t z) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x*x + y * y + z * z); } - inline boost::math::cstdfloat::detail::float_internal128_t hypot(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t log2(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG2(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t log1p(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG1P(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t cbrt(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CBRT(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t hypot(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t z) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x*x + y * y + z * z); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t hypot(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - hypot(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + hypot(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - hypot(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); } - - - inline boost::math::cstdfloat::detail::float_internal128_t erf(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERF(x); } - inline boost::math::cstdfloat::detail::float_internal128_t erfc(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERFC(x); } - inline long long int llround(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLROUND(x); } - inline long int lround(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LROUND(x); } - inline boost::math::cstdfloat::detail::float_internal128_t round(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ROUND(x); } - inline boost::math::cstdfloat::detail::float_internal128_t nearbyint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(x); } - inline long long int llrint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLRINT(x); } - inline long int lrint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LRINT(x); } - inline boost::math::cstdfloat::detail::float_internal128_t rint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_RINT(x); } - inline boost::math::cstdfloat::detail::float_internal128_t modf(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t* y) { return ::BOOST_CSTDFLOAT_FLOAT128_MODF(x, y); } - inline boost::math::cstdfloat::detail::float_internal128_t scalbln(boost::math::cstdfloat::detail::float_internal128_t x, long int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBLN(x, y); } - inline boost::math::cstdfloat::detail::float_internal128_t scalbn(boost::math::cstdfloat::detail::float_internal128_t x, int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBN(x, y); } - inline int ilogb(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ILOGB(x); } - inline boost::math::cstdfloat::detail::float_internal128_t logb(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOGB(x); } - inline boost::math::cstdfloat::detail::float_internal128_t nextafter(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(x, y); } - inline boost::math::cstdfloat::detail::float_internal128_t nexttoward(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return -(::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(-x, -y)); } - inline boost::math::cstdfloat::detail::float_internal128_t copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(x, y); } - inline bool signbit BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(x); } - inline int fpclassify BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + hypot(T x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); } + + + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t erf(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERF(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t erfc(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERFC(x); } + inline long long int llround(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLROUND(x); } + inline long int lround(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LROUND(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t round(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ROUND(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t nearbyint(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(x); } + inline long long int llrint(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLRINT(x); } + inline long int lrint(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LRINT(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t rint(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_RINT(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t modf(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t* y) { return ::BOOST_CSTDFLOAT_FLOAT128_MODF(x, y); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t scalbln(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, long int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBLN(x, y); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t scalbn(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBN(x, y); } + inline int ilogb(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ILOGB(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t logb(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOGB(x); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t nextafter(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(x, y); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t nexttoward(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return -(::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(-x, -y)); } + inline BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(x, y); } + inline bool signbit BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(x); } + inline int fpclassify BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { if (::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x)) return FP_NAN; @@ -729,14 +726,14 @@ namespace boost { else return FP_NORMAL; } - inline bool isfinite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) + inline bool isfinite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return !::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x) && !::BOOST_CSTDFLOAT_FLOAT128_ISINF(x); } - inline bool isinf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISINF(x); } - inline bool isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x); } - inline bool isnormal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return boost::math::cstdfloat::detail::fpclassify BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x) == FP_NORMAL; } - inline bool isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + inline bool isinf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISINF(x); } + inline bool isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x); } + inline bool isnormal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x) { return BOOST_MATH_NAMESPACE::cstdfloat::detail::fpclassify BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x) == FP_NORMAL; } + inline bool isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { if (isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(y)) return false; @@ -744,16 +741,16 @@ namespace boost { } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, T y) { return isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return isgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)x, y); } - inline bool isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + inline bool isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { if (isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(y)) return false; @@ -761,16 +758,16 @@ namespace boost { } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, T y) { return isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return isgreaterequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)x, y); } - inline bool isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + inline bool isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { if (isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(y)) return false; @@ -778,17 +775,17 @@ namespace boost { } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, T y) { return isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return isless BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)x, y); } - inline bool islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + inline bool islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { if (isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(y)) return false; @@ -796,17 +793,17 @@ namespace boost { } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, T y) { return islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return islessequal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)x, y); } - inline bool islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) + inline bool islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { if (isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(y)) return false; @@ -814,118 +811,117 @@ namespace boost { } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, T y) { return islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return islessgreater BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)x, y); } - inline bool isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x) || ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(y); } + inline bool isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x) || ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t x, T y) { return isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, (BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)y); } template inline typename std::enable_if< - std::is_convertible::value - && !std::is_same::value, boost::math::cstdfloat::detail::float_internal128_t>::type - isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); } + std::is_convertible::value + && !std::is_same::value, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t>::type + isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t y) { return isunordered BOOST_MATH_PREVENT_MACRO_SUBSTITUTION((BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t)x, y); } // end more functions } } - } -} // boost::math::cstdfloat::detail + BOOST_MATH_NAMESPACE_END // boost::math::cstdfloat::detail // We will now inject the quadruple-precision functions // into the std namespace. This is done via *using* directive. namespace std { - using boost::math::cstdfloat::detail::ldexp; - using boost::math::cstdfloat::detail::frexp; - using boost::math::cstdfloat::detail::fabs; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::ldexp; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::frexp; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::fabs; #if !(defined(_GLIBCXX_USE_FLOAT128) && defined(__GNUC__) && (__GNUC__ >= 7)) #if (defined(__clang__) && !(!defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128))) || (__GNUC__ <= 6 && !defined(__clang__)) // workaround for clang using libstdc++ and old GCC - using boost::math::cstdfloat::detail::abs; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::abs; #endif #endif - using boost::math::cstdfloat::detail::floor; - using boost::math::cstdfloat::detail::ceil; - using boost::math::cstdfloat::detail::sqrt; - using boost::math::cstdfloat::detail::trunc; - using boost::math::cstdfloat::detail::exp; - using boost::math::cstdfloat::detail::expm1; - using boost::math::cstdfloat::detail::pow; - using boost::math::cstdfloat::detail::log; - using boost::math::cstdfloat::detail::log10; - using boost::math::cstdfloat::detail::sin; - using boost::math::cstdfloat::detail::cos; - using boost::math::cstdfloat::detail::tan; - using boost::math::cstdfloat::detail::asin; - using boost::math::cstdfloat::detail::acos; - using boost::math::cstdfloat::detail::atan; - using boost::math::cstdfloat::detail::sinh; - using boost::math::cstdfloat::detail::cosh; - using boost::math::cstdfloat::detail::tanh; - using boost::math::cstdfloat::detail::asinh; - using boost::math::cstdfloat::detail::acosh; - using boost::math::cstdfloat::detail::atanh; - using boost::math::cstdfloat::detail::fmod; - using boost::math::cstdfloat::detail::atan2; - using boost::math::cstdfloat::detail::lgamma; - using boost::math::cstdfloat::detail::tgamma; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::floor; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::ceil; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::sqrt; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::trunc; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::exp; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::expm1; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::pow; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::log; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::log10; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::sin; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::cos; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::tan; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::asin; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::acos; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::atan; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::sinh; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::cosh; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::tanh; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::asinh; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::acosh; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::atanh; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::fmod; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::atan2; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::lgamma; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::tgamma; // begin more functions - using boost::math::cstdfloat::detail::remainder; - using boost::math::cstdfloat::detail::remquo; - using boost::math::cstdfloat::detail::fma; - using boost::math::cstdfloat::detail::fmax; - using boost::math::cstdfloat::detail::fmin; - using boost::math::cstdfloat::detail::fdim; - using boost::math::cstdfloat::detail::nanq; - using boost::math::cstdfloat::detail::exp2; - using boost::math::cstdfloat::detail::log2; - using boost::math::cstdfloat::detail::log1p; - using boost::math::cstdfloat::detail::cbrt; - using boost::math::cstdfloat::detail::hypot; - using boost::math::cstdfloat::detail::erf; - using boost::math::cstdfloat::detail::erfc; - using boost::math::cstdfloat::detail::llround; - using boost::math::cstdfloat::detail::lround; - using boost::math::cstdfloat::detail::round; - using boost::math::cstdfloat::detail::nearbyint; - using boost::math::cstdfloat::detail::llrint; - using boost::math::cstdfloat::detail::lrint; - using boost::math::cstdfloat::detail::rint; - using boost::math::cstdfloat::detail::modf; - using boost::math::cstdfloat::detail::scalbln; - using boost::math::cstdfloat::detail::scalbn; - using boost::math::cstdfloat::detail::ilogb; - using boost::math::cstdfloat::detail::logb; - using boost::math::cstdfloat::detail::nextafter; - using boost::math::cstdfloat::detail::nexttoward; - using boost::math::cstdfloat::detail::copysign; - using boost::math::cstdfloat::detail::signbit; - using boost::math::cstdfloat::detail::fpclassify; - using boost::math::cstdfloat::detail::isfinite; - using boost::math::cstdfloat::detail::isinf; - using boost::math::cstdfloat::detail::isnan; - using boost::math::cstdfloat::detail::isnormal; - using boost::math::cstdfloat::detail::isgreater; - using boost::math::cstdfloat::detail::isgreaterequal; - using boost::math::cstdfloat::detail::isless; - using boost::math::cstdfloat::detail::islessequal; - using boost::math::cstdfloat::detail::islessgreater; - using boost::math::cstdfloat::detail::isunordered; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::remainder; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::remquo; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::fma; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::fmax; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::fmin; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::fdim; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::nanq; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::exp2; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::log2; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::log1p; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::cbrt; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::hypot; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::erf; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::erfc; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::llround; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::lround; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::round; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::nearbyint; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::llrint; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::lrint; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::rint; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::modf; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::scalbln; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::scalbn; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::ilogb; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::logb; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::nextafter; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::nexttoward; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::copysign; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::signbit; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::fpclassify; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::isfinite; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::isinf; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::isnan; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::isnormal; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::isgreater; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::isgreaterequal; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::isless; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::islessequal; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::islessgreater; + using BOOST_MATH_NAMESPACE::cstdfloat::detail::isunordered; // end more functions } // namespace std diff --git a/include/boost/math/cstdfloat/cstdfloat_complex.hpp b/include/boost/math/cstdfloat/cstdfloat_complex.hpp index f79ff6d423..af474899e5 100644 --- a/include/boost/math/cstdfloat/cstdfloat_complex.hpp +++ b/include/boost/math/cstdfloat/cstdfloat_complex.hpp @@ -29,7 +29,7 @@ #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) - #define BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE boost::math::cstdfloat::detail::float_internal128_t + #define BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t #include #undef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE diff --git a/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp b/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp index a4007ee186..1ae6a74de4 100644 --- a/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp +++ b/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp @@ -90,21 +90,6 @@ complex(const complex&); complex(const complex&); - #if defined(BOOST_NO_CXX11_CONSTEXPR) - complex(const value_type& r = value_type(), - const value_type& i = value_type()) : re(r), - im(i) { } - - template - explicit complex(const complex& x) : re(x.real()), - im(x.imag()) { } - - const value_type& real() const { return re; } - const value_type& imag() const { return im; } - - value_type& real() { return re; } - value_type& imag() { return im; } - #else constexpr complex(const value_type& r = value_type(), const value_type& i = value_type()) : re(r), im(i) { } @@ -115,7 +100,6 @@ value_type real() const { return re; } value_type imag() const { return im; } - #endif void real(value_type r) { re = r; } void imag(value_type i) { im = i; } @@ -207,13 +191,13 @@ inline complex::complex(const complex& ld) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.imag())) { } } // namespace std - namespace boost { namespace math { namespace cstdfloat { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace cstdfloat { namespace detail { template inline std::complex multiply_by_i(const std::complex& x) { // Multiply x (in C) by I (the imaginary component), and return the result. return std::complex(-x.imag(), x.real()); } - } } } } // boost::math::cstdfloat::detail + } } BOOST_MATH_NAMESPACE_END // boost::math::cstdfloat::detail namespace std { @@ -376,19 +360,19 @@ inline complex asin(const complex& x) { - return -boost::math::cstdfloat::detail::multiply_by_i(std::log(boost::math::cstdfloat::detail::multiply_by_i(x) + std::sqrt(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - (x * x)))); + return -BOOST_MATH_NAMESPACE::cstdfloat::detail::multiply_by_i(std::log(BOOST_MATH_NAMESPACE::cstdfloat::detail::multiply_by_i(x) + std::sqrt(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - (x * x)))); } inline complex acos(const complex& x) { - return boost::math::constants::half_pi() - std::asin(x); + return BOOST_MATH_NAMESPACE::constants::half_pi() - std::asin(x); } inline complex atan(const complex& x) { - const complex izz = boost::math::cstdfloat::detail::multiply_by_i(x); + const complex izz = BOOST_MATH_NAMESPACE::cstdfloat::detail::multiply_by_i(x); - return boost::math::cstdfloat::detail::multiply_by_i(std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - izz) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + izz)) / 2; + return BOOST_MATH_NAMESPACE::cstdfloat::detail::multiply_by_i(std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - izz) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + izz)) / 2; } inline complex exp(const complex& x) @@ -442,7 +426,7 @@ return std::complex ( log(x.imag()), - boost::math::constants::half_pi() + BOOST_MATH_NAMESPACE::constants::half_pi() ); } else @@ -450,7 +434,7 @@ return std::complex ( log(-x.imag()), - -boost::math::constants::half_pi() + -BOOST_MATH_NAMESPACE::constants::half_pi() ); } } @@ -463,7 +447,7 @@ inline complex log10(const complex& x) { - return std::log(x) / boost::math::constants::ln_ten(); + return std::log(x) / BOOST_MATH_NAMESPACE::constants::ln_ten(); } inline complex pow(const complex& x, @@ -555,7 +539,7 @@ const bool x_im_isneg = (x.imag() < 0); const bool x_im_iszero = ((x_im_isneg || (x.imag() > 0)) == false); - if(x_im_iszero) + if(x_im_iszero && ((x.real() >= 0) || (a == floor(a)))) { using std::pow; diff --git a/include/boost/math/cstdfloat/cstdfloat_iostream.hpp b/include/boost/math/cstdfloat/cstdfloat_iostream.hpp index 2ae2aea33b..c504767f0e 100644 --- a/include/boost/math/cstdfloat/cstdfloat_iostream.hpp +++ b/include/boost/math/cstdfloat/cstdfloat_iostream.hpp @@ -32,8 +32,7 @@ #include #include -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // // What follows is the input streaming code: this is not "proper" iostream code at all @@ -77,19 +76,18 @@ namespace boost { } } - } -} + BOOST_MATH_NAMESPACE_END #if defined(__GNUC__) && !defined(BOOST_MATH_TEST_IO_AS_INTEL_QUAD) // Forward declarations of quadruple-precision string functions. extern "C" int quadmath_snprintf(char *str, size_t size, const char *format, ...) BOOST_MATH_NOTHROW; - extern "C" boost::math::cstdfloat::detail::float_internal128_t strtoflt128(const char*, char **) BOOST_MATH_NOTHROW; + extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t strtoflt128(const char*, char **) BOOST_MATH_NOTHROW; namespace std { template - inline std::basic_ostream& operator<<(std::basic_ostream& os, const boost::math::cstdfloat::detail::float_internal128_t& x) + inline std::basic_ostream& operator<<(std::basic_ostream& os, const BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t& x) { std::basic_ostringstream ostr; ostr.flags(os.flags()); @@ -98,10 +96,14 @@ namespace boost { char my_buffer[64U]; - const int my_prec = static_cast(os.precision()); - const int my_digits = ((my_prec == 0) ? 36 : my_prec); + const int my_prec = static_cast(os.precision()); - const std::ios_base::fmtflags my_flags = os.flags(); + const std::ios_base::fmtflags my_flags = os.flags(); + const bool is_hexfloat = ((my_flags & std::ios_base::floatfield) == std::ios_base::floatfield); + + // std::hexfloat ignores stream precision. A negative printf precision + // supplied through '*' is treated as if the precision were omitted. + const int my_digits = (is_hexfloat ? -1 : ((my_prec == 0) ? 36 : my_prec)); char my_format_string[8U]; @@ -121,7 +123,8 @@ namespace boost { char the_notation_char; - if (my_flags & std::ios_base::scientific) { the_notation_char = 'e'; } + if (is_hexfloat) { the_notation_char = ((my_flags & std::ios_base::uppercase) ? 'A' : 'a'); } + else if(my_flags & std::ios_base::scientific) { the_notation_char = 'e'; } else if(my_flags & std::ios_base::fixed) { the_notation_char = 'f'; } else { the_notation_char = 'g'; } @@ -181,9 +184,9 @@ namespace boost { } template - inline std::basic_istream& operator>>(std::basic_istream& is, boost::math::cstdfloat::detail::float_internal128_t& x) + inline std::basic_istream& operator>>(std::basic_istream& is, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t& x) { - std::string str = boost::math::detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY"); + std::string str = BOOST_MATH_NAMESPACE::detail::read_string_while(is, "+-eEpPxXbBcCdD.0123456789infINFnanNANinfinityINFINITY"); char* p_end; @@ -220,7 +223,7 @@ namespace boost { #include #include - namespace boost { namespace math { namespace cstdfloat { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace cstdfloat { namespace detail { template void format_float_string(string_type& str, @@ -497,7 +500,7 @@ namespace boost { { int e = -expon / 2; - const float_type t2 = boost::math::cstdfloat::detail::pown(ten, e); + const float_type t2 = BOOST_MATH_NAMESPACE::cstdfloat::detail::pown(ten, e); eval_multiply(t, t2, x); eval_multiply(t, t2); @@ -509,7 +512,7 @@ namespace boost { } else { - t = boost::math::cstdfloat::detail::pown(ten, -expon); + t = BOOST_MATH_NAMESPACE::cstdfloat::detail::pown(ten, -expon); eval_multiply(t, x); } @@ -749,15 +752,15 @@ namespace boost { if(expon > (std::numeric_limits::min_exponent10 + 2)) { - t = boost::math::cstdfloat::detail::pown(t, expon); + t = BOOST_MATH_NAMESPACE::cstdfloat::detail::pown(t, expon); eval_multiply(value, t); } else { - t = boost::math::cstdfloat::detail::pown(t, (expon + digits_seen + 1)); + t = BOOST_MATH_NAMESPACE::cstdfloat::detail::pown(t, (expon + digits_seen + 1)); eval_multiply(value, t); t = ten; - t = boost::math::cstdfloat::detail::pown(t, (-digits_seen - 1)); + t = BOOST_MATH_NAMESPACE::cstdfloat::detail::pown(t, (-digits_seen - 1)); eval_multiply(value, t); } } @@ -769,16 +772,16 @@ namespace boost { return (*p == '\0'); } - } } } } // boost::math::cstdfloat::detail + } } BOOST_MATH_NAMESPACE_END // boost::math::cstdfloat::detail namespace std { template - inline std::basic_ostream& operator<<(std::basic_ostream& os, const boost::math::cstdfloat::detail::float_internal128_t& x) + inline std::basic_ostream& operator<<(std::basic_ostream& os, const BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t& x) { - boost::math::cstdfloat::detail::float_internal128_t non_const_x = x; + BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t non_const_x = x; - const std::string str = boost::math::cstdfloat::detail::convert_to_string(non_const_x, + const std::string str = BOOST_MATH_NAMESPACE::cstdfloat::detail::convert_to_string(non_const_x, os.precision(), os.flags()); @@ -793,11 +796,11 @@ namespace boost { } template - inline std::basic_istream& operator>>(std::basic_istream& is, boost::math::cstdfloat::detail::float_internal128_t& x) + inline std::basic_istream& operator>>(std::basic_istream& is, BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t& x) { - std::string str = boost::math::detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY"); + std::string str = BOOST_MATH_NAMESPACE::detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY"); - const bool conversion_is_ok = boost::math::cstdfloat::detail::convert_from_string(x, str.c_str()); + const bool conversion_is_ok = BOOST_MATH_NAMESPACE::cstdfloat::detail::convert_from_string(x, str.c_str()); if(false == conversion_is_ok) { diff --git a/include/boost/math/cstdfloat/cstdfloat_limits.hpp b/include/boost/math/cstdfloat/cstdfloat_limits.hpp index 59c614781d..a7828478b9 100644 --- a/include/boost/math/cstdfloat/cstdfloat_limits.hpp +++ b/include/boost/math/cstdfloat/cstdfloat_limits.hpp @@ -38,18 +38,18 @@ #endif // Forward declaration of the quadruple-precision square root function. - extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(boost::math::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; + extern "C" BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t) BOOST_MATH_NOTHROW; namespace std { template<> - class numeric_limits + class numeric_limits { public: static constexpr bool is_specialized = true; - static boost::math::cstdfloat::detail::float_internal128_t (min) () noexcept { return BOOST_CSTDFLOAT_FLOAT128_MIN; } - static boost::math::cstdfloat::detail::float_internal128_t (max) () noexcept { return BOOST_CSTDFLOAT_FLOAT128_MAX; } - static boost::math::cstdfloat::detail::float_internal128_t lowest() noexcept { return -(max)(); } + static BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t (min) () noexcept { return BOOST_CSTDFLOAT_FLOAT128_MIN; } + static BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t (max) () noexcept { return BOOST_CSTDFLOAT_FLOAT128_MAX; } + static BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t lowest() noexcept { return -(max)(); } static constexpr int digits = 113; static constexpr int digits10 = 33; static constexpr int max_digits10 = 36; @@ -57,8 +57,8 @@ static constexpr bool is_integer = false; static constexpr bool is_exact = false; static constexpr int radix = 2; - static boost::math::cstdfloat::detail::float_internal128_t epsilon () { return BOOST_CSTDFLOAT_FLOAT128_EPS; } - static boost::math::cstdfloat::detail::float_internal128_t round_error() { return BOOST_FLOAT128_C(0.5); } + static BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t epsilon () { return BOOST_CSTDFLOAT_FLOAT128_EPS; } + static BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t round_error() { return BOOST_FLOAT128_C(0.5); } static constexpr int min_exponent = -16381; static constexpr int min_exponent10 = static_cast((min_exponent * 301L) / 1000L); static constexpr int max_exponent = +16384; @@ -68,10 +68,10 @@ static constexpr bool has_signaling_NaN = false; static constexpr float_denorm_style has_denorm = denorm_present; static constexpr bool has_denorm_loss = false; - static boost::math::cstdfloat::detail::float_internal128_t infinity () { return BOOST_FLOAT128_C(1.0) / BOOST_FLOAT128_C(0.0); } - static boost::math::cstdfloat::detail::float_internal128_t quiet_NaN () { return -(::BOOST_CSTDFLOAT_FLOAT128_SQRT(BOOST_FLOAT128_C(-1.0))); } - static boost::math::cstdfloat::detail::float_internal128_t signaling_NaN() { return BOOST_FLOAT128_C(0.0); } - static boost::math::cstdfloat::detail::float_internal128_t denorm_min () { return BOOST_CSTDFLOAT_FLOAT128_DENORM_MIN; } + static BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t infinity () { return BOOST_FLOAT128_C(1.0) / BOOST_FLOAT128_C(0.0); } + static BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t quiet_NaN () { return -(::BOOST_CSTDFLOAT_FLOAT128_SQRT(BOOST_FLOAT128_C(-1.0))); } + static BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t signaling_NaN() { return BOOST_FLOAT128_C(0.0); } + static BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t denorm_min () { return BOOST_CSTDFLOAT_FLOAT128_DENORM_MIN; } static constexpr bool is_iec559 = true; static constexpr bool is_bounded = true; static constexpr bool is_modulo = false; diff --git a/include/boost/math/cstdfloat/cstdfloat_types.hpp b/include/boost/math/cstdfloat/cstdfloat_types.hpp index b64276558b..c1e912827d 100644 --- a/include/boost/math/cstdfloat/cstdfloat_types.hpp +++ b/include/boost/math/cstdfloat/cstdfloat_types.hpp @@ -209,7 +209,7 @@ #if (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT) // Specify the underlying name of the internal 128-bit floating-point type definition. - namespace boost { namespace math { namespace cstdfloat { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace cstdfloat { namespace detail { #if defined(__GNUC__) typedef __float128 float_internal128_t; #elif defined(__INTEL_COMPILER) @@ -217,9 +217,9 @@ #else #error "Sorry, the compiler is neither GCC, nor Intel, I don't know how to configure ." #endif - } } } } // boost::math::cstdfloat::detail + } } BOOST_MATH_NAMESPACE_END // boost::math::cstdfloat::detail - #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE boost::math::cstdfloat::detail::float_internal128_t + #define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE BOOST_MATH_NAMESPACE::cstdfloat::detail::float_internal128_t #undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH #define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128 #undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE diff --git a/include/boost/math/differentiation/autodiff.hpp b/include/boost/math/differentiation/autodiff.hpp index b8880f24de..4225385db7 100644 --- a/include/boost/math/differentiation/autodiff.hpp +++ b/include/boost/math/differentiation/autodiff.hpp @@ -6,7 +6,11 @@ #ifndef BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP #define BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP +// cstdfloat is outside the module surface and textually includes standard +// library headers, which must not enter the module purview. +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include @@ -20,6 +24,7 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -29,9 +34,9 @@ #include #include #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { // Automatic Differentiation v1 inline namespace autodiff_v1 { @@ -49,7 +54,7 @@ struct promote_args_n { } // namespace detail -template +BOOST_MATH_EXPORT template using promote = typename detail::promote_args_n::type; namespace detail { @@ -66,6 +71,14 @@ struct is_fvar_impl> : std::true_type {}; template using is_fvar = is_fvar_impl::type>; +// Unlike std::is_constructible, this accepts explicit-only conversions such as double -> std::float32_t. +template +struct is_static_castable : std::false_type {}; + +template +struct is_static_castable(static_cast(std::declval())))> + : std::true_type {}; + template struct nest_fvar { using type = fvar::type, Order>; @@ -146,8 +159,8 @@ class fvar { // RealType(ca) | RealType | RealType is copy constructible from the arithmetic types. explicit fvar(root_type const&); // Initialize a constant. (No epsilon terms.) - template - fvar(RealType2 const& ca); // Supports any RealType2 for which static_cast(ca) compiles. + template ::value, int>::type = 0> + fvar(RealType2 const& ca); // Supports any RealType2 for which static_cast(ca) compiles. // r = cr | RealType& | Assignment operator. fvar& operator=(fvar const&) = default; @@ -539,6 +552,10 @@ template promote, fvar> fmod(fvar const&, fvar const&); +// fma(cr1, cr2, cr3) | RealType +template +fvar fma(fvar const&, fvar const&, fvar const&); + // round(cr1) | RealType template fvar round(fvar const&); @@ -615,10 +632,10 @@ struct zero : std::integral_constant {}; } // namespace detail -template +BOOST_MATH_EXPORT template using autodiff_fvar = typename detail::nest_fvar::type; -template +BOOST_MATH_EXPORT template autodiff_fvar make_fvar(RealType const& ca) { return autodiff_fvar(ca, true); } @@ -638,7 +655,7 @@ auto make_ftuple_impl(std::index_sequence, RealTypes const&... ca) { } // namespace detail -template +BOOST_MATH_EXPORT template auto make_ftuple(RealTypes const&... ca) { static_assert(sizeof...(Orders) == sizeof...(RealTypes), "Number of Orders must match number of function parameters."); @@ -677,9 +694,9 @@ fvar::fvar(fvar const& cr) { template fvar::fvar(root_type const& ca) : v{{static_cast(ca)}} {} -// Can cause compiler error if RealType2 cannot be cast to root_type. +// Constrained so that e.g. Eigen expression templates are not implicitly convertible to fvar. template -template +template ::value, int>::type> fvar::fvar(RealType2 const& ca) : v{{static_cast(ca)}} {} /* @@ -1679,39 +1696,50 @@ promote, fvar> atan2(fvar promote, fvar> fmod(fvar const& cr1, fvar const& cr2) { - using boost::math::trunc; + using BOOST_MATH_NAMESPACE::trunc; auto const numer = static_cast::root_type>(cr1); auto const denom = static_cast::root_type>(cr2); return cr1 - cr2 * trunc(numer / denom); } +template +fvar fma(fvar const& cr1, fvar const& cr2, fvar const& cr3) { + using std::fma; + using root_type = typename fvar::root_type; + // The derivatives are those of cr1 * cr2 + cr3, and the value is rounded once, as fma's is: + fvar result = cr1 * cr2 + cr3; + root_type const value = + fma(static_cast(cr1), static_cast(cr2), static_cast(cr3)); + return result += value - static_cast(result); +} + template fvar round(fvar const& cr) { - using boost::math::round; + using BOOST_MATH_NAMESPACE::round; return fvar(round(static_cast::root_type>(cr))); } template int iround(fvar const& cr) { - using boost::math::iround; + using BOOST_MATH_NAMESPACE::iround; return iround(static_cast::root_type>(cr)); } template long lround(fvar const& cr) { - using boost::math::lround; + using BOOST_MATH_NAMESPACE::lround; return lround(static_cast::root_type>(cr)); } template long long llround(fvar const& cr) { - using boost::math::llround; + using BOOST_MATH_NAMESPACE::llround; return llround(static_cast::root_type>(cr)); } template fvar trunc(fvar const& cr) { - using boost::math::trunc; + using BOOST_MATH_NAMESPACE::trunc; return fvar(trunc(static_cast::root_type>(cr))); } @@ -1723,13 +1751,13 @@ long double truncl(fvar const& cr) { template int itrunc(fvar const& cr) { - using boost::math::itrunc; + using BOOST_MATH_NAMESPACE::itrunc; return itrunc(static_cast::root_type>(cr)); } template long long lltrunc(fvar const& cr) { - using boost::math::lltrunc; + using BOOST_MATH_NAMESPACE::lltrunc; return lltrunc(static_cast::root_type>(cr)); } @@ -1760,7 +1788,7 @@ fvar acos(fvar const& cr) { template fvar acosh(fvar const& cr) { - using boost::math::acosh; + using BOOST_MATH_NAMESPACE::acosh; using root_type = typename fvar::root_type; constexpr size_t order = fvar::order_sum; root_type const d0 = acosh(static_cast(cr)); @@ -1775,7 +1803,7 @@ fvar acosh(fvar const& cr) { template fvar asinh(fvar const& cr) { - using boost::math::asinh; + using BOOST_MATH_NAMESPACE::asinh; using root_type = typename fvar::root_type; constexpr size_t order = fvar::order_sum; root_type const d0 = asinh(static_cast(cr)); @@ -1790,7 +1818,7 @@ fvar asinh(fvar const& cr) { template fvar atanh(fvar const& cr) { - using boost::math::atanh; + using BOOST_MATH_NAMESPACE::atanh; using root_type = typename fvar::root_type; constexpr size_t order = fvar::order_sum; root_type const d0 = atanh(static_cast(cr)); @@ -1819,7 +1847,7 @@ fvar cosh(fvar const& cr) { template fvar digamma(fvar const& cr) { - using boost::math::digamma; + using BOOST_MATH_NAMESPACE::digamma; using root_type = typename fvar::root_type; constexpr size_t order = fvar::order_sum; root_type const x = static_cast(cr); @@ -1830,13 +1858,13 @@ fvar digamma(fvar const& cr) { static_assert(order <= static_cast((std::numeric_limits::max)()), "order exceeds maximum derivative for boost::math::polygamma()."); return cr.apply_derivatives( - order, [&x, &d0](size_t i) { return i ? boost::math::polygamma(static_cast(i), x) : d0; }); + order, [&x, &d0](size_t i) { return i ? BOOST_MATH_NAMESPACE::polygamma(static_cast(i), x) : d0; }); } } template fvar erf(fvar const& cr) { - using boost::math::erf; + using BOOST_MATH_NAMESPACE::erf; using root_type = typename fvar::root_type; constexpr size_t order = fvar::order_sum; root_type const d0 = erf(static_cast(cr)); @@ -1851,7 +1879,7 @@ fvar erf(fvar const& cr) { template fvar erfc(fvar const& cr) { - using boost::math::erfc; + using BOOST_MATH_NAMESPACE::erfc; using root_type = typename fvar::root_type; constexpr size_t order = fvar::order_sum; root_type const d0 = erfc(static_cast(cr)); @@ -1867,7 +1895,7 @@ fvar erfc(fvar const& cr) { template fvar lambert_w0(fvar const& cr) { using std::exp; - using boost::math::lambert_w0; + using BOOST_MATH_NAMESPACE::lambert_w0; using root_type = typename fvar::root_type; constexpr size_t order = fvar::order_sum; root_type derivatives[order + 1]; @@ -1915,7 +1943,7 @@ fvar lgamma(fvar const& cr) { static_assert(order <= static_cast((std::numeric_limits::max)()) + 1, "order exceeds maximum derivative for boost::math::polygamma()."); return cr.apply_derivatives( - order, [&x, &d0](size_t i) { return i ? boost::math::polygamma(static_cast(i - 1), x) : d0; }); + order, [&x, &d0](size_t i) { return i ? BOOST_MATH_NAMESPACE::polygamma(static_cast(i - 1), x) : d0; }); } } @@ -1974,27 +2002,25 @@ fvar tgamma(fvar const& cr) { } // namespace detail } // namespace autodiff_v1 } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END namespace std { // boost::math::tools::digits() is handled by this std::numeric_limits<> specialization, // and similarly for max_value, min_value, log_max_value, log_min_value, and epsilon. template -class numeric_limits> - : public numeric_limits::root_type> { +class numeric_limits> + : public numeric_limits::root_type> { }; } // namespace std -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { template -using autodiff_fvar_type = differentiation::detail::fvar; +using autodiff_fvar_type = differentiation::autodiff_v1::detail::fvar; template using autodiff_root_type = typename autodiff_fvar_type::root_type; @@ -2005,11 +2031,7 @@ template struct promote_args, detail::autodiff_fvar_type> { using type = detail::autodiff_fvar_type::type, -#ifndef BOOST_MATH_NO_CXX14_CONSTEXPR (std::max)(Order0, Order1)>; -#else - Order0; -#endif }; template @@ -2027,7 +2049,7 @@ struct promote_args> { using type = detail::autodiff_fvar_type::type, Order1>; }; -template +BOOST_MATH_EXPORT template inline constexpr destination_t real_cast(detail::autodiff_fvar_type const& from_v) noexcept(BOOST_MATH_IS_FLOAT(destination_t) && BOOST_MATH_IS_FLOAT(RealType)) { return real_cast(static_cast>(from_v)); @@ -2037,8 +2059,8 @@ inline constexpr destination_t real_cast(detail::autodiff_fvar_type -using fvar_t = differentiation::detail::fvar; +BOOST_MATH_EXPORT template +using fvar_t = differentiation::autodiff_v1::detail::fvar; template struct evaluation, Policy> { using type = fvar_t::type, Order>; @@ -2051,8 +2073,7 @@ struct evaluation, Policy> { }; } // namespace policies -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef BOOST_MATH_NO_CXX17_IF_CONSTEXPR #include "autodiff_cpp11.hpp" diff --git a/include/boost/math/differentiation/autodiff_cpp11.hpp b/include/boost/math/differentiation/autodiff_cpp11.hpp index 1624c494ee..026a8ec3c2 100644 --- a/include/boost/math/differentiation/autodiff_cpp11.hpp +++ b/include/boost/math/differentiation/autodiff_cpp11.hpp @@ -19,11 +19,12 @@ "Do not #include this file directly. This should only be #included by autodiff.hpp for C++11 compatibility." #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace mp = tools::meta_programming; @@ -96,7 +97,7 @@ get_type_at, sizeof...(Orders)> fvar::der static_assert(sizeof...(Orders) <= depth, "Number of parameters to derivative(...) cannot exceed fvar::depth."); return at(static_cast(orders)...) * - product(boost::math::factorial(static_cast(orders))...); + product(BOOST_MATH_NAMESPACE::factorial(static_cast(orders))...); } template @@ -383,5 +384,4 @@ auto make_ftuple(RealTypes const&... ca) } // namespace autodiff_v1 } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END diff --git a/include/boost/math/differentiation/autodiff_reverse.hpp b/include/boost/math/differentiation/autodiff_reverse.hpp index d7b5124ce5..87e5076abb 100644 --- a/include/boost/math/differentiation/autodiff_reverse.hpp +++ b/include/boost/math/differentiation/autodiff_reverse.hpp @@ -38,14 +38,15 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #define BOOST_MATH_BUFFER_SIZE 65536 -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { @@ -307,7 +308,7 @@ class gradient_node if (!n_) // leaf node return; - using boost::math::differentiation::reverse_mode::fabs; + using BOOST_MATH_NAMESPACE::differentiation::reverse_mode::fabs; using std::fabs; if (!adjoint_ || fabs(*adjoint_) < 2 * std::numeric_limits::epsilon()) return; @@ -612,6 +613,15 @@ rvar make_rvar(const expression(expr); } +// The value is a*b + c rounded twice, not once; the derivatives are exact either way. +template +rvar fma(const expression &a, + const expression &b, + const expression &c) +{ + return a * b + c; +} + namespace detail { /** @brief helper overload for grad implementation. @@ -797,14 +807,13 @@ auto grad_nd(ftype &f, First first, Other... other) } } // namespace reverse_mode } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END namespace std { // copied from forward mode template -class numeric_limits> - : public numeric_limits> + : public numeric_limits::value_type> {}; } // namespace std diff --git a/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_operator_expressions.hpp b/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_operator_expressions.hpp index 9efd485bca..927aa3c6c5 100644 --- a/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_operator_expressions.hpp +++ b/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_operator_expressions.hpp @@ -7,8 +7,9 @@ #include -namespace boost { -namespace math { +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { /****************************************************************************************************************/ @@ -270,7 +271,6 @@ struct const_div_by_expr } // namespace reverse_mode } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_et.hpp b/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_et.hpp index 9d552fbe92..f5c5c7e8b0 100644 --- a/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_et.hpp +++ b/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_et.hpp @@ -7,8 +7,9 @@ #define REVERSE_MODE_AUTODIFF_BASIC_OPS_ET_HPP #include -namespace boost { -namespace math { +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { template @@ -154,7 +155,6 @@ div_by_const_expr operator/( } } // namespace reverse_mode } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // REVERSE_MODE_AUTODIFF_BASIC_OPS_ET_HPP diff --git a/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_no_et.hpp b/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_no_et.hpp index 67c1fb77e9..5c13b1b7bf 100644 --- a/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_no_et.hpp +++ b/include/boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_no_et.hpp @@ -5,8 +5,9 @@ #ifndef REVERSE_MODE_AUTODIFF_BASIC_OPS_NO_ET_HPP #define REVERSE_MODE_AUTODIFF_BASIC_OPS_NO_ET_HPP #include -namespace boost { -namespace math { +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { @@ -149,6 +150,5 @@ rvar operator/(const expression -namespace boost { -namespace math { +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { template @@ -162,6 +163,5 @@ bool operator>=(const RealType2 &lhs, const expression #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { @@ -82,8 +81,8 @@ struct erf_expr : public abstract_unary_expression 1)>( - [this](auto &&x) { return reverse_mode::erf(std::forward(x)); }, - [this](auto &&x) { return boost::math::erf(std::forward(x)); }, + [](auto &&x) { return reverse_mode::erf(std::forward(x)); }, + [](auto &&x) { return BOOST_MATH_NAMESPACE::erf(std::forward(x)); }, this->arg.evaluate()); } static const inner_t derivative(const inner_t &argv, @@ -118,8 +117,8 @@ struct erfc_expr : public abstract_unary_expression 1))>( - [this](auto &&x) { return reverse_mode::erfc(std::forward(x)); }, - [this](auto &&x) { return boost::math::erfc(std::forward(x)); }, + [](auto &&x) { return reverse_mode::erfc(std::forward(x)); }, + [](auto &&x) { return BOOST_MATH_NAMESPACE::erfc(std::forward(x)); }, this->arg.evaluate()); } static const inner_t derivative(const inner_t &argv, @@ -155,8 +154,8 @@ struct erf_inv_expr : public abstract_unary_expression 1))>( - [this](auto &&x) { return reverse_mode::erf_inv(std::forward(x)); }, - [this](auto &&x) { return boost::math::erf_inv(std::forward(x)); }, + [](auto &&x) { return reverse_mode::erf_inv(std::forward(x)); }, + [](auto &&x) { return BOOST_MATH_NAMESPACE::erf_inv(std::forward(x)); }, this->arg.evaluate()); } static const inner_t derivative(const inner_t &argv, @@ -172,7 +171,7 @@ struct erf_inv_expr : public abstract_unary_expression(0.5) * sqrt(constants::pi()) - * exp(pow(boost::math::erf_inv(x), static_cast(2.0))); + * exp(pow(BOOST_MATH_NAMESPACE::erf_inv(x), static_cast(2.0))); }, argv); } @@ -203,8 +202,8 @@ struct erfc_inv_expr inner_t evaluate() const { return detail::if_functional_dispatch<((DerivativeOrder > 1))>( - [this](auto &&x) { return reverse_mode::erfc_inv(std::forward(x)); }, - [this](auto &&x) { return boost::math::erfc_inv(std::forward(x)); }, + [](auto &&x) { return reverse_mode::erfc_inv(std::forward(x)); }, + [](auto &&x) { return BOOST_MATH_NAMESPACE::erfc_inv(std::forward(x)); }, this->arg.evaluate()); } static const inner_t derivative(const inner_t &argv, @@ -220,7 +219,7 @@ struct erfc_inv_expr }, [](auto &&x) { return static_cast(-0.5) * sqrt(constants::pi()) - * exp(pow(boost::math::erfc_inv(x), static_cast(2.0))); + * exp(pow(BOOST_MATH_NAMESPACE::erfc_inv(x), static_cast(2.0))); }, argv); } @@ -228,7 +227,6 @@ struct erfc_inv_expr } // namespace reverse_mode } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // REVERSE_MODE_AUTODIFF_ERF_OVERLOADS_HPP diff --git a/include/boost/math/differentiation/detail/reverse_mode_autodiff_expression_template_base.hpp b/include/boost/math/differentiation/detail/reverse_mode_autodiff_expression_template_base.hpp index 494b317c67..ab64903967 100644 --- a/include/boost/math/differentiation/detail/reverse_mode_autodiff_expression_template_base.hpp +++ b/include/boost/math/differentiation/detail/reverse_mode_autodiff_expression_template_base.hpp @@ -5,10 +5,13 @@ #ifndef REVERSE_MODE_AUTODIFF_EXPRESSION_TEMPLATE_BASE_HPP #define REVERSE_MODE_AUTODIFF_EXPRESSION_TEMPLATE_BASE_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include -namespace boost { -namespace math { +#endif +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { @@ -96,7 +99,7 @@ struct count_rvar_impl< = count_rvar_impl::value; }; template -constexpr std::size_t count_rvars = detail::count_rvar_impl::value; +BOOST_MATH_INLINE_CONSTEXPR std::size_t count_rvars = detail::count_rvar_impl::value; template struct is_expression : std::is_base_of::type> @@ -252,7 +255,6 @@ struct abstract_unary_expression }; } // namespace reverse_mode } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // REVERSE_MODE_AUTODIFF_EXPRESSION_TEMPLATE_BASE_HPP diff --git a/include/boost/math/differentiation/detail/reverse_mode_autodiff_helper_functions.hpp b/include/boost/math/differentiation/detail/reverse_mode_autodiff_helper_functions.hpp index 4bd88ad68a..6553702a1e 100644 --- a/include/boost/math/differentiation/detail/reverse_mode_autodiff_helper_functions.hpp +++ b/include/boost/math/differentiation/detail/reverse_mode_autodiff_helper_functions.hpp @@ -5,14 +5,16 @@ #ifndef BOOST_REVERSE_MODE_AUTODIFF_HELPER_FUNCTIONS_HPP #define BOOST_REVERSE_MODE_AUTODIFF_HELPER_FUNCTIONS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include -namespace boost { -namespace math { +#endif +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode {} // namespace reverse_mode } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/differentiation/detail/reverse_mode_autodiff_memory_management.hpp b/include/boost/math/differentiation/detail/reverse_mode_autodiff_memory_management.hpp index 382af5f5c5..f562a6f1ab 100644 --- a/include/boost/math/differentiation/detail/reverse_mode_autodiff_memory_management.hpp +++ b/include/boost/math/differentiation/detail/reverse_mode_autodiff_memory_management.hpp @@ -6,17 +6,20 @@ #ifndef REVERSE_MODE_AUTODIFF_MEMORY_MANAGEMENT_HPP #define REVERSE_MODE_AUTODIFF_MEMORY_MANAGEMENT_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include -namespace boost { -namespace math { +#endif +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { namespace detail { @@ -456,7 +459,6 @@ class flat_linear_allocator } // namespace detail } // namespace reverse_mode } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/differentiation/detail/reverse_mode_autodiff_stl_et.hpp b/include/boost/math/differentiation/detail/reverse_mode_autodiff_stl_et.hpp index 70bf424590..43ebcb8fd5 100644 --- a/include/boost/math/differentiation/detail/reverse_mode_autodiff_stl_et.hpp +++ b/include/boost/math/differentiation/detail/reverse_mode_autodiff_stl_et.hpp @@ -6,8 +6,7 @@ #define REVERSE_MODE_AUTODIFF_STL_ET_HPP #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { @@ -269,7 +268,6 @@ atanh_expr atanh( } } // namespace reverse_mode } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/differentiation/detail/reverse_mode_autodiff_stl_expressions.hpp b/include/boost/math/differentiation/detail/reverse_mode_autodiff_stl_expressions.hpp index b5f9570d35..522bcbaa0c 100644 --- a/include/boost/math/differentiation/detail/reverse_mode_autodiff_stl_expressions.hpp +++ b/include/boost/math/differentiation/detail/reverse_mode_autodiff_stl_expressions.hpp @@ -15,10 +15,11 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include -namespace boost { -namespace math { +#endif +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { template @@ -83,7 +84,7 @@ struct ceil_expr : public abstract_unary_expression -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { @@ -260,7 +259,6 @@ rvar atanh(const expression +#endif -namespace boost { -namespace math { +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace reverse_mode { namespace detail { @@ -46,6 +49,5 @@ decltype(auto) if_functional_dispatch(F1&& f1, F2&& f2, Args&&... args) } // namespace detail } // namespace reverse_mode } // namespace differentiation -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // REVERSE_MODE_AUTODIFF_UTILITIES_HPP diff --git a/include/boost/math/differentiation/finite_difference.hpp b/include/boost/math/differentiation/finite_difference.hpp index 1375bac7ad..2c68643d20 100644 --- a/include/boost/math/differentiation/finite_difference.hpp +++ b/include/boost/math/differentiation/finite_difference.hpp @@ -44,10 +44,12 @@ * 1) Squire, William, and George Trapp. "Using complex variables to estimate derivatives of real functions." Siam Review 40.1 (1998): 110-112. */ +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include -namespace boost{ namespace math{ namespace differentiation { +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace detail { template @@ -61,13 +63,13 @@ namespace detail { // Handle the case x + h == x: if (h == 0) { - h = boost::math::nextafter(x, (numeric_limits::max)()) - x; + h = BOOST_MATH_NAMESPACE::nextafter(x, (numeric_limits::max)()) - x; } return h; } } -template +BOOST_MATH_EXPORT template Real complex_step_derivative(const F f, Real x) { // Is it really this easy? Yes. @@ -256,11 +258,11 @@ namespace detail { } -template +BOOST_MATH_EXPORT template inline Real finite_difference_derivative(const F f, Real x, Real* error = nullptr) { return detail::finite_difference_derivative(f, x, error, detail::fd_tag()); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/differentiation/lanczos_smoothing.hpp b/include/boost/math/differentiation/lanczos_smoothing.hpp index 4103f538d7..b84b275b9d 100644 --- a/include/boost/math/differentiation/lanczos_smoothing.hpp +++ b/include/boost/math/differentiation/lanczos_smoothing.hpp @@ -5,6 +5,7 @@ #ifndef BOOST_MATH_DIFFERENTIATION_LANCZOS_SMOOTHING_HPP #define BOOST_MATH_DIFFERENTIATION_LANCZOS_SMOOTHING_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include // for std::abs #include #include // to nan initialize @@ -13,6 +14,7 @@ #include #include #include +#endif #include #include @@ -23,7 +25,7 @@ #endif #endif -namespace boost::math::differentiation { +BOOST_MATH_NAMESPACE_BEGIN namespace differentiation { namespace detail { template @@ -48,11 +50,16 @@ class discrete_legendre { return prod; } + // Every product that meets a sum is an explicit fma. Contraction is optional, so a compiler may fuse a + // plain a*b - c in one inlined copy of a step and not in another (CSE of a shared product is enough), + // and the recurrence then disagrees with itself. The other products feed multiplies, divides or an + // fma's addend, which contraction never touches, and N*N - (r-1)^2 is exact either way. Real next() { + using std::fma; Real N = 2 * m_n + 1; Real num = (m_r - 1) * (N * N - (m_r - 1) * (m_r - 1)) * m_qrm2; - Real tmp = (2 * m_r - 1) * m_x * m_qrm1 - num / Real(4 * m_n * m_n); + Real tmp = fma((2 * m_r - 1) * m_x, m_qrm1, -(num / Real(4 * m_n * m_n))); m_qrm2 = m_qrm1; m_qrm1 = tmp / m_r; ++m_r; @@ -61,10 +68,11 @@ class discrete_legendre { Real next_prime() { + using std::fma; Real N = 2 * m_n + 1; Real s = (m_r - 1) * (N * N - (m_r - 1) * (m_r - 1)) / Real(4 * m_n * m_n); - Real tmp1 = ((2 * m_r - 1) * m_x * m_qrm1 - s * m_qrm2) / m_r; - Real tmp2 = ((2 * m_r - 1) * (m_qrm1 + m_x * m_qrm1p) - s * m_qrm2p) / m_r; + Real tmp1 = fma((2 * m_r - 1) * m_x, m_qrm1, -s * m_qrm2) / m_r; + Real tmp2 = fma(Real(2 * m_r - 1), fma(m_x, m_qrm1p, m_qrm1), -s * m_qrm2p) / m_r; m_qrm2 = m_qrm1; m_qrm1 = tmp1; m_qrm2p = m_qrm1p; @@ -75,12 +83,13 @@ class discrete_legendre { Real next_dbl_prime() { + using std::fma; Real N = 2*m_n + 1; Real trm1 = 2*m_r - 1; Real s = (m_r - 1) * (N * N - (m_r - 1) * (m_r - 1)) / Real(4 * m_n * m_n); - Real rqrpp = 2*trm1*m_qrm1p + trm1*m_x*m_qrm1pp - s*m_qrm2pp; - Real tmp1 = ((2 * m_r - 1) * m_x * m_qrm1 - s * m_qrm2) / m_r; - Real tmp2 = ((2 * m_r - 1) * (m_qrm1 + m_x * m_qrm1p) - s * m_qrm2p) / m_r; + Real rqrpp = fma(trm1 * m_x, m_qrm1pp, fma(2 * trm1, m_qrm1p, -s * m_qrm2pp)); + Real tmp1 = fma(trm1 * m_x, m_qrm1, -s * m_qrm2) / m_r; + Real tmp2 = fma(trm1, fma(m_x, m_qrm1p, m_qrm1), -s * m_qrm2p) / m_r; m_qrm2 = m_qrm1; m_qrm1 = tmp1; m_qrm2p = m_qrm1p; @@ -91,53 +100,32 @@ class discrete_legendre { return m_qrm1pp; } - Real operator()(Real x, std::size_t k) + Real operator()(Real x, std::size_t k) const { BOOST_MATH_ASSERT_MSG(k <= 2 * m_n, "r <= 2n is required."); if (k == 0) { return 1; } - if (k == 1) - { - return x; - } - Real qrm2 = 1; - Real qrm1 = x; - Real N = 2 * m_n + 1; + discrete_legendre dlp(m_n, x); + Real q = x; for (std::size_t r = 2; r <= k; ++r) { - Real num = (r - 1) * (N * N - (r - 1) * (r - 1)) * qrm2; - Real tmp = (2 * r - 1) * x * qrm1 - num / Real(4 * m_n * m_n); - qrm2 = qrm1; - qrm1 = tmp / r; + q = dlp.next(); } - return qrm1; + return q; } - Real prime(Real x, std::size_t k) { + Real prime(Real x, std::size_t k) const { BOOST_MATH_ASSERT_MSG(k <= 2 * m_n, "r <= 2n is required."); if (k == 0) { return 0; } - if (k == 1) { - return 1; - } - Real qrm2 = 1; - Real qrm1 = x; - Real qrm2p = 0; - Real qrm1p = 1; - Real N = 2 * m_n + 1; + discrete_legendre dlp(m_n, x); + Real qp = 1; for (std::size_t r = 2; r <= k; ++r) { - Real s = - (r - 1) * (N * N - (r - 1) * (r - 1)) / Real(4 * m_n * m_n); - Real tmp1 = ((2 * r - 1) * x * qrm1 - s * qrm2) / r; - Real tmp2 = ((2 * r - 1) * (qrm1 + x * qrm1p) - s * qrm2p) / r; - qrm2 = qrm1; - qrm1 = tmp1; - qrm2p = qrm1p; - qrm1p = tmp2; + qp = dlp.next_prime(); } - return qrm1p; + return qp; } private: @@ -252,7 +240,7 @@ std::vector acceleration_filter(std::size_t n, std::size_t p, int64_t s) } // namespace detail -template +BOOST_MATH_EXPORT template class discrete_lanczos_derivative { public: discrete_lanczos_derivative(Real const & spacing, @@ -587,5 +575,5 @@ class discrete_lanczos_derivative { Real m_dt; }; -} // namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/distributions.hpp b/include/boost/math/distributions.hpp index 0834db870a..4ab64adb67 100644 --- a/include/boost/math/distributions.hpp +++ b/include/boost/math/distributions.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/math/distributions/arcsine.hpp b/include/boost/math/distributions/arcsine.hpp index 4fe3c7d751..d476002fb9 100644 --- a/include/boost/math/distributions/arcsine.hpp +++ b/include/boost/math/distributions/arcsine.hpp @@ -42,10 +42,12 @@ #ifndef BOOST_MATH_HAS_NVRTC #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include // For std::domain_error. #endif +#endif #if defined (BOOST_MSVC) # pragma warning(push) @@ -53,10 +55,7 @@ // in domain_error_imp in error_handling. #endif -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace arcsine_detail { // Common error checking routines for arcsine distribution functions: @@ -64,7 +63,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_x_min(const char* function, const RealType& x, RealType* result, const Policy& pol) { - if (!(boost::math::isfinite)(x)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(x)) { *result = policies::raise_domain_error( function, @@ -77,7 +76,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_x_max(const char* function, const RealType& x, RealType* result, const Policy& pol) { - if (!(boost::math::isfinite)(x)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(x)) { *result = policies::raise_domain_error( function, @@ -109,7 +108,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_prob(const char* function, const RealType& p, RealType* result, const Policy& pol) { - if ((p < 0) || (p > 1) || !(boost::math::isfinite)(p)) + if ((p < 0) || (p > 1) || !(BOOST_MATH_NAMESPACE::isfinite)(p)) { *result = policies::raise_domain_error( function, @@ -122,7 +121,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_x(const char* function, const RealType& x_min, const RealType& x_max, const RealType& x, RealType* result, const Policy& pol) { // Check x finite and x_min < x < x_max. - if (!(boost::math::isfinite)(x)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(x)) { *result = policies::raise_domain_error( function, @@ -181,7 +180,7 @@ namespace boost BOOST_MATH_GPU_ENABLED inline RealType arcsine_pdf(const RealType x, const RealType x_min, const RealType x_max) { BOOST_MATH_STD_USING - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; return 1 / (pi() * sqrt((x - x_min) * (x_max - x))); } @@ -198,7 +197,7 @@ namespace boost { return 1; } - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; return 2 * asin(sqrt((x - x_min) / (x_max - x_min))) / pi(); } @@ -215,7 +214,7 @@ namespace boost { return 0; } - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; // Naive version x = 1 - x; // result = static_cast(2) * asin(sqrt((x - x_min) / (x_max - x_min))) / pi(); // is less accurate, so use acos instead of asin for complement. @@ -235,7 +234,7 @@ namespace boost { return 1; } - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half_pi; RealType sin2hpip = sin(half_pi() * p); RealType sin2hpip2 = sin2hpip * sin2hpip; return -x_min * sin2hpip2 + x_min + x_max * sin2hpip2; @@ -257,14 +256,14 @@ namespace boost //result = cos(half_pi() * q); // for arcsine(0,1) //result = result * result; // For generalized arcsine: - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half_pi; RealType cos2hpip = cos(half_pi() * q); RealType cos2hpip2 = cos2hpip * cos2hpip; return -x_min * cos2hpip2 + x_min + x_max * cos2hpip2; } } // namespace arcsine_detail - template > + BOOST_MATH_EXPORT template > class arcsine_distribution { public: @@ -297,30 +296,30 @@ namespace boost }; // template class arcsine_distribution // Convenient typedef to construct double version. - typedef arcsine_distribution arcsine; + BOOST_MATH_EXPORT typedef arcsine_distribution arcsine; #ifdef __cpp_deduction_guides - template - arcsine_distribution(RealType)->arcsine_distribution::type>; - template - arcsine_distribution(RealType, RealType)->arcsine_distribution::type>; + BOOST_MATH_EXPORT template + arcsine_distribution(RealType)->arcsine_distribution::type>; + BOOST_MATH_EXPORT template + arcsine_distribution(RealType, RealType)->arcsine_distribution::type>; #endif - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const arcsine_distribution& dist) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const arcsine_distribution& dist) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(dist.x_min()), static_cast(dist.x_max())); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(dist.x_min()), static_cast(dist.x_max())); } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const arcsine_distribution& dist) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const arcsine_distribution& dist) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - return boost::math::pair(static_cast(dist.x_min()), static_cast(dist.x_max())); + return BOOST_MATH_NAMESPACE::pair(static_cast(dist.x_min()), static_cast(dist.x_max())); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const arcsine_distribution& dist) { // Mean of arcsine distribution . RealType result; @@ -341,7 +340,7 @@ namespace boost return static_cast(arcsine_detail::arcsine_mean(static_cast(x_min), static_cast(x_max))); } // mean - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const arcsine_distribution& dist) { // Variance of standard arcsine distribution = (1-0)/8 = 0.125. RealType result; @@ -361,7 +360,7 @@ namespace boost return static_cast(arcsine_detail::arcsine_variance(static_cast(x_min), static_cast(x_max))); } // variance - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const arcsine_distribution& /* dist */) { //There are always [*two] values for the mode, at ['x_min] and at ['x_max], default 0 and 1, // so instead we raise the exception domain_error. @@ -372,7 +371,7 @@ namespace boost std::numeric_limits::quiet_NaN(), Policy()); } // mode - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const arcsine_distribution& dist) { // Median of arcsine distribution (a + b) / 2 == mean. RealType x_min = dist.x_min(); @@ -392,7 +391,7 @@ namespace boost return static_cast(arcsine_detail::arcsine_mean(static_cast(x_min), static_cast(x_max))); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const arcsine_distribution& dist) { RealType result; @@ -411,7 +410,7 @@ namespace boost return 0; } // skewness - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const arcsine_distribution& dist) { RealType result; @@ -430,7 +429,28 @@ namespace boost return static_cast(-1.5f); } // kurtosis_excess - template + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline RealType entropy(const arcsine_distribution& dist) + { + BOOST_MATH_STD_USING + RealType result; + RealType x_min = dist.x_min(); + RealType x_max = dist.x_max(); + + if (!arcsine_detail::check_dist( + "boost::math::entropy(arcsine_distribution<%1%> const&, %1% )", + x_min, + x_max, + &result, Policy()) + ) + { + return result; + } + // A beta(1/2, 1/2) distribution scaled to [x_min, x_max]: log(pi (x_max - x_min) / 4). + return log(x_max - x_min) + log(constants::pi() / 4); + } // entropy + + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const arcsine_distribution& dist) { RealType result; @@ -449,7 +469,7 @@ namespace boost return static_cast(1.5f); } // kurtosis - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const arcsine_distribution& dist, const RealType& xx) { // Probability Density/Mass Function arcsine. BOOST_FPU_EXCEPTION_GUARD @@ -475,7 +495,7 @@ namespace boost static_cast(x_max))); } // pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const arcsine_distribution& dist, const RealType& x) { // Cumulative Distribution Function arcsine. RealType x_min = dist.x_min(); @@ -498,7 +518,7 @@ namespace boost static_cast(x_max))); } // arcsine cdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function arcsine. RealType x = c.param; @@ -523,7 +543,7 @@ namespace boost static_cast(x_max))); } // arcsine ccdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const arcsine_distribution& dist, const RealType& p) { // Quantile or Percent Point arcsine function or @@ -552,7 +572,7 @@ namespace boost static_cast(x_max))); } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { // Complement Quantile or Percent Point arcsine function. @@ -578,8 +598,7 @@ namespace boost static_cast(x_min), static_cast(x_max))); } // Quantile Complement - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/bernoulli.hpp b/include/boost/math/distributions/bernoulli.hpp index bfb5bf6180..700a6874fe 100644 --- a/include/boost/math/distributions/bernoulli.hpp +++ b/include/boost/math/distributions/bernoulli.hpp @@ -35,25 +35,25 @@ #include // complements #include // error checks #include // isnan. +#include #include #include #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #endif -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace bernoulli_detail { // Common error checking routines for bernoulli distribution functions: template BOOST_MATH_GPU_ENABLED inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& /* pol */) { - if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(p) || (p < 0) || (p > 1)) { *result = policies::raise_domain_error( function, @@ -63,12 +63,12 @@ namespace boost return true; } template - BOOST_MATH_GPU_ENABLED inline bool check_dist(const char* function, const RealType& p, RealType* result, const Policy& /* pol */, const boost::math::true_type&) + BOOST_MATH_GPU_ENABLED inline bool check_dist(const char* function, const RealType& p, RealType* result, const Policy& /* pol */, const BOOST_MATH_NAMESPACE::true_type&) { return check_success_fraction(function, p, result, Policy()); } template - BOOST_MATH_GPU_ENABLED inline bool check_dist(const char* , const RealType& , RealType* , const Policy& /* pol */, const boost::math::false_type&) + BOOST_MATH_GPU_ENABLED inline bool check_dist(const char* , const RealType& , RealType* , const Policy& /* pol */, const BOOST_MATH_NAMESPACE::false_type&) { return true; } @@ -85,7 +85,7 @@ namespace boost { return false; } - if(!(boost::math::isfinite)(k) || !((k == 0) || (k == 1))) + if(!(BOOST_MATH_NAMESPACE::isfinite)(k) || !((k == 0) || (k == 1))) { *result = policies::raise_domain_error( function, @@ -106,7 +106,7 @@ namespace boost } // namespace bernoulli_detail - template > + BOOST_MATH_EXPORT template > class bernoulli_distribution { public: @@ -132,28 +132,28 @@ namespace boost RealType m_p; // success_fraction }; // template class bernoulli_distribution - typedef bernoulli_distribution bernoulli; + BOOST_MATH_EXPORT typedef bernoulli_distribution bernoulli; #ifdef __cpp_deduction_guides - template - bernoulli_distribution(RealType)->bernoulli_distribution::type>; + BOOST_MATH_EXPORT template + bernoulli_distribution(RealType)->bernoulli_distribution::type>; #endif - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const bernoulli_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const bernoulli_distribution& /* dist */) { // Range of permissible values for random variable k = {0, 1}. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), static_cast(1)); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), static_cast(1)); } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const bernoulli_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const bernoulli_distribution& /* dist */) { // Range of supported values for random variable k = {0, 1}. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - return boost::math::pair(static_cast(0), static_cast(1)); + return BOOST_MATH_NAMESPACE::pair(static_cast(0), static_cast(1)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const bernoulli_distribution& dist) { // Mean of bernoulli distribution = p (n = 1). return dist.success_fraction(); @@ -166,13 +166,13 @@ namespace boost // return tools::domain_error(BOOST_CURRENT_FUNCTION, "Median is not implemented, result is %1%!", std::numeric_limits::quiet_NaN()); //} // median - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const bernoulli_distribution& dist) { // Variance of bernoulli distribution =p * q. return dist.success_fraction() * (1 - dist.success_fraction()); } // variance - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType pdf(const bernoulli_distribution& dist, const RealType& k) { // Probability Density/Mass Function. BOOST_FPU_EXCEPTION_GUARD @@ -197,7 +197,7 @@ namespace boost } } // pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const bernoulli_distribution& dist, const RealType& k) { // Cumulative Distribution Function Bernoulli. RealType p = dist.success_fraction(); @@ -221,7 +221,7 @@ namespace boost } } // bernoulli cdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function bernoulli. RealType const& k = c.param; @@ -247,7 +247,7 @@ namespace boost } } // bernoulli cdf complement - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const bernoulli_distribution& dist, const RealType& p) { // Quantile or Percent Point Bernoulli function. // Return the number of expected successes k either 0 or 1. @@ -262,8 +262,8 @@ namespace boost { return result; } - if (p <= (1 - dist.success_fraction())) - { // p <= pdf(dist, 0) == cdf(dist, 0) + if (p <= cdf(dist, RealType(0))) + { // The smallest k with cdf(k) >= p. return 0; } else @@ -272,7 +272,7 @@ namespace boost } } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { // Quantile or Percent Point bernoulli function. // Return the number of expected successes k for a given @@ -291,23 +291,24 @@ namespace boost return result; } - if (q <= 1 - dist.success_fraction()) - { // // q <= cdf(complement(dist, 0)) == pdf(dist, 0) - return 1; + // The smallest k with cdf(complement(dist, k)) <= q: + if (q >= cdf(complement(dist, RealType(0)))) + { + return 0; } else { - return 0; + return 1; } } // quantile complemented. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const bernoulli_distribution& dist) { return static_cast((dist.success_fraction() <= 0.5) ? 0 : 1); // p = 0.5 can be 0 or 1 } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const bernoulli_distribution& dist) { BOOST_MATH_STD_USING; // Aid ADL for sqrt. @@ -315,7 +316,7 @@ namespace boost return (1 - 2 * p) / sqrt(p * (1 - p)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const bernoulli_distribution& dist) { RealType p = dist.success_fraction(); @@ -326,7 +327,7 @@ namespace boost return 1 / (1 - p) + 1/p -6; } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const bernoulli_distribution& dist) { RealType p = dist.success_fraction(); @@ -335,8 +336,18 @@ namespace boost // return (6 * p * p - 6 * p + 1) / (p * (1 - p)) + 3; } - } // namespace math -} // namespace boost + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline RealType entropy(const bernoulli_distribution& dist) + { + BOOST_MATH_STD_USING + // -p log(p) - (1 - p) log(1 - p), with 0 log(0) = 0: + RealType p = dist.success_fraction(); + if ((p == 0) || (p == 1)) + return 0; + return -p * log(p) - (1 - p) * BOOST_MATH_NAMESPACE::log1p(-p, Policy()); + } + + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/beta.hpp b/include/boost/math/distributions/beta.hpp index fef991a870..948f11e50f 100644 --- a/include/boost/math/distributions/beta.hpp +++ b/include/boost/math/distributions/beta.hpp @@ -29,6 +29,11 @@ #include #include #include // for beta. +#include // for entropy. +#include +#include // for entropy. +#include +#include #include // complements. #include // error checks #include // isnan. @@ -41,17 +46,14 @@ // in domain_error_imp in error_handling #endif -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace beta_detail { // Common error checking routines for beta distribution functions: template BOOST_MATH_GPU_ENABLED inline bool check_alpha(const char* function, const RealType& alpha, RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(alpha) || (alpha <= 0)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(alpha) || (alpha <= 0)) { *result = policies::raise_domain_error( function, @@ -64,7 +66,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_beta(const char* function, const RealType& beta, RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(beta) || (beta <= 0)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(beta) || (beta <= 0)) { *result = policies::raise_domain_error( function, @@ -77,7 +79,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_prob(const char* function, const RealType& p, RealType* result, const Policy& pol) { - if((p < 0) || (p > 1) || !(boost::math::isfinite)(p)) + if((p < 0) || (p > 1) || !(BOOST_MATH_NAMESPACE::isfinite)(p)) { *result = policies::raise_domain_error( function, @@ -90,7 +92,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_x(const char* function, const RealType& x, RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(x) || (x < 0) || (x > 1)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(x) || (x < 0) || (x > 1)) { *result = policies::raise_domain_error( function, @@ -124,7 +126,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_mean(const char* function, const RealType& mean, RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(mean) || (mean <= 0)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(mean) || (mean <= 0)) { *result = policies::raise_domain_error( function, @@ -136,7 +138,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_variance(const char* function, const RealType& variance, RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(variance) || (variance <= 0)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(variance) || (variance <= 0)) { *result = policies::raise_domain_error( function, @@ -145,13 +147,58 @@ namespace boost } return true; } // bool check_variance + + // Entropy for a and b near 1, where H vanishes to second order and the usual form cancels to + // first order. Here H = g(a) + g(b) + k(a + b), with g(x) = lgamma(x) - (x - 1) digamma(x) and + // k(s) = (s - 2) digamma(s) - lgamma(s), which have zero value and slope at x = 1 and s = 2. + // Integrating their derivatives, -(x - 1) trigamma(x) and (s - 2) trigamma(s), term by term + // with the series for trigamma(1 + t) and trigamma(2 + t) gives, for |t| < 1, + // g(1 + t) = -sum_{n >= 0} (-1)^n (n + 1)/(n + 2) zeta(n + 2) t^(n + 2), + // k(2 + t) = sum_{n >= 0} (-1)^n (n + 1)/(n + 2) (zeta(n + 2) - 1) t^(n + 2). + // zeta(n + 2) - 1 is only accurate to absolute eps, so k uses its series for |t| <= 1/2 only; + // further out it has no cancellation to speak of. + template + inline RealType entropy_zeta_series(RealType t, bool minus_one, const Policy& pol) + { + BOOST_MATH_STD_USING + const RealType eps = policies::get_epsilon(); + RealType t_power = t * t; + RealType sum = 0; + for (int n = 0; n < 500; ++n) + { + RealType z = zeta(RealType(n + 2), pol); + RealType term = RealType(n + 1) / (n + 2) * (minus_one ? z - 1 : z) * t_power; + sum += (n & 1) ? -term : term; + if (fabs(term) <= eps * fabs(sum)) + break; + t_power *= t; + } + return sum; + } + + template + inline RealType entropy_near_uniform(RealType a, RealType b, const Policy& pol) + { + BOOST_MATH_STD_USING + RealType s = a + b; + RealType k = (fabs(s - 2) <= RealType(0.5)) + ? entropy_zeta_series(RealType(s - 2), true, pol) + : (s - 2) * digamma(s, pol) - lgamma(s, pol); + auto g = [&pol](RealType x) + { + return (fabs(x - 1) <= RealType(0.5)) + ? RealType(-entropy_zeta_series(RealType(x - 1), false, pol)) + : RealType(lgamma(x, pol) - (x - 1) * digamma(x, pol)); + }; + return k + g(a) + g(b); + } } // namespace beta_detail // typedef beta_distribution beta; // is deliberately NOT included to avoid a name clash with the beta function. // Use beta_distribution<> mybeta(...) to construct type double. - template > + BOOST_MATH_EXPORT template > class beta_distribution { public: @@ -275,33 +322,33 @@ namespace boost }; // template class beta_distribution #ifdef __cpp_deduction_guides - template - beta_distribution(RealType)->beta_distribution::type>; - template - beta_distribution(RealType, RealType)->beta_distribution::type>; + BOOST_MATH_EXPORT template + beta_distribution(RealType)->beta_distribution::type>; + BOOST_MATH_EXPORT template + beta_distribution(RealType, RealType)->beta_distribution::type>; #endif - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const beta_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const beta_distribution& /* dist */) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), static_cast(1)); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), static_cast(1)); } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const beta_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const beta_distribution& /* dist */) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - return boost::math::pair(static_cast(0), static_cast(1)); + return BOOST_MATH_NAMESPACE::pair(static_cast(0), static_cast(1)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const beta_distribution& dist) { // Mean of beta distribution = np. return dist.alpha() / (dist.alpha() + dist.beta()); } // mean - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const beta_distribution& dist) { // Variance of beta distribution = np(1-p). RealType a = dist.alpha(); @@ -309,7 +356,7 @@ namespace boost return (a * b) / ((a + b ) * (a + b) * (a + b + 1)); } // variance - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const beta_distribution& dist) { constexpr auto function = "boost::math::mode(beta_distribution<%1%> const&)"; @@ -343,7 +390,7 @@ namespace boost //But WILL be provided by the derived accessor as quantile(0.5). - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const beta_distribution& dist) { BOOST_MATH_STD_USING // ADL of std functions. @@ -352,7 +399,7 @@ namespace boost return (2 * (b-a) * sqrt(a + b + 1)) / ((a + b + 2) * sqrt(a * b)); } // skewness - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const beta_distribution& dist) { RealType a = dist.alpha(); @@ -363,13 +410,52 @@ namespace boost return n / d; } // kurtosis_excess - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const beta_distribution& dist) { return 3 + kurtosis_excess(dist); } // kurtosis - template + // Not GPU enabled: the series use Bernoulli numbers and zeta. + BOOST_MATH_EXPORT template + inline RealType entropy(const beta_distribution& dist) + { + BOOST_MATH_STD_USING + // H = log(B(a, b)) - (a - 1) digamma(a) - (b - 1) digamma(b) + (a + b - 2) digamma(a + b). + // For large a or b those terms are ~a log(a) while H ~ log(a), so with s = a + b, the + // Stirling forms of lgamma and digamma cancel the large parts exactly: + // H = log(2 pi e ab / s^3) / 2 - 1/(2a) - 1/(2b) + 1/s + r(a) + r(b) - r(s) + nu(s), + // where nu and r are the remainders computed by entropy_stirling_series. A small parameter + // b keeps its lgamma and digamma: log(2 pi e b)/2 - 1/(2b) + r(b) = lgamma(b) + b - (b - 1) digamma(b). + RealType a = dist.alpha(); + RealType b = dist.beta(); + const RealType threshold = detail::entropy_series_threshold(); + if ((a < threshold) && (b < threshold)) + { + return beta_detail::entropy_near_uniform(a, b, Policy()); + } + if (a < b) + { + BOOST_MATH_GPU_SAFE_SWAP(a, b); + } + RealType s = a + b; + RealType r_a, nu_a, r_s, nu_s; + detail::entropy_stirling_series(a, r_a, nu_a, Policy()); + detail::entropy_stirling_series(s, r_s, nu_s, Policy()); + // The terms that depend on a and s only; log(a/s) = -log1p(b/a): + RealType result = -BOOST_MATH_NAMESPACE::log1p(b / a, Policy()) / 2 - log(s) - 1 / (2 * a) + 1 / s + r_a - r_s + nu_s; + if (b < threshold) + { + return result + lgamma(b, Policy()) + b - (b - 1) * digamma(b, Policy()); + } + RealType r_b, nu_b; + detail::entropy_stirling_series(b, r_b, nu_b, Policy()); + // log(b/s) / 2 + log(s) / 2 + the b terms, given result's -log(s): + return result + constants::log_root_two_pi() + constants::half() + - BOOST_MATH_NAMESPACE::log1p(a / b, Policy()) / 2 + log(s) / 2 - 1 / (2 * b) + r_b; + } // entropy + + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const beta_distribution& dist, const RealType& x) { // Probability Density/Mass Function. BOOST_FPU_EXCEPTION_GUARD @@ -390,7 +476,7 @@ namespace boost { return result; } - using boost::math::beta; + using BOOST_MATH_NAMESPACE::beta; // Corner cases: check_x ensures x element of [0, 1], but PDF is 0 for x = 0 and x = 1. PDF EQN: // https://wikimedia.org/api/rest_v1/media/math/render/svg/125fdaa41844a8703d1a8610ac00fbf3edacc8e7 @@ -428,7 +514,7 @@ namespace boost return static_cast(ibeta_derivative(a, b, x, Policy())); } // pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const beta_distribution& dist, const RealType& x) { // Cumulative Distribution Function beta. BOOST_MATH_STD_USING // for ADL of std functions @@ -459,7 +545,7 @@ namespace boost return static_cast(ibeta(a, b, x, Policy())); } // beta cdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function beta. @@ -495,7 +581,54 @@ namespace boost return static_cast(ibetac(a, b, x, Policy())); } // beta cdf - template + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline RealType logcdf(const beta_distribution& dist, const RealType& x) + { + BOOST_MATH_STD_USING + constexpr auto function = "boost::math::logcdf(beta_distribution<%1%> const&, %1%)"; + RealType a = dist.alpha(); + RealType b = dist.beta(); + RealType result = 0; + if(false == beta_detail::check_dist_and_x(function, a, b, x, &result, Policy())) + { + return result; + } + if (x == 0) + { + return log(RealType(0)); + } + else if (x == 1) + { + return 0; + } + return static_cast(libeta(a, b, x, Policy())); + } + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) + { + BOOST_MATH_STD_USING + constexpr auto function = "boost::math::logcdf(beta_distribution<%1%> const&, %1%)"; + RealType const& x = c.param; + RealType a = c.dist.alpha(); + RealType b = c.dist.beta(); + RealType result = 0; + if(false == beta_detail::check_dist_and_x(function, a, b, x, &result, Policy())) + { + return result; + } + if (x == 0) + { + return 0; + } + else if (x == 1) + { + return log(RealType(0)); + } + return static_cast(libetac(a, b, x, Policy())); + } + + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const beta_distribution& dist, const RealType& p) { // Quantile or Percent Point beta function or // Inverse Cumulative probability distribution function CDF. @@ -530,7 +663,7 @@ namespace boost return static_cast(ibeta_inv(a, b, p, static_cast(nullptr), Policy())); } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { // Complement Quantile or Percent Point beta function . // Return the number of expected x for a given @@ -567,8 +700,7 @@ namespace boost return static_cast(ibetac_inv(a, b, q, static_cast(nullptr), Policy())); } // Quantile Complement - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/binomial.hpp b/include/boost/math/distributions/binomial.hpp index 262823170f..92e24b96bf 100644 --- a/include/boost/math/distributions/binomial.hpp +++ b/include/boost/math/distributions/binomial.hpp @@ -89,14 +89,17 @@ #include // isnan. #include // for root finding. +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost -{ - namespace math - { +#ifndef BOOST_MATH_HAS_NVRTC +#include +#endif - template +BOOST_MATH_NAMESPACE_BEGIN + + BOOST_MATH_EXPORT template class binomial_distribution; namespace binomial_detail{ @@ -104,7 +107,7 @@ namespace boost template BOOST_MATH_CUDA_ENABLED inline bool check_N(const char* function, const RealType& N, RealType* result, const Policy& pol) { - if((N < 0) || !(boost::math::isfinite)(N)) + if((N < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(N)) { *result = policies::raise_domain_error( function, @@ -116,7 +119,7 @@ namespace boost template BOOST_MATH_CUDA_ENABLED inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& pol) { - if((p < 0) || (p > 1) || !(boost::math::isfinite)(p)) + if((p < 0) || (p > 1) || !(BOOST_MATH_NAMESPACE::isfinite)(p)) { *result = policies::raise_domain_error( function, @@ -138,7 +141,7 @@ namespace boost { if(check_dist(function, N, p, result, pol) == false) return false; - if((k < 0) || !(boost::math::isfinite)(k)) + if((k < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(k)) { *result = policies::raise_domain_error( function, @@ -175,7 +178,7 @@ namespace boost // kurtosis: // T k = (1 - 6 * sf * (1 - sf) ) / (n * sf * (1 - sf)); // Get the inverse of a std normal distribution: - T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two(); + T x = BOOST_MATH_NAMESPACE::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two(); // Set the sign: if(p < 0.5) x = -x; @@ -231,8 +234,8 @@ namespace boost // so n is the most sensible answer here: return trials; } - if (p <= pow(1 - success_fraction, trials)) - { // p <= pdf(dist, 0) == cdf(dist, 0) + if (comp ? (q >= cdf(complement(dist, RealType(0)))) : (p <= cdf(dist, RealType(0)))) + { // Compare with the cdf itself, not pow(1 - p, n), so quantile(cdf(0)) round-trips. return 0; // So the only reasonable result is zero. } // And root finder would fail otherwise. @@ -274,7 +277,7 @@ namespace boost } - template > + BOOST_MATH_EXPORT template > class binomial_distribution { public: @@ -408,45 +411,45 @@ namespace boost RealType m_p; // success_fraction }; // template class binomial_distribution - typedef binomial_distribution<> binomial; + BOOST_MATH_EXPORT typedef binomial_distribution<> binomial; // typedef binomial_distribution binomial; // IS now included since no longer a name clash with function binomial. //typedef binomial_distribution binomial; // Reserved name of type double. #ifdef __cpp_deduction_guides - template - binomial_distribution(RealType)->binomial_distribution::type>; - template - binomial_distribution(RealType,RealType)->binomial_distribution::type>; + BOOST_MATH_EXPORT template + binomial_distribution(RealType)->binomial_distribution::type>; + BOOST_MATH_EXPORT template + binomial_distribution(RealType,RealType)->binomial_distribution::type>; #endif - template - BOOST_MATH_CUDA_ENABLED const boost::math::pair range(const binomial_distribution& dist) + BOOST_MATH_EXPORT template + BOOST_MATH_CUDA_ENABLED const BOOST_MATH_NAMESPACE::pair range(const binomial_distribution& dist) { // Range of permissible values for random variable k. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), dist.trials()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), dist.trials()); } - template - BOOST_MATH_CUDA_ENABLED const boost::math::pair support(const binomial_distribution& dist) + BOOST_MATH_EXPORT template + BOOST_MATH_CUDA_ENABLED const BOOST_MATH_NAMESPACE::pair support(const binomial_distribution& dist) { // Range of supported values for random variable k. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - return boost::math::pair(static_cast(0), dist.trials()); + return BOOST_MATH_NAMESPACE::pair(static_cast(0), dist.trials()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType mean(const binomial_distribution& dist) { // Mean of Binomial distribution = np. return dist.trials() * dist.success_fraction(); } // mean - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType variance(const binomial_distribution& dist) { // Variance of Binomial distribution = np(1-p). return dist.trials() * dist.success_fraction() * (1 - dist.success_fraction()); } // variance - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED RealType pdf(const binomial_distribution& dist, const RealType& k) { // Probability Density/Mass Function. BOOST_FPU_EXCEPTION_GUARD @@ -497,12 +500,12 @@ namespace boost // = p^k (1-p)^(n-k) / (beta(k+1, n-k+1) * (n+1)) // = ibeta_derivative(k+1, n-k+1, p) / (n+1) // - using boost::math::ibeta_derivative; // a, b, x + using BOOST_MATH_NAMESPACE::ibeta_derivative; // a, b, x return ibeta_derivative(k+1, n-k+1, dist.success_fraction(), Policy()) / (n+1); } // pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType cdf(const binomial_distribution& dist, const RealType& k) { // Cumulative Distribution Function Binomial. // The random variate k is the number of successes in n trials. @@ -574,7 +577,7 @@ namespace boost return ibetac(k + 1, n - k, p, Policy()); } // binomial cdf - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function Binomial. // The random variate k is the number of successes in n trials. @@ -651,19 +654,66 @@ namespace boost return ibeta(k + 1, n - k, p, Policy()); } // binomial cdf - template + BOOST_MATH_EXPORT template + BOOST_MATH_CUDA_ENABLED inline RealType logcdf(const binomial_distribution& dist, const RealType& k) + { + BOOST_MATH_STD_USING + RealType n = dist.trials(); + RealType p = dist.success_fraction(); + RealType result = 0; + if(false == binomial_detail::check_dist_and_k( + "boost::math::logcdf(binomial_distribution<%1%> const&, %1%)", n, p, k, &result, Policy())) + { + return result; + } + if ((k == n) || (p == 0)) + { + return 0; + } + if (p == 1) + { + return log(RealType(0)); + } + return libetac(k + 1, n - k, p, Policy()); + } + + BOOST_MATH_EXPORT template + BOOST_MATH_CUDA_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) + { + BOOST_MATH_STD_USING + RealType const& k = c.param; + RealType n = c.dist.trials(); + RealType p = c.dist.success_fraction(); + RealType result = 0; + if(false == binomial_detail::check_dist_and_k( + "boost::math::logcdf(binomial_distribution<%1%> const&, %1%)", n, p, k, &result, Policy())) + { + return result; + } + if ((k == n) || (p == 0)) + { + return log(RealType(0)); + } + if (p == 1) + { + return 0; + } + return libeta(k + 1, n - k, p, Policy()); + } + + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType quantile(const binomial_distribution& dist, const RealType& p) { return binomial_detail::quantile_imp(dist, p, RealType(1-p), false); } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED RealType quantile(const complemented2_type, RealType>& c) { return binomial_detail::quantile_imp(c.dist, RealType(1-c.param), c.param, true); } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType mode(const binomial_distribution& dist) { BOOST_MATH_STD_USING // ADL of std functions. @@ -672,7 +722,7 @@ namespace boost return floor(p * (n + 1)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType median(const binomial_distribution& dist) { // Bounds for the median of the negative binomial distribution // VAN DE VEN R. ; WEBER N. C. ; @@ -690,7 +740,7 @@ namespace boost return floor(p * n); // Chose the middle value. } - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType skewness(const binomial_distribution& dist) { BOOST_MATH_STD_USING // ADL of std functions. @@ -699,7 +749,7 @@ namespace boost return (1 - 2 * p) / sqrt(n * p * (1 - p)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType kurtosis(const binomial_distribution& dist) { RealType p = dist.success_fraction(); @@ -707,7 +757,7 @@ namespace boost return 3 - 6 / n + 1 / (n * p * (1 - p)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline RealType kurtosis_excess(const binomial_distribution& dist) { RealType p = dist.success_fraction(); @@ -716,8 +766,91 @@ namespace boost return (1 - 6 * p * q) / (n * p * q); } - } // namespace math - } // namespace boost +#ifndef BOOST_MATH_HAS_NVRTC + // Not GPU enabled: the large-variance path uses Bernoulli numbers. + BOOST_MATH_EXPORT template + inline RealType entropy(const binomial_distribution& dist) + { + BOOST_MATH_STD_USING + // No closed form: -sum p log(p) from the log ratios of the probabilities (detail::discrete_entropy_sum). + constexpr auto function = "boost::math::entropy(const binomial_distribution<%1%>&)"; + RealType n = dist.trials(); + RealType p = dist.success_fraction(); + RealType result = 0; + if (!binomial_detail::check_dist(function, n, p, &result, Policy())) + return result; + if (floor(n) != n) + return policies::raise_domain_error(function, "The number of trials must be an integer for the entropy, but got %1%.", n, Policy()); + if ((p == 0) || (p == 1) || (n == 0)) + return 0; + RealType q = 1 - p; + RealType mode = (std::min)(RealType(floor((n + 1) * p)), n); + const RealType sigmas = detail::discrete_entropy_tail_sigmas(); + const RealType threshold = detail::entropy_series_threshold(); + RealType sigma = sqrt(n * p * q); + RealType z1 = mode + 1; + RealType z2 = n + 1 - mode; + RealType margin = sigmas * sigma + threshold + 2; + if ((sigma >= 2 * sigmas) && (z1 >= margin) && (z2 >= margin)) + { + // Trapezoidal rule on the continuation S(t) = t alpha - [lgamma(z1 + t) - lgamma(z1) - t log(z1)] + // - [lgamma(z2 - t) - lgamma(z2) + t log(z2)], alpha = log(z2 p / (z1 q)), with z2 p - z1 q = (n + 2) p - z1: + RealType alpha = BOOST_MATH_NAMESPACE::log1p(RealType(fma(n + 2, p, -z1) / (z1 * q)), Policy()); + RealType h = sigma / detail::discrete_entropy_step_ratio(); + auto s_of = [&](RealType t) { return t * alpha - detail::entropy_lgamma_delta(z1, t, Policy()) - detail::entropy_lgamma_delta(z2, RealType(-t), Policy()); }; + int j_right = 0; + int j_left = 0; + auto right = [&](RealType& s, RealType&) + { + RealType t = (++j_right) * h; + if (z2 - t < threshold) + return false; + s = s_of(t); + return true; + }; + auto left = [&](RealType& s, RealType&) + { + RealType t = -(++j_left) * h; + if (z1 + t < threshold) + return false; + s = s_of(t); + return true; + }; + return detail::discrete_entropy_sum(right, left, h, RealType(0), function, Policy()); + } + // Direct sum from the mode, with p(k + 1) / p(k) = (n - k) p / ((k + 1) q), whose numerator minus + // denominator is (n + 1) p - (k + 1): + RealType k_right = mode; + RealType k_left = mode; + detail::compensated_sum s_right; + detail::compensated_sum s_left; + auto log_ratio = [&](RealType k, RealType& ratio, bool left) + { + return detail::entropy_log_ratio(RealType((n - k) * p), RealType((k + 1) * q), RealType(fma(n + 1, p, -(k + 1))), ratio, left, Policy()); + }; + auto right = [&](RealType& s, RealType& ratio) + { + if (k_right == n) + return false; + s_right.add(log_ratio(k_right, ratio, false)); + k_right += 1; + s = s_right.value(); + return true; + }; + auto left = [&](RealType& s, RealType& ratio) + { + if (k_left == 0) + return false; + k_left -= 1; + s_left.add(-log_ratio(k_left, ratio, true)); + s = s_left.value(); + return true; + }; + return detail::discrete_entropy_sum(right, left, RealType(1), RealType(0), function, Policy()); + } +#endif + + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/cauchy.hpp b/include/boost/math/distributions/cauchy.hpp index 5a19f499a3..4da00b8698 100644 --- a/include/boost/math/distributions/cauchy.hpp +++ b/include/boost/math/distributions/cauchy.hpp @@ -27,14 +27,15 @@ #ifndef BOOST_MATH_HAS_NVRTC #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #endif +#endif -namespace boost{ namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template class cauchy_distribution; namespace detail @@ -75,11 +76,11 @@ BOOST_MATH_GPU_ENABLED RealType cdf_imp(const cauchy_distribution((complement) ? 1 : 0); } #else - if(boost::math::numeric_limits::has_infinity && x == boost::math::numeric_limits::infinity()) + if(BOOST_MATH_NAMESPACE::numeric_limits::has_infinity && x == BOOST_MATH_NAMESPACE::numeric_limits::infinity()) { // cdf +infinity is unity. return static_cast((complement) ? 0 : 1); } - if(boost::math::numeric_limits::has_infinity && x == -boost::math::numeric_limits::infinity()) + if(BOOST_MATH_NAMESPACE::numeric_limits::has_infinity && x == -BOOST_MATH_NAMESPACE::numeric_limits::infinity()) { // cdf -infinity is zero. return static_cast((complement) ? 1 : 0); } @@ -147,7 +148,7 @@ BOOST_MATH_GPU_ENABLED RealType quantile_imp( } // namespace detail -template > +BOOST_MATH_EXPORT template > class cauchy_distribution { public: @@ -177,45 +178,45 @@ class cauchy_distribution RealType m_hg; // The scale )or shape), this is the half width at half height. }; -typedef cauchy_distribution cauchy; +BOOST_MATH_EXPORT typedef cauchy_distribution cauchy; #ifdef __cpp_deduction_guides -template -cauchy_distribution(RealType)->cauchy_distribution::type>; -template -cauchy_distribution(RealType,RealType)->cauchy_distribution::type>; +BOOST_MATH_EXPORT template +cauchy_distribution(RealType)->cauchy_distribution::type>; +BOOST_MATH_EXPORT template +cauchy_distribution(RealType,RealType)->cauchy_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const cauchy_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const cauchy_distribution&) { // Range of permissible values for random variable x. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + max. } } -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const cauchy_distribution& ) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const cauchy_distribution& ) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-tools::max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-tools::max_value(), max_value()); // - to + max. } } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const cauchy_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -232,7 +233,7 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const cauchy_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const cauchy_distribution& dist, const RealType& x) { return detail::cdf_imp(dist, x, false); } // cdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const cauchy_distribution& dist, const RealType& p) { return detail::quantile_imp(dist, p, false); } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { return detail::cdf_imp(c.dist, c.param, true); } // cdf complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { return detail::quantile_imp(c.dist, c.param, true); } // quantile complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const cauchy_distribution&) { // There is no mean: typedef typename Policy::assert_undefined_type assert_type; @@ -286,10 +287,10 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const cauchy_distribution&)", "The Cauchy distribution does not have a mean: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const cauchy_distribution& /*dist*/) { // There is no variance: @@ -300,22 +301,22 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const cauchy_distribution&)", "The Cauchy distribution does not have a variance: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const cauchy_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const cauchy_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const cauchy_distribution& /*dist*/) { // There is no skewness: @@ -326,10 +327,10 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const cauchy_distribution&)", "The Cauchy distribution does not have a skewness: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); // infinity? + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); // infinity? } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const cauchy_distribution& /*dist*/) { // There is no kurtosis: @@ -340,10 +341,10 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const cauchy_distribution&)", "The Cauchy distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const cauchy_distribution& /*dist*/) { // There is no kurtosis excess: @@ -354,18 +355,17 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const cauchy_distribution "boost::math::kurtosis_excess(cauchy<%1%>&)", "The Cauchy distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const cauchy_distribution & dist) { using std::log; return log(2*constants::two_pi()*dist.scale()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/distributions/chi_squared.hpp b/include/boost/math/distributions/chi_squared.hpp index 9823a2d555..b025a49437 100644 --- a/include/boost/math/distributions/chi_squared.hpp +++ b/include/boost/math/distributions/chi_squared.hpp @@ -20,9 +20,13 @@ #include // error checks #include -namespace boost{ namespace math{ +#ifndef BOOST_MATH_HAS_NVRTC +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN -template > +BOOST_MATH_EXPORT template > class chi_squared_distribution { public: @@ -56,11 +60,11 @@ class chi_squared_distribution RealType m_df; // degrees of freedom is a positive real number. }; // class chi_squared_distribution -using chi_squared = chi_squared_distribution; +BOOST_MATH_EXPORT using chi_squared = chi_squared_distribution; #ifdef __cpp_deduction_guides -template -chi_squared_distribution(RealType)->chi_squared_distribution::type>; +BOOST_MATH_EXPORT template +chi_squared_distribution(RealType)->chi_squared_distribution::type>; #endif #ifdef _MSC_VER @@ -68,17 +72,17 @@ chi_squared_distribution(RealType)->chi_squared_distribution -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const chi_squared_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const chi_squared_distribution& /*dist*/) { // Range of permissible values for random variable x. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(static_cast(0), boost::math::numeric_limits::infinity()); // 0 to + infinity. + return BOOST_MATH_NAMESPACE::pair(static_cast(0), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // 0 to + infinity. } else { - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // 0 to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // 0 to + max. } } @@ -86,14 +90,14 @@ BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const #pragma warning(pop) #endif -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const chi_squared_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const chi_squared_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - return boost::math::pair(static_cast(0), tools::max_value()); // 0 to + infinity. + return BOOST_MATH_NAMESPACE::pair(static_cast(0), tools::max_value()); // 0 to + infinity. } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType pdf(const chi_squared_distribution& dist, const RealType& chi_square) { BOOST_MATH_STD_USING // for ADL of std functions @@ -107,7 +111,7 @@ BOOST_MATH_GPU_ENABLED RealType pdf(const chi_squared_distribution( function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy()); @@ -134,7 +138,7 @@ BOOST_MATH_GPU_ENABLED RealType pdf(const chi_squared_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const chi_squared_distribution& dist, const RealType& chi_square) { RealType degrees_of_freedom = dist.degrees_of_freedom(); @@ -146,16 +150,16 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const chi_squared_distribution( function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy()); } - return boost::math::gamma_p(degrees_of_freedom / 2, chi_square / 2, Policy()); + return BOOST_MATH_NAMESPACE::gamma_p(degrees_of_freedom / 2, chi_square / 2, Policy()); } // cdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const chi_squared_distribution& dist, const RealType& p) { RealType degrees_of_freedom = dist.degrees_of_freedom(); @@ -169,10 +173,10 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const chi_squared_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { RealType const& degrees_of_freedom = c.dist.degrees_of_freedom(); @@ -184,16 +188,49 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type( function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy()); } - return boost::math::gamma_q(degrees_of_freedom / 2, chi_square / 2, Policy()); + return BOOST_MATH_NAMESPACE::gamma_q(degrees_of_freedom / 2, chi_square / 2, Policy()); } -template +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const chi_squared_distribution& dist, const RealType& chi_square) +{ + RealType degrees_of_freedom = dist.degrees_of_freedom(); + RealType error_result; + constexpr auto function = "boost::math::logcdf(const chi_squared_distribution<%1%>&, %1%)"; + if(!detail::check_df(function, degrees_of_freedom, &error_result, Policy())) + return error_result; + if((chi_square < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(chi_square)) + { + return policies::raise_domain_error( + function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy()); + } + return BOOST_MATH_NAMESPACE::lgamma_p(degrees_of_freedom / 2, chi_square / 2, Policy()); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) +{ + RealType const& degrees_of_freedom = c.dist.degrees_of_freedom(); + RealType const& chi_square = c.param; + constexpr auto function = "boost::math::logcdf(const chi_squared_distribution<%1%>&, %1%)"; + RealType error_result; + if(!detail::check_df(function, degrees_of_freedom, &error_result, Policy())) + return error_result; + if((chi_square < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(chi_square)) + { + return policies::raise_domain_error( + function, "Chi Square parameter was %1%, but must be > 0 !", chi_square, Policy()); + } + return BOOST_MATH_NAMESPACE::lgamma_q(degrees_of_freedom / 2, chi_square / 2, Policy()); +} + +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { RealType const& degrees_of_freedom = c.dist.degrees_of_freedom(); @@ -206,22 +243,22 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const chi_squared_distribution& dist) { // Mean of Chi-Squared distribution = v. return dist.degrees_of_freedom(); } // mean -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const chi_squared_distribution& dist) { // Variance of Chi-Squared distribution = 2v. return 2 * dist.degrees_of_freedom(); } // variance -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const chi_squared_distribution& dist) { RealType df = dist.degrees_of_freedom(); @@ -235,7 +272,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mode(const chi_squared_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const chi_squared_distribution& dist) { BOOST_MATH_STD_USING // For ADL @@ -243,14 +280,14 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const chi_squared_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const chi_squared_distribution& dist) { RealType df = dist.degrees_of_freedom(); return 3 + 12 / df; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const chi_squared_distribution& dist) { RealType df = dist.degrees_of_freedom(); @@ -322,8 +359,8 @@ BOOST_MATH_GPU_ENABLED RealType chi_squared_distribution::find detail::df_estimator f(alpha, beta, variance, difference_from_variance); tools::eps_tolerance tol(policies::digits()); - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); - boost::math::pair r = + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::pair r = tools::bracket_and_solve_root(f, hint, RealType(2), false, tol, max_iter, Policy()); RealType result = r.first + (r.second - r.first) / 2; if(max_iter >= policies::get_max_root_iterations()) @@ -334,8 +371,17 @@ BOOST_MATH_GPU_ENABLED RealType chi_squared_distribution::find return result; } -} // namespace math -} // namespace boost +#ifndef BOOST_MATH_HAS_NVRTC +// Not GPU enabled: the Stirling series use Bernoulli numbers. +BOOST_MATH_EXPORT template +inline RealType entropy(const chi_squared_distribution& dist) +{ + // A gamma(k/2, 2) distribution: log(2) + k/2 + lgamma(k/2) + (1 - k/2) digamma(k/2). + return constants::ln_two() + detail::gamma_entropy_unit_scale(RealType(dist.degrees_of_freedom() / 2), Policy()); +} +#endif + +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/complement.hpp b/include/boost/math/distributions/complement.hpp index c63b8a5041..b8c35188d5 100644 --- a/include/boost/math/distributions/complement.hpp +++ b/include/boost/math/distributions/complement.hpp @@ -17,9 +17,9 @@ // not clear if that's possible. In any case this // code is *very* lightweight. // -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template struct complemented2_type { BOOST_MATH_GPU_ENABLED complemented2_type( @@ -35,7 +35,7 @@ struct complemented2_type complemented2_type& operator=(const complemented2_type&) = delete; }; -template +BOOST_MATH_EXPORT template struct complemented3_type { BOOST_MATH_GPU_ENABLED complemented3_type( @@ -53,7 +53,7 @@ struct complemented3_type complemented3_type& operator=(const complemented3_type&) = delete; }; -template +BOOST_MATH_EXPORT template struct complemented4_type { BOOST_MATH_GPU_ENABLED complemented4_type( @@ -74,7 +74,7 @@ struct complemented4_type complemented4_type& operator=(const complemented4_type&) = delete; }; -template +BOOST_MATH_EXPORT template struct complemented5_type { BOOST_MATH_GPU_ENABLED complemented5_type( @@ -98,7 +98,7 @@ struct complemented5_type complemented5_type& operator=(const complemented5_type&) = delete; }; -template +BOOST_MATH_EXPORT template struct complemented6_type { BOOST_MATH_GPU_ENABLED complemented6_type( @@ -125,7 +125,7 @@ struct complemented6_type complemented6_type& operator=(const complemented6_type&) = delete; }; -template +BOOST_MATH_EXPORT template struct complemented7_type { BOOST_MATH_GPU_ENABLED complemented7_type( @@ -155,44 +155,43 @@ struct complemented7_type complemented7_type& operator=(const complemented7_type&) = delete; }; -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline complemented2_type complement(const Dist& d, const RealType& r) { return complemented2_type(d, r); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline complemented3_type complement(const Dist& d, const RealType1& r1, const RealType2& r2) { return complemented3_type(d, r1, r2); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline complemented4_type complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3) { return complemented4_type(d, r1, r2, r3); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline complemented5_type complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3, const RealType4& r4) { return complemented5_type(d, r1, r2, r3, r4); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline complemented6_type complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3, const RealType4& r4, const RealType5& r5) { return complemented6_type(d, r1, r2, r3, r4, r5); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline complemented7_type complement(const Dist& d, const RealType1& r1, const RealType2& r2, const RealType3& r3, const RealType4& r4, const RealType5& r5, const RealType6& r6) { return complemented7_type(d, r1, r2, r3, r4, r5, r6); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_STATS_COMPLEMENT_HPP diff --git a/include/boost/math/distributions/detail/common_error_handling.hpp b/include/boost/math/distributions/detail/common_error_handling.hpp index 06e3c105bd..4bc876d6ef 100644 --- a/include/boost/math/distributions/detail/common_error_handling.hpp +++ b/include/boost/math/distributions/detail/common_error_handling.hpp @@ -22,13 +22,13 @@ # pragma warning(disable: 4702) // unreachable code (return after domain_error throw). #endif -namespace boost{ namespace math{ namespace detail +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template BOOST_MATH_GPU_ENABLED inline bool check_probability(const char* function, RealType const& prob, RealType* result, const Policy& pol) { - if((prob < 0) || (prob > 1) || !(boost::math::isfinite)(prob)) + if((prob < 0) || (prob > 1) || !(BOOST_MATH_NAMESPACE::isfinite)(prob)) { *result = policies::raise_domain_error( function, @@ -41,7 +41,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_probability(const char* function, RealT template BOOST_MATH_GPU_ENABLED inline bool check_df(const char* function, RealType const& df, RealType* result, const Policy& pol) { // df > 0 but NOT +infinity allowed. - if((df <= 0) || !(boost::math::isfinite)(df)) + if((df <= 0) || !(BOOST_MATH_NAMESPACE::isfinite)(df)) { *result = policies::raise_domain_error( function, @@ -54,7 +54,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_df(const char* function, RealType const template BOOST_MATH_GPU_ENABLED inline bool check_df_gt0_to_inf(const char* function, RealType const& df, RealType* result, const Policy& pol) { // df > 0 or +infinity are allowed. - if( (df <= 0) || (boost::math::isnan)(df) ) + if( (df <= 0) || (BOOST_MATH_NAMESPACE::isnan)(df) ) { // is bad df <= 0 or NaN or -infinity. *result = policies::raise_domain_error( function, @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_scale( RealType* result, const Policy& pol) { - if((scale <= 0) || !(boost::math::isfinite)(scale)) + if((scale <= 0) || !(BOOST_MATH_NAMESPACE::isfinite)(scale)) { // Assume scale == 0 is NOT valid for any distribution. *result = policies::raise_domain_error( function, @@ -89,7 +89,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_location( RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(location)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(location)) { *result = policies::raise_domain_error( function, @@ -110,7 +110,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_x( // Some distributions permit x to be infinite, so these must be tested 1st and return, // leaving this test to catch any NaNs. // See Normal, Logistic, Laplace and Cauchy for example. - if(!(boost::math::isfinite)(x)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(x)) { *result = policies::raise_domain_error( function, @@ -130,7 +130,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_x_not_NaN( // Note that this test catches only NaN. // Some distributions permit x to be infinite, leaving this test to catch any NaNs. // See Normal, Logistic, Laplace and Cauchy for example. - if ((boost::math::isnan)(x)) + if ((BOOST_MATH_NAMESPACE::isnan)(x)) { *result = policies::raise_domain_error( function, @@ -168,7 +168,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_positive_x( RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(x) || (x < 0)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(x) || (x < 0)) { *result = policies::raise_domain_error( function, @@ -188,9 +188,9 @@ BOOST_MATH_GPU_ENABLED inline bool check_non_centrality( RealType* result, const Policy& pol) { - BOOST_MATH_STATIC const RealType upper_limit = static_cast((boost::math::numeric_limits::max)()) - boost::math::policies::get_max_root_iterations(); + BOOST_MATH_STATIC const RealType upper_limit = static_cast((BOOST_MATH_NAMESPACE::numeric_limits::max)()) - BOOST_MATH_NAMESPACE::policies::get_max_root_iterations(); - if((ncp < 0) || !(boost::math::isfinite)(ncp) || ncp > upper_limit) + if((ncp < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(ncp) || ncp > upper_limit) { *result = policies::raise_domain_error( function, @@ -207,7 +207,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_finite( RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(x)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(x)) { // Assume scale == 0 is NOT valid for any distribution. *result = policies::raise_domain_error( function, @@ -218,8 +218,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_finite( } } // namespace detail -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER # pragma warning(pop) diff --git a/include/boost/math/distributions/detail/derived_accessors.hpp b/include/boost/math/distributions/detail/derived_accessors.hpp index 90679ef21f..c9d23902e9 100644 --- a/include/boost/math/distributions/detail/derived_accessors.hpp +++ b/include/boost/math/distributions/detail/derived_accessors.hpp @@ -32,8 +32,10 @@ #include #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif #ifdef _MSC_VER # pragma warning(push) @@ -41,26 +43,26 @@ // Suppressing spurious warning in coefficient_of_variation #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename Distribution::value_type variance(const Distribution& dist); -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type standard_deviation(const Distribution& dist) { BOOST_MATH_STD_USING // ADL of sqrt. return sqrt(variance(dist)); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type variance(const Distribution& dist) { typename Distribution::value_type result = standard_deviation(dist); return result * result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type hazard(const Distribution& dist, const RealType& x) { // hazard function // http://www.itl.nist.gov/div898/handbook/eda/section3/eda362.htm#HAZ @@ -79,7 +81,7 @@ BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type hazard(const Dis return d / p; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type chf(const Distribution& dist, const RealType& x) { // cumulative hazard function. // http://www.itl.nist.gov/div898/handbook/eda/section3/eda362.htm#HAZ @@ -87,7 +89,7 @@ BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type chf(const Distri return -log(cdf(complement(dist, x))); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type coefficient_of_variation(const Distribution& dist) { typedef typename Distribution::value_type value_type; @@ -108,33 +110,33 @@ BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type coefficient_of_v // argument types. We just use a typecast to forward on to the "real" // implementation with all arguments of the same type: // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type pdf(const Distribution& dist, const RealType& x) { typedef typename Distribution::value_type value_type; return pdf(dist, static_cast(x)); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type logpdf(const Distribution& dist, const RealType& x) { using std::log; typedef typename Distribution::value_type value_type; return log(pdf(dist, static_cast(x))); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type cdf(const Distribution& dist, const RealType& x) { typedef typename Distribution::value_type value_type; return cdf(dist, static_cast(x)); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type logcdf(const Distribution& dist, const Realtype& x) { using std::log; using value_type = typename Distribution::value_type; return log(cdf(dist, static_cast(x))); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type quantile(const Distribution& dist, const RealType& x) { typedef typename Distribution::value_type value_type; @@ -148,14 +150,14 @@ inline typename Distribution::value_type chf(const Distribution& dist, const Rea return chf(dist, static_cast(x)); } */ -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type cdf(const complemented2_type& c) { typedef typename Distribution::value_type value_type; return cdf(complement(c.dist, static_cast(c.param))); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type logcdf(const complemented2_type& c) { using std::log; @@ -163,14 +165,14 @@ BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type logcdf(const com return log(cdf(complement(c.dist, static_cast(c.param)))); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Distribution::value_type quantile(const complemented2_type& c) { typedef typename Distribution::value_type value_type; return quantile(complement(c.dist, static_cast(c.param))); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Dist::value_type median(const Dist& d) { // median - default definition for those distributions for which a // simple closed form is not known, @@ -179,8 +181,7 @@ BOOST_MATH_GPU_ENABLED inline typename Dist::value_type median(const Dist& d) return quantile(d, static_cast(0.5f)); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER diff --git a/include/boost/math/distributions/detail/entropy.hpp b/include/boost/math/distributions/detail/entropy.hpp new file mode 100644 index 0000000000..660d375108 --- /dev/null +++ b/include/boost/math/distributions/detail/entropy.hpp @@ -0,0 +1,220 @@ +// Copyright 2026 Nick Thompson +// 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) +// +// Building blocks for entropy(dist): Stirling remainders, which remove the cancellation between +// the x log(x) parts of lgamma and digamma at large parameters, and the Shannon entropy of a +// discrete distribution from the log ratios of its probabilities. + +#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_ENTROPY_HPP +#define BOOST_MATH_DISTRIBUTIONS_DETAIL_ENTROPY_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN +namespace detail { + +// Below this, entropies use lgamma and digamma directly; at or above it, the Stirling series +// below have converged to full precision before their terms start to grow. +template +inline RealType entropy_series_threshold() +{ + return (std::max)(RealType(10), RealType(policies::digits()) * RealType(0.14)); +} + +// Asymptotic series for large x of nu(x) = log(x) - 1/(2x) - digamma(x) and of +// r(x) = mu(x) + (x - 1) nu(x), where mu(x) = lgamma(x) - (x - 1/2) log(x) + x - log(2 pi)/2. +template +inline void entropy_stirling_series(RealType x, RealType& r, RealType& nu, const Policy& pol) +{ + BOOST_MATH_STD_USING + const RealType eps = policies::get_epsilon(); + r = 0; + nu = 0; + RealType x_power = x; // x^(2k - 1) + for (int k = 1; k < 100; ++k) + { + RealType b2k = bernoulli_b2n(k, pol); + RealType nu_term = b2k / (2 * k * x_power * x); + RealType r_term = b2k / ((2 * k - 1) * x_power) - nu_term; + r += r_term; + nu += nu_term; + if ((fabs(r_term) <= eps * fabs(r)) && (fabs(nu_term) <= eps * fabs(nu))) + break; + x_power *= x * x; + } +} + +// mu(x) = lgamma(x) - (x - 1/2) log(x) + x - log(2 pi)/2. +template +inline RealType entropy_stirling_mu(RealType x, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (x < entropy_series_threshold()) + { + return BOOST_MATH_NAMESPACE::lgamma(x, pol) - (x - constants::half()) * log(x) + x - constants::log_root_two_pi(); + } + const RealType eps = policies::get_epsilon(); + RealType mu = 0; + RealType x_power = x; + for (int k = 1; k < 100; ++k) + { + RealType term = bernoulli_b2n(k, pol) / (2 * k * (2 * k - 1) * x_power); + mu += term; + if (fabs(term) <= eps * fabs(mu)) + break; + x_power *= x * x; + } + return mu; +} + +// lgamma(z + t) - lgamma(z) - t log(z), for z and z + t > 0. With u = t/z it is +// z phi(u) - log1p(u)/2 + mu(z + t) - mu(z), where phi(u) = (1 + u) log1p(u) - u = u log1p(u) + log1pmx(u) +// has no cancellation to speak of, unlike the difference of the lgammas. +template +inline RealType entropy_lgamma_delta(RealType z, RealType t, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (t == 0) + return 0; + RealType u = t / z; + RealType l = BOOST_MATH_NAMESPACE::log1p(u, pol); + return z * (u * l + BOOST_MATH_NAMESPACE::log1pmx(u, pol)) - l / 2 + entropy_stirling_mu(RealType(z + t), pol) - entropy_stirling_mu(z, pol); +} + +// The entropy of gamma(a, 1): a + lgamma(a) + (1 - a) digamma(a). +// For large a, log(2 pi e a)/2 - 1/(2a) + r(a), with r from entropy_stirling_series. +template +inline RealType gamma_entropy_unit_scale(RealType a, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (a < entropy_series_threshold()) + { + return a + BOOST_MATH_NAMESPACE::lgamma(a, pol) + (1 - a) * BOOST_MATH_NAMESPACE::digamma(a, pol); + } + RealType r, nu; + entropy_stirling_series(a, r, nu, pol); + return log(a) / 2 + constants::log_root_two_pi() + constants::half() - 1 / (2 * a) + r; +} + +// The entropy of inverse_gamma(a, 1): a + lgamma(a) - (1 + a) digamma(a). +// For large a, log(2 pi e)/2 - 3 log(a)/2 + 1/(2a) + r(a) + 2 nu(a). +template +inline RealType inverse_gamma_entropy_unit_scale(RealType a, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (a < entropy_series_threshold()) + { + return a + BOOST_MATH_NAMESPACE::lgamma(a, pol) - (1 + a) * BOOST_MATH_NAMESPACE::digamma(a, pol); + } + RealType r, nu; + entropy_stirling_series(a, r, nu, pol); + return constants::log_root_two_pi() + constants::half() - 3 * log(a) / 2 + 1 / (2 * a) + r + 2 * nu; +} + +// Shannon entropy -sum p log(p) of a discrete distribution, from the log ratios S = log(p / p_0) of its +// probabilities at points spaced h apart, relative to a point near the mode (S = 0 there): +// H = log(h Z) - sum(w S) / Z, where w = exp(S) and Z = sum(w). +// Normalising by Z means that p_0 itself is never needed. With h = 1 at the integers this is exact. +// For a smooth pmf with standard deviation sigma >> 1, the sum over the integers equals the integral of +// the pmf's continuation (through lgamma) up to about exp(-2 pi^2 sigma^2), by the Poisson summation +// formula, and the trapezoidal rule with step h = sigma / c has the same integral up to exp(-2 pi^2 c^2). +// So a few dozen points suffice for any sigma. +// +// right(S, ratio) and left(S, ratio) set S at the next point to the right (left) of the last one and +// return false when there is none (the end of the support). On the integers they also set ratio to +// p(next) / p(last), and w is then the running product of the ratios wherever that has the smaller error +// bound (j steps against |S|; it is far better for tiny Poisson means, say); elsewhere ratio = 0. rho_floor is a lower bound for the ratio of successive +// weights far out in the right tail (needed only when that ratio increases, as for negative binomials +// with r < 1); the tail is bounded as a geometric series. +template +RealType discrete_entropy_sum(Right& right, Left& left, RealType h, RealType rho_floor, const char* function, const Policy& pol) +{ + BOOST_MATH_STD_USING + const RealType eps = policies::get_epsilon(); + const std::uintmax_t max_iter = policies::get_max_series_iterations(); + // Neumaier's compensated sums: the direct sums can run to ~1e5 terms (negative binomials with small p). + compensated_sum z; // sum of w, without the w = 1 at S = 0. + compensated_sum zs; // sum of w S. + std::uintmax_t iter = 0; + for (int side = 0; side < 2; ++side) + { + RealType s_prev = 0; + RealType w_product = 1; + RealType steps = 0; + RealType rho_min = side == 0 ? rho_floor : RealType(0); + for (;;) + { + RealType s; + RealType ratio = 0; + if (!(side == 0 ? right(s, ratio) : left(s, ratio))) + break; + w_product *= ratio; + steps += 1; + if (++iter > max_iter) + { + return policies::raise_evaluation_error(function, "Series did not converge, the entropy is approximately %1%.", + RealType(log(h) + BOOST_MATH_NAMESPACE::log1p(z.value(), pol) - zs.value() / (1 + z.value())), pol); + } + RealType w = ((ratio > 0) && (steps < fabs(s))) ? w_product : RealType(exp(s)); + z.add(w); + zs.add(w * s); + RealType rho = (std::max)(RealType(exp(s - s_prev)), rho_min); + s_prev = s; + if (rho < 1) + { + // Bound on the remaining sum of w (1 + |S|), S growing at most linearly in the tail: + RealType tail = w * (1 + fabs(s)) * rho / ((1 - rho) * (1 - rho)); + if (tail <= eps * (z.value() + fabs(zs.value())) / 16) + break; + } + } + } + RealType zv = z.value(); + return log(h) + BOOST_MATH_NAMESPACE::log1p(zv, pol) - zs.value() / (1 + zv); +} + +// The number of standard deviations beyond which a near-normal pmf is below eps / e^4, +// and c with exp(-2 pi^2 c^2) below eps / e^4: the trapezoidal step is sigma / c. +template +inline RealType discrete_entropy_tail_sigmas() +{ + BOOST_MATH_STD_USING + return sqrt(2 * (RealType(policies::digits()) * constants::ln_two() + 4)); +} + +template +inline RealType discrete_entropy_step_ratio() +{ + BOOST_MATH_STD_USING + return sqrt((RealType(policies::digits()) * constants::ln_two() + 4) / (2 * constants::pi_sqr())) + constants::half(); +} + +// log(num/den), with d = num - den computed accurately by the caller, for successive pmf ratios; +// sets ratio = num/den, or den/num going left. +template +inline RealType entropy_log_ratio(RealType num, RealType den, RealType d, RealType& ratio, bool left, const Policy& pol) +{ + BOOST_MATH_STD_USING + ratio = left ? RealType(den / num) : RealType(num / den); + return (fabs(d) < den / 2) ? BOOST_MATH_NAMESPACE::log1p(d / den, pol) : RealType(log(num / den)); +} + +} // namespace detail +BOOST_MATH_NAMESPACE_END + +#endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_ENTROPY_HPP diff --git a/include/boost/math/distributions/detail/generic_mode.hpp b/include/boost/math/distributions/detail/generic_mode.hpp index 9306c815da..5c028a0ee9 100644 --- a/include/boost/math/distributions/detail/generic_mode.hpp +++ b/include/boost/math/distributions/detail/generic_mode.hpp @@ -15,7 +15,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template struct pdf_minimizer @@ -73,7 +73,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type generic_find_mode(const Dist& d v = pdf(dist, lower_bound); }while(maxval < v); - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); value_type result = tools::brent_find_minima( pdf_minimizer(dist), @@ -124,7 +124,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type generic_find_mode_01(const Dist v = pdf(dist, lower_bound); }while(maxval < v); - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); value_type result = tools::brent_find_minima( pdf_minimizer(dist), @@ -140,6 +140,6 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type generic_find_mode_01(const Dist return result; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_MODE_HPP diff --git a/include/boost/math/distributions/detail/generic_quantile.hpp b/include/boost/math/distributions/detail/generic_quantile.hpp index 917532566f..6261fb7689 100644 --- a/include/boost/math/distributions/detail/generic_quantile.hpp +++ b/include/boost/math/distributions/detail/generic_quantile.hpp @@ -10,7 +10,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template struct generic_quantile_finder @@ -82,8 +82,8 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type generic_quantile(const Dist& di generic_quantile_finder f(dist, p, comp); tools::eps_tolerance tol(policies::digits() - 3); - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); - boost::math::pair ir = tools::bracket_and_solve_root( + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::pair ir = tools::bracket_and_solve_root( f, guess, value_type(2), true, tol, max_iter, forwarding_policy()); value_type result = ir.first + (ir.second - ir.first) / 2; if(max_iter >= policies::get_max_root_iterations()) @@ -94,7 +94,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type generic_quantile(const Dist& di return result; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP diff --git a/include/boost/math/distributions/detail/hypergeometric_cdf.hpp b/include/boost/math/distributions/detail/hypergeometric_cdf.hpp index 60e29bc10c..36bc62573b 100644 --- a/include/boost/math/distributions/detail/hypergeometric_cdf.hpp +++ b/include/boost/math/distributions/detail/hypergeometric_cdf.hpp @@ -10,9 +10,11 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template T hypergeometric_cdf_imp(std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, bool invert, const Policy& pol) @@ -95,7 +97,7 @@ namespace boost{ namespace math{ namespace detail{ return policies::checked_narrowing_cast(result, "boost::math::hypergeometric_cdf<%1%>(%1%,%1%,%1%,%1%)"); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/distributions/detail/hypergeometric_pdf.hpp b/include/boost/math/distributions/detail/hypergeometric_pdf.hpp index 0ec3065eb3..c877ac9cde 100644 --- a/include/boost/math/distributions/detail/hypergeometric_pdf.hpp +++ b/include/boost/math/distributions/detail/hypergeometric_pdf.hpp @@ -15,14 +15,20 @@ #include #include #include +#include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#include +#endif #ifdef BOOST_MATH_INSTRUMENT +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template void bubble_down_one(T* first, T* last, Func f) @@ -217,19 +223,19 @@ T hypergeometric_pdf_lanczos_imp(T /*dummy*/, std::uint64_t x, std::uint64_t r, } template -T hypergeometric_pdf_lanczos_imp(T /*dummy*/, std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const boost::math::lanczos::undefined_lanczos&, const Policy& pol) +T hypergeometric_pdf_lanczos_imp(T /*dummy*/, std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const BOOST_MATH_NAMESPACE::lanczos::undefined_lanczos&, const Policy& pol) { BOOST_MATH_STD_USING return exp( - boost::math::lgamma(T(n + 1), pol) - + boost::math::lgamma(T(r + 1), pol) - + boost::math::lgamma(T(N - n + 1), pol) - + boost::math::lgamma(T(N - r + 1), pol) - - boost::math::lgamma(T(N + 1), pol) - - boost::math::lgamma(T(x + 1), pol) - - boost::math::lgamma(T(n - x + 1), pol) - - boost::math::lgamma(T(r - x + 1), pol) - - boost::math::lgamma(T(N - n - r + x + 1), pol)); + BOOST_MATH_NAMESPACE::lgamma(T(n + 1), pol) + + BOOST_MATH_NAMESPACE::lgamma(T(r + 1), pol) + + BOOST_MATH_NAMESPACE::lgamma(T(N - n + 1), pol) + + BOOST_MATH_NAMESPACE::lgamma(T(N - r + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(T(N + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(T(x + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(T(n - x + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(T(r - x + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(T(N - n - r + x + 1), pol)); } template @@ -248,15 +254,15 @@ inline T integer_power(const T& x, int ex) case 3: return x * x * x; case 4: - return boost::math::pow<4>(x); + return BOOST_MATH_NAMESPACE::pow<4>(x); case 5: - return boost::math::pow<5>(x); + return BOOST_MATH_NAMESPACE::pow<5>(x); case 6: - return boost::math::pow<6>(x); + return BOOST_MATH_NAMESPACE::pow<6>(x); case 7: - return boost::math::pow<7>(x); + return BOOST_MATH_NAMESPACE::pow<7>(x); case 8: - return boost::math::pow<8>(x); + return BOOST_MATH_NAMESPACE::pow<8>(x); } BOOST_MATH_STD_USING #ifdef __SUNPRO_CC @@ -394,19 +400,19 @@ template T hypergeometric_pdf_factorial_imp(std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy&) { BOOST_MATH_STD_USING - BOOST_MATH_ASSERT(N <= boost::math::max_factorial::value); - T result = boost::math::unchecked_factorial(static_cast(n)); + BOOST_MATH_ASSERT(N <= BOOST_MATH_NAMESPACE::max_factorial::value); + T result = BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(n)); T num[3] = { - boost::math::unchecked_factorial(static_cast(r)), - boost::math::unchecked_factorial(static_cast(N - n)), - boost::math::unchecked_factorial(static_cast(N - r)) + BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(r)), + BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(N - n)), + BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(N - r)) }; T denom[5] = { - boost::math::unchecked_factorial(static_cast(N)), - boost::math::unchecked_factorial(static_cast(x)), - boost::math::unchecked_factorial(static_cast(n - x)), - boost::math::unchecked_factorial(static_cast(r - x)), - boost::math::unchecked_factorial(static_cast(N - n - r + x)) + BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(N)), + BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(x)), + BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(n - x)), + BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(r - x)), + BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(N - n - r + x)) }; std::size_t i = 0; std::size_t j = 0; @@ -427,6 +433,52 @@ T hypergeometric_pdf_factorial_imp(std::uint64_t x, std::uint64_t r, std::uint64 } +#ifndef BOOST_MATH_HAS_GPU_SUPPORT +// +// Loader's method, as in R's dhyper: the ratio of binomial densities +// Binom(x; r, p) Binom(n - x; N - r, p) / Binom(n; N, p), +// in which the powers of p cancel. With p = n / N the denominator is at its mode. Near the mode +// the accuracy does not degrade as N grows, as long as the products of counts formed below are +// exact (below 2^53 for double); in the tails the relative error grows like |ln pdf| eps. +// +template +T hypergeometric_pdf_saddle_point_imp(std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (n > N - n) + { + // Swap the sample with the rest of the population, pdf(x; r, n, N) = pdf(r - x; r, N - n, N), + // so that p = n / N <= 1/2: with p near 1, powers of q = 1 - p with huge exponents would + // have to cancel between the binomials. + return hypergeometric_pdf_saddle_point_imp(r - x, r, N - n, N, pol); + } + const std::uint64_t r_x = r - x, n_x = n - x, rest = N - r - n + x; + const T p = static_cast(n) / static_cast(N); + const T q = static_cast(N - n) / static_cast(N); + if ((x == 0) || (r_x == 0) || (n_x == 0) || (rest == 0) || (n == 0) || (n == N)) + { + // At the ends of the support one binomial is degenerate; its own branches handle that. + // Combined as logarithms, so that no intermediate product underflows before the division. + return exp(log_binomial_pdf_saddle_point(static_cast(x), static_cast(r), p, q, pol) + + log_binomial_pdf_saddle_point(static_cast(n_x), static_cast(N - r), p, q, pol) + - log_binomial_pdf_saddle_point(static_cast(n), static_cast(N), p, q, pol)); + } + // All three binomials in one exponent. The means are r n / N, r (N - n) / N, (N - r) n / N and + // (N - r)(N - n) / N, passed as ratios; the denominator's deviance terms vanish, as n = N p exactly. + const T vN = static_cast(N), vn = static_cast(n), vm = static_cast(N - n); + const T vr = static_cast(r), vs = static_cast(N - r); + const T vx = static_cast(x), vr_x = static_cast(r_x), vn_x = static_cast(n_x), vrest = static_cast(rest); + const T lc = stirlerr(vr, pol) - stirlerr(vx, pol) - stirlerr(vr_x, pol) + + stirlerr(vs, pol) - stirlerr(vn_x, pol) - stirlerr(vrest, pol) + - stirlerr(vN, pol) + stirlerr(vn, pol) + stirlerr(vm, pol) + - bd0_ratio(vx, T(vr * vn), vN, pol) - bd0_ratio(vr_x, T(vr * vm), vN, pol) + - bd0_ratio(vn_x, T(vs * vn), vN, pol) - bd0_ratio(vrest, T(vs * vm), vN, pol); + // The Gaussian prefactors: sqrt(r / (2 pi x (r - x))) sqrt((N - r) / (2 pi (n - x) rest)) / sqrt(N / (2 pi n (N - n))). + const T prefactor = sqrt((vr / (vx * vr_x)) * (vs / (vn_x * vrest)) * ((vn * vm) / vN) / constants::two_pi()); + return exp(lc) * prefactor; +} +#endif + template inline typename tools::promote_args::type hypergeometric_pdf(std::uint64_t x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy&) @@ -434,7 +486,6 @@ inline typename tools::promote_args::type BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; typedef typename policies::evaluation::type value_type; - typedef typename lanczos::lanczos::type evaluation_type; typedef typename policies::normalise< Policy, policies::promote_float, @@ -443,7 +494,7 @@ inline typename tools::promote_args::type policies::assert_undefined<> >::type forwarding_policy; value_type result; - if(N <= boost::math::max_factorial::value) + if(N <= BOOST_MATH_NAMESPACE::max_factorial::value) { // // If N is small enough then we can evaluate the PDF via the factorials @@ -452,7 +503,31 @@ inline typename tools::promote_args::type // result = detail::hypergeometric_pdf_factorial_imp(x, r, n, N, forwarding_policy()); } - else if(N <= boost::math::prime(boost::math::max_prime - 1)) +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + else if((N <= BOOST_MATH_NAMESPACE::prime(BOOST_MATH_NAMESPACE::max_prime - 1)) && !(std::numeric_limits::is_specialized && (std::numeric_limits::digits <= 64))) + { + // + // Beyond 64-bit precision, Loader's method needs many more steps for its Stirling remainders + // at small arguments, so while the table of primes reaches we keep prime factorisation. + // + result = detail::hypergeometric_pdf_prime_imp(x, r, n, N, forwarding_policy()); + } + else + { + // + // Otherwise Loader's saddle-point method, as in R's dhyper: it keeps its accuracy however + // large N is, and is hundreds of times faster than prime factorisation at N ~ 1e5. + // Its relative error grows like |ln pdf| eps, though, since it exponentiates, so in the + // tails, where the prime table reaches, prime factorisation is more accurate: + // + result = detail::hypergeometric_pdf_saddle_point_imp(x, r, n, N, forwarding_policy()); + if((result < value_type(3.0590232050182578837e-7L)) && (N <= BOOST_MATH_NAMESPACE::prime(BOOST_MATH_NAMESPACE::max_prime - 1))) // e^-15 + { + result = detail::hypergeometric_pdf_prime_imp(x, r, n, N, forwarding_policy()); + } + } +#else + else if(N <= BOOST_MATH_NAMESPACE::prime(BOOST_MATH_NAMESPACE::max_prime - 1)) { // // If N is no larger than the largest prime number in our lookup table @@ -464,13 +539,13 @@ inline typename tools::promote_args::type else { // - // Catch all case - use the lanczos approximation - where available - - // to evaluate the ratio of factorials. This is reasonably fast - // (almost as quick as using logarithmic evaluation in terms of lgamma) - // but only a few digits better in accuracy than using lgamma: + // Catch all case - use the lanczos approximation - where available - + // to evaluate the ratio of factorials. This loses around log10(N) decimal digits. // + typedef typename lanczos::lanczos::type evaluation_type; result = detail::hypergeometric_pdf_lanczos_imp(value_type(), x, r, n, N, evaluation_type(), forwarding_policy()); } +#endif if(result > 1) { @@ -484,7 +559,48 @@ inline typename tools::promote_args::type return policies::checked_narrowing_cast(result, "boost::math::hypergeometric_pdf<%1%>(%1%,%1%,%1%,%1%)"); } -}}} // namespaces +// +// The analytic continuation C(r, x) C(N - r, n - x) / C(N, n) to non-integer x, lower < x < upper. +// Anchor at k = floor(x) (passed as floor_x), whose PDF the integer code computes accurately, and shift by d = x - k: +// pdf(x) = pdf(k) D(k + 1) D(N - r - n + k + 1) / (D(r - x + 1) D(n - x + 1)), +// where D(z) = Gamma(z) / Gamma(z + d) is tgamma_delta_ratio. Each ratio is accurate for small d +// and large z, where a quotient of gamma functions or of powers would lose digits in proportion to N, +// and each tends to 1 as d -> 0, so the continuation meets the integer values. +// +template +inline typename tools::promote_args::type + hypergeometric_pdf_noninteger(T x, std::uint64_t floor_x, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy&) +{ + BOOST_FPU_EXCEPTION_GUARD + BOOST_MATH_STD_USING + typedef typename tools::promote_args::type result_type; + typedef typename policies::evaluation::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + const value_type vx = x; + const value_type k = static_cast(floor_x); + const value_type d = vx - k; + const value_type base = hypergeometric_pdf(floor_x, r, n, N, forwarding_policy()); + // Differences of the counts are formed in integers, where they are exact and, inside the support, + // non-negative; converting the counts first would round them when they exceed the precision. + const value_type failures_left = static_cast(N + floor_x - r - n); // N - r - n + floor(x) >= 0 + const value_type r_left = static_cast(r - floor_x); // >= 1, as x < r + const value_type n_left = static_cast(n - floor_x); // >= 1, as x < n + // Each numerator is paired with a denominator, so that no intermediate product underflows early. + value_type result = base + * (BOOST_MATH_NAMESPACE::tgamma_delta_ratio(value_type(k + 1), d, forwarding_policy()) + / BOOST_MATH_NAMESPACE::tgamma_delta_ratio(value_type(r_left + 1 - d), d, forwarding_policy())) + * (BOOST_MATH_NAMESPACE::tgamma_delta_ratio(value_type(failures_left + 1), d, forwarding_policy()) + / BOOST_MATH_NAMESPACE::tgamma_delta_ratio(value_type(n_left + 1 - d), d, forwarding_policy())); + return policies::checked_narrowing_cast(result, "boost::math::hypergeometric_pdf<%1%>(%1%,%1%,%1%,%1%)"); +} + +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/distributions/detail/hypergeometric_quantile.hpp b/include/boost/math/distributions/detail/hypergeometric_quantile.hpp index 2441a73309..5f158fbb48 100644 --- a/include/boost/math/distributions/detail/hypergeometric_quantile.hpp +++ b/include/boost/math/distributions/detail/hypergeometric_quantile.hpp @@ -11,139 +11,77 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ -template -inline std::uint64_t round_x_from_p(std::uint64_t x, T p, T cum, T fudge_factor, std::uint64_t lbound, std::uint64_t /*ubound*/, const policies::discrete_quantile&) -{ - if((p < cum * fudge_factor) && (x != lbound)) - { - BOOST_MATH_INSTRUMENT_VARIABLE(x-1); - return --x; - } - return x; -} - -template -inline std::uint64_t round_x_from_p(std::uint64_t x, T p, T cum, T fudge_factor, std::uint64_t /*lbound*/, std::uint64_t ubound, const policies::discrete_quantile&) -{ - if((cum < p * fudge_factor) && (x != ubound)) - { - BOOST_MATH_INSTRUMENT_VARIABLE(x+1); - return ++x; - } - return x; -} - -template -inline std::uint64_t round_x_from_p(std::uint64_t x, T p, T cum, T fudge_factor, std::uint64_t lbound, std::uint64_t ubound, const policies::discrete_quantile&) -{ - if(p >= 0.5) - return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); - return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); -} - -template -inline std::uint64_t round_x_from_p(std::uint64_t x, T p, T cum, T fudge_factor, std::uint64_t lbound, std::uint64_t ubound, const policies::discrete_quantile&) -{ - if(p >= 0.5) - return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); - return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); -} - -template -inline std::uint64_t round_x_from_p(std::uint64_t x, T /*p*/, T /*cum*/, T /*fudge_factor*/, std::uint64_t /*lbound*/, std::uint64_t /*ubound*/, const policies::discrete_quantile&) -{ - return x; -} - -template -inline std::uint64_t round_x_from_q(std::uint64_t x, T q, T cum, T fudge_factor, std::uint64_t lbound, std::uint64_t /*ubound*/, const policies::discrete_quantile&) -{ - if((q * fudge_factor > cum) && (x != lbound)) - { - BOOST_MATH_INSTRUMENT_VARIABLE(x-1); - return --x; - } - return x; -} - -template -inline std::uint64_t round_x_from_q(std::uint64_t x, T q, T cum, T fudge_factor, std::uint64_t /*lbound*/, std::uint64_t ubound, const policies::discrete_quantile&) -{ - if((q < cum * fudge_factor) && (x != ubound)) - { - BOOST_MATH_INSTRUMENT_VARIABLE(x+1); - return ++x; - } - return x; -} - -template -inline std::uint64_t round_x_from_q(std::uint64_t x, T q, T cum, T fudge_factor, std::uint64_t lbound, std::uint64_t ubound, const policies::discrete_quantile&) -{ - if(q < 0.5) - return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); - return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); -} - -template -inline std::uint64_t round_x_from_q(std::uint64_t x, T q, T cum, T fudge_factor, std::uint64_t lbound, std::uint64_t ubound, const policies::discrete_quantile&) -{ - if(q >= 0.5) - return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); - return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile()); -} - -template -inline std::uint64_t round_x_from_q(std::uint64_t x, T /*q*/, T /*cum*/, T /*fudge_factor*/, std::uint64_t /*lbound*/, std::uint64_t /*ubound*/, const policies::discrete_quantile&) +// +// The result of summing the pdf up to p (or down to q = 1 - p): +// +// up: the smallest x with cdf(x) >= p, by the running sum, +// nearest: up or up - 1, whichever p is nearer to in a linear +// interpolation of the cdf between them, +// ambiguous: the running sum at up or up - 1 is within rounding error of +// p, so the comparison with p must be made with cdf() itself. +// +// c says whether the caller's probability is q (the complement) or p. +// +struct hypergeometric_quantile_result { - return x; -} + std::uint64_t up; + std::uint64_t nearest; + bool ambiguous; +}; template -std::uint64_t hypergeometric_quantile_imp(T p, T q, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy& pol) +hypergeometric_quantile_result hypergeometric_quantile_imp(T p, T q, bool c, T caller_epsilon, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy& pol) { #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable:4267) #endif - typedef typename Policy::discrete_quantile_type discrete_quantile_type; BOOST_MATH_STD_USING BOOST_FPU_EXCEPTION_GUARD - T result; - T fudge_factor = 1 + tools::epsilon() * ((N <= boost::math::prime(boost::math::max_prime - 1)) ? 50 : 2 * N); - std::uint64_t base = static_cast((std::max)(0, static_cast(n + r) - static_cast(N))); - std::uint64_t lim = (std::min)(r, n); + // How far (relatively) the running sum may be from cdf(): the error of + // each, doubled. cdf() is rounded to the caller's type, which may be + // narrower than T (float is evaluated in double): + const T eps = (std::max)(tools::epsilon(), caller_epsilon); + const T fudge = eps * ((N <= BOOST_MATH_NAMESPACE::prime(BOOST_MATH_NAMESPACE::max_prime - 1)) ? 100 : 4 * N); + // The caller compares with p if c is false, else with q. When we search + // with the other one, 1 - p or 1 - q and the cdf near 1 it is compared + // with are only known to within a few epsilon absolutely: + const T converted = 4 * eps; + const std::uint64_t base = static_cast((std::max)(0, static_cast(n + r) - static_cast(N))); + const std::uint64_t lim = (std::min)(r, n); + hypergeometric_quantile_result res; BOOST_MATH_INSTRUMENT_VARIABLE(p); BOOST_MATH_INSTRUMENT_VARIABLE(q); BOOST_MATH_INSTRUMENT_VARIABLE(r); BOOST_MATH_INSTRUMENT_VARIABLE(n); BOOST_MATH_INSTRUMENT_VARIABLE(N); - BOOST_MATH_INSTRUMENT_VARIABLE(fudge_factor); BOOST_MATH_INSTRUMENT_VARIABLE(base); BOOST_MATH_INSTRUMENT_VARIABLE(lim); if(p <= 0.5) { + // + // Sum the cdf upwards: cum = cdf(x), prev = cdf(x - 1). + // std::uint64_t x = base; - result = hypergeometric_pdf(x, r, n, N, pol); - T diff = result; + T diff = hypergeometric_pdf(x, r, n, N, pol); if (diff == 0) { ++x; // We want to skip through x values as fast as we can until we start getting non-zero values, // otherwise we're just making lots of expensive PDF calls: - T log_pdf = boost::math::lgamma(static_cast(n + 1), pol) - + boost::math::lgamma(static_cast(r + 1), pol) - + boost::math::lgamma(static_cast(N - n + 1), pol) - + boost::math::lgamma(static_cast(N - r + 1), pol) - - boost::math::lgamma(static_cast(N + 1), pol) - - boost::math::lgamma(static_cast(x + 1), pol) - - boost::math::lgamma(static_cast(n - x + 1), pol) - - boost::math::lgamma(static_cast(r - x + 1), pol) - - boost::math::lgamma(static_cast(N - n - r + x + 1), pol); + T log_pdf = BOOST_MATH_NAMESPACE::lgamma(static_cast(n + 1), pol) + + BOOST_MATH_NAMESPACE::lgamma(static_cast(r + 1), pol) + + BOOST_MATH_NAMESPACE::lgamma(static_cast(N - n + 1), pol) + + BOOST_MATH_NAMESPACE::lgamma(static_cast(N - r + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(N + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(x + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(n - x + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(r - x + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(N - n - r + x + 1), pol); while (log_pdf < tools::log_min_value()) { log_pdf += -log(static_cast(x + 1)) + log(static_cast(n - x)) + log(static_cast(r - x)) - log(static_cast(N - n - r + x + 1)); @@ -153,45 +91,47 @@ std::uint64_t hypergeometric_quantile_imp(T p, T q, std::uint64_t r, std::uint64 // roundoff errors, get a fresh PDF calculation before proceeding: diff = hypergeometric_pdf(x, r, n, N, pol); } - while(result < p) + T cum = diff; + T prev = 0; + while((cum < p) && (x < lim)) { diff = (diff > tools::min_value() * 8) ? T(n - x) * T(r - x) * diff / (T(x + 1) * T(N + x + 1 - n - r)) : hypergeometric_pdf(x + 1, r, n, N, pol); - if(result + diff / 2 > p) - break; ++x; - result += diff; -#ifdef BOOST_MATH_INSTRUMENT - if(diff != 0) - { - BOOST_MATH_INSTRUMENT_VARIABLE(x); - BOOST_MATH_INSTRUMENT_VARIABLE(diff); - BOOST_MATH_INSTRUMENT_VARIABLE(result); - } -#endif + prev = cum; + cum += diff; + BOOST_MATH_INSTRUMENT_VARIABLE(x); + BOOST_MATH_INSTRUMENT_VARIABLE(cum); } - return round_x_from_p(x, p, result, fudge_factor, base, lim, discrete_quantile_type()); + res.up = x; + res.nearest = ((x != base) && (p < (prev + cum) / 2)) ? x - 1 : x; + const T slack = p * fudge + (c ? converted : T(0)); + res.ambiguous = (cum < p) || (cum - p <= slack) || ((x != base) && (p - prev <= slack)); } else { + // + // Sum the complement downwards: cum = cdf(complement(x)), + // next = cdf(complement(x - 1)), and up is the smallest x with + // cum <= q. + // std::uint64_t x = lim; - result = 0; T diff = hypergeometric_pdf(x, r, n, N, pol); if (diff == 0) { // We want to skip through x values as fast as we can until we start getting non-zero values, // otherwise we're just making lots of expensive PDF calls: --x; - T log_pdf = boost::math::lgamma(static_cast(n + 1), pol) - + boost::math::lgamma(static_cast(r + 1), pol) - + boost::math::lgamma(static_cast(N - n + 1), pol) - + boost::math::lgamma(static_cast(N - r + 1), pol) - - boost::math::lgamma(static_cast(N + 1), pol) - - boost::math::lgamma(static_cast(x + 1), pol) - - boost::math::lgamma(static_cast(n - x + 1), pol) - - boost::math::lgamma(static_cast(r - x + 1), pol) - - boost::math::lgamma(static_cast(N - n - r + x + 1), pol); + T log_pdf = BOOST_MATH_NAMESPACE::lgamma(static_cast(n + 1), pol) + + BOOST_MATH_NAMESPACE::lgamma(static_cast(r + 1), pol) + + BOOST_MATH_NAMESPACE::lgamma(static_cast(N - n + 1), pol) + + BOOST_MATH_NAMESPACE::lgamma(static_cast(N - r + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(N + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(x + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(n - x + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(r - x + 1), pol) + - BOOST_MATH_NAMESPACE::lgamma(static_cast(N - n - r + x + 1), pol); while (log_pdf < tools::log_min_value()) { log_pdf += log(static_cast(x)) - log(static_cast(n - x + 1)) - log(static_cast(r - x + 1)) + log(static_cast(N - n - r + x)); @@ -201,31 +141,33 @@ std::uint64_t hypergeometric_quantile_imp(T p, T q, std::uint64_t r, std::uint64 // roundoff errors, get a fresh PDF calculation before proceeding: diff = hypergeometric_pdf(x, r, n, N, pol); } - while(result + diff / 2 < q) + // diff is pdf(x), so cdf(complement(x - 1)) = cum + diff: + T cum = 0; + while((cum + diff <= q) && (x > base)) { - result += diff; + cum += diff; diff = (diff > tools::min_value() * 8) ? x * T(N + x - n - r) * diff / (T(1 + n - x) * T(1 + r - x)) : hypergeometric_pdf(x - 1, r, n, N, pol); --x; -#ifdef BOOST_MATH_INSTRUMENT - if(diff != 0) - { - BOOST_MATH_INSTRUMENT_VARIABLE(x); - BOOST_MATH_INSTRUMENT_VARIABLE(diff); - BOOST_MATH_INSTRUMENT_VARIABLE(result); - } -#endif + BOOST_MATH_INSTRUMENT_VARIABLE(x); + BOOST_MATH_INSTRUMENT_VARIABLE(cum); } - return round_x_from_q(x, q, result, fudge_factor, base, lim, discrete_quantile_type()); + const T next = cum + diff; + res.up = x; + // In terms of p, x - 1 is nearer when p < cdf(x - 1) + pdf(x) / 2: + res.nearest = ((x != base) && (q > cum + diff / 2)) ? x - 1 : x; + const T slack = q * fudge + (c ? T(0) : converted); + res.ambiguous = (q - cum <= slack) || ((x != base) && (next - q <= slack)); } + return res; #ifdef _MSC_VER # pragma warning(pop) #endif } template -inline std::uint64_t hypergeometric_quantile(T p, T q, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy&) +inline hypergeometric_quantile_result hypergeometric_quantile(T p, T q, bool c, std::uint64_t r, std::uint64_t n, std::uint64_t N, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -236,10 +178,10 @@ inline std::uint64_t hypergeometric_quantile(T p, T q, std::uint64_t r, std::uin policies::promote_double, policies::assert_undefined<> >::type forwarding_policy; - return detail::hypergeometric_quantile_imp(p, q, r, n, N, forwarding_policy()); + return detail::hypergeometric_quantile_imp(p, q, c, value_type(tools::epsilon()), r, n, N, forwarding_policy()); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/distributions/detail/inv_discrete_quantile.hpp b/include/boost/math/distributions/detail/inv_discrete_quantile.hpp index ac4a2b2318..36581693e1 100644 --- a/include/boost/math/distributions/detail/inv_discrete_quantile.hpp +++ b/include/boost/math/distributions/detail/inv_discrete_quantile.hpp @@ -12,7 +12,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // // Functor for root finding algorithm: @@ -82,7 +82,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type const typename Dist::value_type& multiplier, typename Dist::value_type adder, const Tolerance& tol, - boost::math::uintmax_t& max_iter) + BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { typedef typename Dist::value_type value_type; typedef typename Dist::policy_type policy_type; @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type // Max bounds of the distribution: // value_type min_bound, max_bound; - boost::math::tie(min_bound, max_bound) = support(dist); + BOOST_MATH_NAMESPACE::tie(min_bound, max_bound) = support(dist); if(guess > max_bound) guess = max_bound; @@ -104,7 +104,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type guess = min_bound; value_type fa = f(guess); - boost::math::uintmax_t count = max_iter - 1; + BOOST_MATH_NAMESPACE::uintmax_t count = max_iter - 1; value_type fb(fa), a(guess), b =0; // Compiler warning C4701: potentially uninitialized local variable 'b' used if(fa == 0) @@ -207,7 +207,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type // If the root hasn't been bracketed yet, try again // using the multiplier this time: // - if((boost::math::sign)(fb) == (boost::math::sign)(fa)) + if((BOOST_MATH_NAMESPACE::sign)(fb) == (BOOST_MATH_NAMESPACE::sign)(fa)) { if(fa < 0) { @@ -215,7 +215,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type // Zero is to the right of x2, so walk upwards // until we find it: // - while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b)) + while(((BOOST_MATH_NAMESPACE::sign)(fb) == (BOOST_MATH_NAMESPACE::sign)(fa)) && (a != b)) { if(count == 0) return policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, policy_type()); // LCOV_EXCL_LINE @@ -235,7 +235,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type // Zero is to the left of a, so walk downwards // until we find it: // - while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b)) + while(((BOOST_MATH_NAMESPACE::sign)(fb) == (BOOST_MATH_NAMESPACE::sign)(fa)) && (a != b)) { if(fabs(a) < tools::min_value()) { @@ -277,7 +277,7 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type // // Go ahead and find the root: // - boost::math::pair r = toms748_solve(f, a, b, fa, fb, tol, count, policy_type()); + BOOST_MATH_NAMESPACE::pair r = toms748_solve(f, a, b, fa, fb, tol, count, policy_type()); max_iter += count; if (max_iter >= policies::get_max_root_iterations()) { @@ -288,83 +288,237 @@ BOOST_MATH_GPU_ENABLED typename Dist::value_type return (r.first + r.second) / 2; } // -// Some special routine for rounding up and down: -// We want to check and see if we are very close to an integer, and if so test to see if -// that integer is an exact root of the cdf. We do this because our root finder only -// guarantees to find *a root*, and there can sometimes be many consecutive floating -// point values which are all roots. This is especially true if the target probability -// is very close 1. +// Rounding the real-valued root to an integer. +// +// The root finder above solves the *continuous* cdf(x) = p, and near an +// integer k the root it finds is only known to within the error of the cdf +// evaluated slightly off that integer. Simply taking floor or ceil of it +// then gets the integer wrong by one whenever p is within a few ulps of +// cdf(k): https://github.com/boostorg/math/issues/935 +// +// So we only use the real root as a starting point and settle the answer +// using the cdf at integers, which is what callers compare against: +// +// round up: the smallest k with cdf(k) >= p, +// round down: the largest k with cdf(k) <= p. +// +// Round up is the usual definition of a discrete quantile (R, SciPy, Julia +// and Mathematica all use it). Where a run of consecutive integers all have +// cdf(k) == p exactly (common as p -> 1) both take these definitions +// literally: round up gives the first of the run and round down the last. +// For the complement (c == true) read "cdf(k) - p" as +// "p - cdf(complement(d, k))", which also increases with k, so round up +// gives the smallest k with cdf(complement(d, k)) <= p. +// +// The support need not end on an integer (the binomial accepts fractional +// trials), so integers above it are handled without calling the cdf: there +// cdf(k) == 1 and cdf(complement(d, k)) == 0. // template -BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_to_floor(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c) +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type discrete_quantile_residual(const Dist& d, const typename Dist::value_type& k, const typename Dist::value_type& p, bool c) +{ + typedef typename Dist::value_type value_type; + if (k > support(d).second) + return c ? p : value_type(1 - p); + return c ? value_type(p - cdf(complement(d, k))) : value_type(cdf(d, k) - p); +} + +// +// The smallest integer k in [lo, hi] at which the residual is >= 0 (or > 0 +// when "strict"), searching from k. The residual increases with k, and is +// taken to pass at hi without evaluating it there. The answer is normally +// within one of k, but where the cdf rounds to the same value over a long +// run of integers (as p -> 1) it may be far away, so gallop, then bisect. +// +template +BOOST_MATH_GPU_ENABLED inline bool discrete_quantile_passes(const Dist& d, const typename Dist::value_type& k, const typename Dist::value_type& p, bool c, bool strict) +{ + typename Dist::value_type r = discrete_quantile_residual(d, k, p, c); + return strict ? (r > 0) : (r >= 0); +} + +template +BOOST_MATH_GPU_ENABLED typename Dist::value_type first_passing_integer(const Dist& d, typename Dist::value_type k, const typename Dist::value_type& p, bool c, bool strict, const typename Dist::value_type& lo, const typename Dist::value_type& hi) { BOOST_MATH_STD_USING - typename Dist::value_type cc = ceil(result); - typename Dist::value_type pp = cc <= support(d).second ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 1; - if(pp == p) - result = cc; + typedef typename Dist::value_type value_type; + constexpr auto function = "boost::math::quantile<%1%>(%1%, %1%)"; + if (k < lo) + k = lo; + if (k > hi) + k = hi; + // Beyond 1/epsilon every value is an integer and k + 1 == k, so there is + // nothing to settle: + if (k + 1 == k) + return k; + // Each evaluation after the first counts against the root finder's + // iteration budget, and running out of it is an error: + BOOST_MATH_NAMESPACE::uintmax_t steps = policies::get_max_root_iterations(); + value_type pass = k, fail = k; // Once both are known, fail < pass. + value_type step = 1; + if ((k == hi) || discrete_quantile_passes(d, k, p, c, strict)) + { + for (;;) + { + if (pass == lo) + return lo; + if (steps-- == 0) + return policies::raise_evaluation_error(function, "Unable to settle the integer result, last value tried was %1%", pass, typename Dist::policy_type()); // LCOV_EXCL_LINE + value_type t = (pass - lo > step) ? value_type(pass - step) : lo; + if (!discrete_quantile_passes(d, t, p, c, strict)) + { + fail = t; + break; + } + pass = t; + step *= 2; + } + } else - result = floor(result); - // - // Now find the smallest integer <= result for which we get an exact root: - // - while(result != 0) { - #ifdef BOOST_MATH_HAS_GPU_SUPPORT - cc = floor(::nextafter(result, -tools::max_value())); - #else - cc = floor(float_prior(result)); - #endif - if(cc < support(d).first) - break; - pp = c ? cdf(complement(d, cc)) : cdf(d, cc); - if(c ? pp > p : pp < p) - break; - result = cc; + for (;;) + { + value_type t = (hi - fail > step) ? value_type(fail + step) : hi; + if (t == hi) + { + pass = t; + break; + } + if (steps-- == 0) + return policies::raise_evaluation_error(function, "Unable to settle the integer result, last value tried was %1%", fail, typename Dist::policy_type()); // LCOV_EXCL_LINE + if (discrete_quantile_passes(d, t, p, c, strict)) + { + pass = t; + break; + } + fail = t; + step *= 2; + } } + while (pass - fail > 1) + { + if (steps-- == 0) + return policies::raise_evaluation_error(function, "Unable to settle the integer result, last value tried was %1%", pass, typename Dist::policy_type()); // LCOV_EXCL_LINE + value_type mid = fail + floor((pass - fail) / 2); + if (discrete_quantile_passes(d, mid, p, c, strict)) + pass = mid; + else + fail = mid; + } + return pass; +} - return result; +// +// Integers only: the last one in the support is floor(support.second), and +// the one after it (where cdf == 1, so the residual is positive unless +// p == 1) bounds the searches. +// +template +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_to_ceil(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c) +{ + BOOST_MATH_STD_USING + typedef typename Dist::value_type value_type; + const value_type lo = ceil(support(d).first); + const value_type hi = floor(support(d).second) + 1; + return first_passing_integer(d, value_type(ceil(result)), p, c, false, lo, hi); } -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4127) -#endif +template +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_to_floor(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c) +{ + BOOST_MATH_STD_USING + typedef typename Dist::value_type value_type; + const value_type lo = ceil(support(d).first); + const value_type hi = floor(support(d).second) + 1; + // One below the first k with cdf(k) > p. If even cdf(lo) > p there is no + // answer, and lo is the best we can do: + const value_type k = first_passing_integer(d, value_type(floor(result) + 1), p, c, true, lo, hi); + return k > lo ? value_type(k - 1) : lo; +} +// +// integer_round_nearest rounds result + 0.5 down, but "nearest" is not a +// statement about the cdf at integers, so it keeps the original logic: +// prefer ceil(result) if it is an exact root, else floor(result), then move +// down to the smallest k with cdf(k) >= p (what round up gives) if that is +// lower. So the answer is the nearest integer, but never above round up's. +// template -BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_to_ceil(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c) +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_to_nearest_floor(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c) { BOOST_MATH_STD_USING - typename Dist::value_type cc = floor(result); - typename Dist::value_type pp = cc >= support(d).first ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 0; - if(pp == p) - result = cc; - else - result = ceil(result); - // - // Now find the largest integer >= result for which we get an exact root: - // - while(true) - { - #ifdef BOOST_MATH_HAS_GPU_SUPPORT - cc = ceil(::nextafter(result, tools::max_value())); - #else - cc = ceil(float_next(result)); - #endif - if(cc > support(d).second) - break; - pp = c ? cdf(complement(d, cc)) : cdf(d, cc); - if(c ? pp < p : pp > p) - break; - result = cc; - } + typedef typename Dist::value_type value_type; + const value_type lo = ceil(support(d).first); + const value_type hi = floor(support(d).second) + 1; + value_type k = floor(result); + if (k < lo) + k = lo; + if (k > hi) + k = hi; + const value_type cc = ceil(result); + if ((cc != k) && (cc >= lo) && (cc <= hi) && (discrete_quantile_residual(d, cc, p, c) == 0)) + return first_passing_integer(d, cc, p, c, false, lo, cc); + if (discrete_quantile_passes(d, k, p, c, false)) + return first_passing_integer(d, k, p, c, false, lo, k); + return k; +} +// +// Rounding for distributions that find their quantile some other way (in +// closed form, or by summing the pdf) and only need the result settled on +// the integer the policy asks for. "result" is the real-valued quantile, +// or an integer within a step or so of the answer. +// +template +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_discrete_quantile(const Dist&, typename Dist::value_type result, typename Dist::value_type, bool, const policies::discrete_quantile&) +{ return result; } -#ifdef _MSC_VER -#pragma warning(pop) -#endif +template +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_discrete_quantile(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c, const policies::discrete_quantile&) +{ + return round_to_ceil(d, result, p, c); +} + +template +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_discrete_quantile(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c, const policies::discrete_quantile&) +{ + return round_to_floor(d, result, p, c); +} + +// +// integer_round_outwards rounds lower quantiles (probability below 0.5) down +// and upper ones up; integer_round_inwards the reverse. Both are a choice of +// one of the other two policies: +// +template +BOOST_MATH_GPU_ENABLED inline bool is_lower_quantile(const T& p, bool c) +{ + return (c ? T(1 - p) : p) < 0.5f; +} + +template +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_discrete_quantile(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c, const policies::discrete_quantile&) +{ + return is_lower_quantile(p, c) + ? round_discrete_quantile(d, result, p, c, policies::discrete_quantile()) + : round_discrete_quantile(d, result, p, c, policies::discrete_quantile()); +} + +template +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_discrete_quantile(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c, const policies::discrete_quantile&) +{ + return is_lower_quantile(p, c) + ? round_discrete_quantile(d, result, p, c, policies::discrete_quantile()) + : round_discrete_quantile(d, result, p, c, policies::discrete_quantile()); +} + +template +BOOST_MATH_GPU_ENABLED inline typename Dist::value_type round_discrete_quantile(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c, const policies::discrete_quantile&) +{ + return round_to_nearest_floor(d, typename Dist::value_type(result + 0.5f), p, c); +} // // Now finally are the public API functions. // There is one overload for each policy, @@ -382,16 +536,15 @@ BOOST_MATH_GPU_ENABLED inline typename Dist::value_type const typename Dist::value_type& multiplier, const typename Dist::value_type& adder, const policies::discrete_quantile&, - boost::math::uintmax_t& max_iter) + BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { if(p > 0.5) { p = 1 - p; c = !c; } - typename Dist::value_type pp = c ? 1 - p : p; - if(pp <= pdf(dist, 0)) - return 0; + if(discrete_quantile_residual(dist, typename Dist::value_type(0), p, c) >= 0) + return 0; // cdf(0) >= p already: see round_to_ceil / round_to_floor. return do_inverse_discrete_quantile( dist, p, @@ -412,37 +565,21 @@ BOOST_MATH_GPU_ENABLED inline typename Dist::value_type const typename Dist::value_type& guess, const typename Dist::value_type& multiplier, const typename Dist::value_type& adder, - const policies::discrete_quantile&, - boost::math::uintmax_t& max_iter) + const policies::discrete_quantile&, + BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { typedef typename Dist::value_type value_type; BOOST_MATH_STD_USING - typename Dist::value_type pp = c ? 1 - p : p; - if(pp <= pdf(dist, 0)) - return 0; - // - // What happens next depends on whether we're looking for an - // upper or lower quantile: - // - if(pp < 0.5f) - return round_to_floor(dist, do_inverse_discrete_quantile( - dist, - p, - c, - (guess < 1 ? value_type(1) : (value_type)floor(guess)), - multiplier, - adder, - tools::equal_floor(), - max_iter), p, c); - // else: - return round_to_ceil(dist, do_inverse_discrete_quantile( + if(discrete_quantile_residual(dist, typename Dist::value_type(0), p, c) >= 0) + return 0; // cdf(0) >= p already: see round_to_ceil / round_to_floor. + return round_to_floor(dist, do_inverse_discrete_quantile( dist, p, c, - (value_type)ceil(guess), + (guess < 1 ? value_type(1) : floor(guess)), multiplier, adder, - tools::equal_ceil(), + tools::equal_floor(), max_iter), p, c); } @@ -455,37 +592,20 @@ BOOST_MATH_GPU_ENABLED inline typename Dist::value_type const typename Dist::value_type& guess, const typename Dist::value_type& multiplier, const typename Dist::value_type& adder, - const policies::discrete_quantile&, - boost::math::uintmax_t& max_iter) + const policies::discrete_quantile&, + BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { - typedef typename Dist::value_type value_type; BOOST_MATH_STD_USING - typename Dist::value_type pp = c ? 1 - p : p; - if(pp <= pdf(dist, 0)) - return 0; - // - // What happens next depends on whether we're looking for an - // upper or lower quantile: - // - if(pp < 0.5f) - return round_to_ceil(dist, do_inverse_discrete_quantile( - dist, - p, - c, - ceil(guess), - multiplier, - adder, - tools::equal_ceil(), - max_iter), p, c); - // else: - return round_to_floor(dist, do_inverse_discrete_quantile( + if(discrete_quantile_residual(dist, typename Dist::value_type(0), p, c) >= 0) + return 0; // cdf(0) >= p already: see round_to_ceil / round_to_floor. + return round_to_ceil(dist, do_inverse_discrete_quantile( dist, p, c, - (guess < 1 ? value_type(1) : floor(guess)), + ceil(guess), multiplier, adder, - tools::equal_floor(), + tools::equal_ceil(), max_iter), p, c); } @@ -498,23 +618,27 @@ BOOST_MATH_GPU_ENABLED inline typename Dist::value_type const typename Dist::value_type& guess, const typename Dist::value_type& multiplier, const typename Dist::value_type& adder, - const policies::discrete_quantile&, - boost::math::uintmax_t& max_iter) + const policies::discrete_quantile&, + BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { typedef typename Dist::value_type value_type; BOOST_MATH_STD_USING - typename Dist::value_type pp = c ? 1 - p : p; - if(pp <= pdf(dist, 0)) - return 0; - return round_to_floor(dist, do_inverse_discrete_quantile( + if(discrete_quantile_residual(dist, typename Dist::value_type(0), p, c) >= 0) + return 0; // cdf(0) >= p already: see round_to_ceil / round_to_floor. + // + // Note that we adjust the guess to the nearest half-integer: + // this increase the chances that we will bracket the root + // with two results that both round to the same integer quickly. + // + return round_to_nearest_floor(dist, do_inverse_discrete_quantile( dist, p, c, - (guess < 1 ? value_type(1) : floor(guess)), + (guess < 0.5f ? value_type(1.5f) : floor(guess + 0.5f) + 0.5f), multiplier, adder, - tools::equal_floor(), - max_iter), p, c); + tools::equal_nearest_integer(), + max_iter) + 0.5f, p, c); } template @@ -526,22 +650,13 @@ BOOST_MATH_GPU_ENABLED inline typename Dist::value_type const typename Dist::value_type& guess, const typename Dist::value_type& multiplier, const typename Dist::value_type& adder, - const policies::discrete_quantile&, - boost::math::uintmax_t& max_iter) + const policies::discrete_quantile&, + BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { - BOOST_MATH_STD_USING - typename Dist::value_type pp = c ? 1 - p : p; - if(pp <= pdf(dist, 0)) - return 0; - return round_to_ceil(dist, do_inverse_discrete_quantile( - dist, - p, - c, - ceil(guess), - multiplier, - adder, - tools::equal_ceil(), - max_iter), p, c); + // The up and down overloads also return 0 when cdf(0) >= p already. + return is_lower_quantile(p, c) + ? inverse_discrete_quantile(dist, p, c, guess, multiplier, adder, policies::discrete_quantile(), max_iter) + : inverse_discrete_quantile(dist, p, c, guess, multiplier, adder, policies::discrete_quantile(), max_iter); } template @@ -553,31 +668,16 @@ BOOST_MATH_GPU_ENABLED inline typename Dist::value_type const typename Dist::value_type& guess, const typename Dist::value_type& multiplier, const typename Dist::value_type& adder, - const policies::discrete_quantile&, - boost::math::uintmax_t& max_iter) + const policies::discrete_quantile&, + BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { - typedef typename Dist::value_type value_type; - BOOST_MATH_STD_USING - typename Dist::value_type pp = c ? 1 - p : p; - if(pp <= pdf(dist, 0)) - return 0; - // - // Note that we adjust the guess to the nearest half-integer: - // this increase the chances that we will bracket the root - // with two results that both round to the same integer quickly. - // - return round_to_floor(dist, do_inverse_discrete_quantile( - dist, - p, - c, - (guess < 0.5f ? value_type(1.5f) : floor(guess + 0.5f) + 0.5f), - multiplier, - adder, - tools::equal_nearest_integer(), - max_iter) + 0.5f, p, c); + // The up and down overloads also return 0 when cdf(0) >= p already. + return is_lower_quantile(p, c) + ? inverse_discrete_quantile(dist, p, c, guess, multiplier, adder, policies::discrete_quantile(), max_iter) + : inverse_discrete_quantile(dist, p, c, guess, multiplier, adder, policies::discrete_quantile(), max_iter); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE diff --git a/include/boost/math/distributions/detail/saddle_point.hpp b/include/boost/math/distributions/detail/saddle_point.hpp new file mode 100644 index 0000000000..867be69714 --- /dev/null +++ b/include/boost/math/distributions/detail/saddle_point.hpp @@ -0,0 +1,165 @@ +// Copyright Nick Thompson, 2026. +// 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) + +#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_SADDLE_POINT_HPP +#define BOOST_MATH_DISTRIBUTIONS_DETAIL_SADDLE_POINT_HPP + +// +// The building blocks of Loader's saddle-point evaluation of discrete densities: +// C. Loader, "Fast and Accurate Computation of Binomial Probabilities", 2000. +// + +#include + +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + +#include +#include +#include +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace detail { + +// ln(n!) minus Stirling's approximation (n + 1/2) ln n - n + ln(2 pi)/2, for n above the point +// where its Bernoulli series converges; that is minimum_argument_for_bernoulli_recursion, with a margin +// because just above it the series can still fail to converge (at n = 6.05 for double). +template +inline bool stirlerr_series_converges(const RealType& n) +{ + return n > 2 * minimum_argument_for_bernoulli_recursion(); +} + +template +inline RealType stirlerr_series(const RealType& n, const Policy& pol) +{ + return bernoulli_stirling_series(n, pol); +} + +// The same for any n > 0. Below the series' range, step down from above it with +// stirlerr(z) = stirlerr(z + 1) + (z + 1/2) log1pmx(1/z) + 1/(2z), +// whose terms are about 1/(12 z^2) and are each formed with an absolute error of about eps/z. +// (Computing ln(n!) - [(n + 1/2) ln n - n + ln(2 pi)/2] directly would cancel, with an absolute +// error of about ln(n!) eps, which grows with the series' threshold and so with the precision.) +template +inline RealType stirlerr(const RealType& n, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (stirlerr_series_converges(n)) + { + return stirlerr_series(n, pol); + } + const RealType target = 2 * minimum_argument_for_bernoulli_recursion(); + int steps = 1; + while (!(n + steps > target)) + { + ++steps; + } + RealType sum = stirlerr_series(RealType(n + steps), pol); + for (int j = steps - 1; j >= 0; --j) + { + const RealType z = n + j; + sum += (z + RealType(0.5)) * BOOST_MATH_NAMESPACE::log1pmx(RealType(1 / z), pol) + 1 / (2 * z); + } + return sum; +} + +// The deviance term k ln(k/mean) + mean - k, for k > 0. +// For |v| < 1/2, with v = (k - mean)/(k + mean), sum its series in v^2, which has no cancellation; +// beyond that, the direct formula loses at most a factor of about 2.5. +template +inline RealType bd0(const RealType& mean, const RealType& k, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (abs(k - mean) < (k + mean) / 2) + { + const RealType v = (k - mean) / (k + mean); + const RealType v2 = v * v; + RealType sum = (k - mean) * v; + RealType term = 2 * k * v; + const BOOST_MATH_NAMESPACE::uintmax_t max_iterations = policies::get_max_series_iterations(); + for (BOOST_MATH_NAMESPACE::uintmax_t i = 1; i <= max_iterations; ++i) + { + term *= v2; + const RealType next = term / (2 * i + 1); + sum += next; + if (abs(next) <= abs(sum) * tools::epsilon()) + { + return sum; + } + } + return policies::raise_evaluation_error("boost::math::detail::bd0<%1%>(%1%, %1%)", + "Series did not converge, best approximation was %1%", sum, pol); + } + return k * log(k / mean) + mean - k; +} + +// bd0 for a mean given as the ratio a / b, as when it is a product of counts over a count: +// v = (k b - a) / (k b + a) and a - k b are formed without first rounding the mean, which +// bd0's sensitivity of |k - mean| to its mean would otherwise amplify. This is exact while +// k b and a are exactly representable, e.g. below 2^53 for double. +template +inline RealType bd0_ratio(const RealType& k, const RealType& a, const RealType& b, const Policy& pol) +{ + BOOST_MATH_STD_USING + const RealType kb = k * b; + const RealType diff = kb - a; + if (abs(diff) < (kb + a) / 2) + { + const RealType v = diff / (kb + a); + const RealType v2 = v * v; + RealType sum = diff / b * v; + RealType term = 2 * k * v; + const BOOST_MATH_NAMESPACE::uintmax_t max_iterations = policies::get_max_series_iterations(); + for (BOOST_MATH_NAMESPACE::uintmax_t i = 1; i <= max_iterations; ++i) + { + term *= v2; + const RealType next = term / (2 * i + 1); + sum += next; + if (abs(next) <= abs(sum) * tools::epsilon()) + { + return sum; + } + } + return policies::raise_evaluation_error("boost::math::detail::bd0_ratio<%1%>(%1%, %1%, %1%)", + "Series did not converge, best approximation was %1%", sum, pol); + } + return k * log(kb / a) - diff / b; +} + +// The logarithm of the binomial density C(n, x) p^x q^(n - x), q = 1 - p, for 0 <= x <= n +// (Loader's dbinom_raw, in logarithms so that products of these can be exponentiated once). +// Its exponent is small near the mode, so near the mode it keeps its accuracy as n grows. +template +inline RealType log_binomial_pdf_saddle_point(const RealType& x, const RealType& n, const RealType& p, const RealType& q, const Policy& pol) +{ + BOOST_MATH_STD_USING + // The degenerate cases, as in R, where the general formulas would divide zero by zero. + if ((p == 0) || (n == 0)) + { + return x == 0 ? RealType(0) : RealType(-tools::max_value()); + } + if (q == 0) + { + return x == n ? RealType(0) : RealType(-tools::max_value()); + } + if (x == 0) + { + return p < RealType(0.1) ? RealType(-bd0(RealType(n * q), n, pol) - n * p) : RealType(n * log(q)); + } + if (x == n) + { + return q < RealType(0.1) ? RealType(-bd0(RealType(n * p), n, pol) - n * q) : RealType(n * log(p)); + } + const RealType lc = stirlerr(n, pol) - stirlerr(x, pol) - stirlerr(RealType(n - x), pol) + - bd0(RealType(n * p), x, pol) - bd0(RealType(n * q), RealType(n - x), pol); + const RealType lf = log(constants::two_pi()) + log(x) + BOOST_MATH_NAMESPACE::log1p(-x / n, pol); + return lc - lf / 2; +} + +} BOOST_MATH_NAMESPACE_END + +#endif // BOOST_MATH_HAS_GPU_SUPPORT + +#endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_SADDLE_POINT_HPP diff --git a/include/boost/math/distributions/empirical_cumulative_distribution_function.hpp b/include/boost/math/distributions/empirical_cumulative_distribution_function.hpp index 0d43db16f2..5df421f98c 100644 --- a/include/boost/math/distributions/empirical_cumulative_distribution_function.hpp +++ b/include/boost/math/distributions/empirical_cumulative_distribution_function.hpp @@ -5,11 +5,13 @@ #ifndef BOOST_MATH_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP #define BOOST_MATH_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include +#endif #include #ifndef BOOST_MATH_STANDALONE @@ -19,7 +21,9 @@ #endif #endif -namespace boost { namespace math{ +#include + +BOOST_MATH_NAMESPACE_BEGIN template class empirical_cumulative_distribution_function { @@ -69,5 +73,5 @@ class empirical_cumulative_distribution_function { RandomAccessContainer m_v; }; -}} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/distributions/exponential.hpp b/include/boost/math/distributions/exponential.hpp index 9d45ac4933..5091ff2062 100644 --- a/include/boost/math/distributions/exponential.hpp +++ b/include/boost/math/distributions/exponential.hpp @@ -26,11 +26,13 @@ #ifndef BOOST_MATH_HAS_NVRTC #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #endif +#endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // @@ -39,7 +41,7 @@ namespace detail{ template BOOST_MATH_GPU_ENABLED inline bool verify_lambda(const char* function, RealType l, RealType* presult, const Policy& pol) { - if((l <= 0) || !(boost::math::isfinite)(l)) + if((l <= 0) || !(BOOST_MATH_NAMESPACE::isfinite)(l)) { *presult = policies::raise_domain_error( function, @@ -52,7 +54,7 @@ BOOST_MATH_GPU_ENABLED inline bool verify_lambda(const char* function, RealType template BOOST_MATH_GPU_ENABLED inline bool verify_exp_x(const char* function, RealType x, RealType* presult, const Policy& pol) { - if((x < 0) || (boost::math::isnan)(x)) + if((x < 0) || (BOOST_MATH_NAMESPACE::isnan)(x)) { *presult = policies::raise_domain_error( function, @@ -64,7 +66,7 @@ BOOST_MATH_GPU_ENABLED inline bool verify_exp_x(const char* function, RealType x } // namespace detail -template > +BOOST_MATH_EXPORT template > class exponential_distribution { public: @@ -84,38 +86,38 @@ class exponential_distribution RealType m_lambda; }; -using exponential = exponential_distribution; +BOOST_MATH_EXPORT using exponential = exponential_distribution; #ifdef __cpp_deduction_guides -template -exponential_distribution(RealType)->exponential_distribution::type>; +BOOST_MATH_EXPORT template +exponential_distribution(RealType)->exponential_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const exponential_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const exponential_distribution& /*dist*/) { // Range of permissible values for random variable x. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(static_cast(0), boost::math::numeric_limits::infinity()); // 0 to + infinity. + return BOOST_MATH_NAMESPACE::pair(static_cast(0), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // 0 to + infinity. } else { - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // 0 to + max + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // 0 to + max } } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const exponential_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const exponential_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - using boost::math::tools::min_value; - return boost::math::pair(min_value(), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::min_value; + return BOOST_MATH_NAMESPACE::pair(min_value(), max_value()); // min_value() to avoid a discontinuity at x = 0. } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const exponential_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -129,13 +131,13 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const exponential_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logpdf(const exponential_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -143,7 +145,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const exponential_distribution::infinity(); + RealType result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); if(0 == detail::verify_lambda(function, lambda, &result, Policy())) return result; if(0 == detail::verify_exp_x(function, x, &result, Policy())) @@ -153,7 +155,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const exponential_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const exponential_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -166,12 +168,12 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const exponential_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const exponential_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -184,12 +186,12 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const exponential_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const exponential_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions @@ -208,11 +210,11 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const exponential_distribution(function, 0, Policy()); - result = -boost::math::log1p(-p, Policy()) / lambda; + result = -BOOST_MATH_NAMESPACE::log1p(-p, Policy()) / lambda; return result; } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -233,7 +235,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -254,7 +256,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -279,7 +281,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const exponential_distribution& dist) { RealType result = 0; @@ -289,7 +291,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const exponential_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const exponential_distribution& dist) { RealType result = 0; @@ -299,46 +301,45 @@ BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const exponential_dist return 1 / lambda; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const exponential_distribution& /*dist*/) { return 0; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const exponential_distribution& dist) { - using boost::math::constants::ln_two; + using BOOST_MATH_NAMESPACE::constants::ln_two; return ln_two() / dist.lambda(); // ln(2) / lambda } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const exponential_distribution& /*dist*/) { return 2; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const exponential_distribution& /*dist*/) { return 9; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const exponential_distribution& /*dist*/) { return 6; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const exponential_distribution& dist) { using std::log; return 1 - log(dist.lambda()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER # pragma warning(pop) diff --git a/include/boost/math/distributions/extreme_value.hpp b/include/boost/math/distributions/extreme_value.hpp index 7049ac6a15..67824ce100 100644 --- a/include/boost/math/distributions/extreme_value.hpp +++ b/include/boost/math/distributions/extreme_value.hpp @@ -28,16 +28,18 @@ #ifndef BOOST_MATH_HAS_NVRTC #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #endif +#endif #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4702) // unreachable code (return after domain_error throw). #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // @@ -46,7 +48,7 @@ namespace detail{ template BOOST_MATH_GPU_ENABLED inline bool verify_scale_b(const char* function, RealType b, RealType* presult, const Policy& pol) { - if((b <= 0) || !(boost::math::isfinite)(b)) + if((b <= 0) || !(BOOST_MATH_NAMESPACE::isfinite)(b)) { *presult = policies::raise_domain_error( function, @@ -58,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline bool verify_scale_b(const char* function, RealType } // namespace detail -template > +BOOST_MATH_EXPORT template > class extreme_value_distribution { public: @@ -81,33 +83,33 @@ class extreme_value_distribution RealType m_b; }; -using extreme_value = extreme_value_distribution; +BOOST_MATH_EXPORT using extreme_value = extreme_value_distribution; #ifdef __cpp_deduction_guides -template -extreme_value_distribution(RealType)->extreme_value_distribution::type>; -template -extreme_value_distribution(RealType,RealType)->extreme_value_distribution::type>; +BOOST_MATH_EXPORT template +extreme_value_distribution(RealType)->extreme_value_distribution::type>; +BOOST_MATH_EXPORT template +extreme_value_distribution(RealType,RealType)->extreme_value_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const extreme_value_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const extreme_value_distribution& /*dist*/) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair( - boost::math::numeric_limits::has_infinity ? -boost::math::numeric_limits::infinity() : -max_value(), - boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair( + BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? -BOOST_MATH_NAMESPACE::numeric_limits::infinity() : -max_value(), + BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : max_value()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const extreme_value_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const extreme_value_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const extreme_value_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -121,7 +123,7 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const extreme_value_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logpdf(const extreme_value_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -141,12 +143,12 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const extreme_value_distribution::infinity(); + RealType result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); if(0 == detail::verify_scale_b(function, b, &result, Policy())) return result; if(0 == detail::check_finite(function, a, &result, Policy())) return result; - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) return 0.0f; if(0 == detail::check_x(function, x, &result, Policy())) return result; @@ -157,14 +159,14 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const extreme_value_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const extreme_value_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions constexpr auto function = "boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)"; - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) return x < 0 ? 0.0f : 1.0f; RealType a = dist.location(); RealType b = dist.scale(); @@ -181,15 +183,13 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const extreme_value_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const extreme_value_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions constexpr auto function = "boost::math::logcdf(const extreme_value_distribution<%1%>&, %1%)"; - if((boost::math::isinf)(x)) - return x < 0 ? 0.0f : 1.0f; RealType a = dist.location(); RealType b = dist.scale(); RealType result = 0; @@ -197,6 +197,9 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const extreme_value_distribution(function, nullptr, Policy()) : RealType(0); if(0 == detail::check_x("boost::math::logcdf(const extreme_value_distribution<%1%>&, %1%)", x, &result, Policy())) return result; @@ -205,7 +208,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const extreme_value_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType quantile(const extreme_value_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions @@ -232,14 +235,14 @@ BOOST_MATH_GPU_ENABLED RealType quantile(const extreme_value_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions constexpr auto function = "boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)"; - if((boost::math::isinf)(c.param)) + if((BOOST_MATH_NAMESPACE::isinf)(c.param)) return c.param < 0 ? 1.0f : 0.0f; RealType a = c.dist.location(); RealType b = c.dist.scale(); @@ -251,20 +254,18 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions constexpr auto function = "boost::math::logcdf(const extreme_value_distribution<%1%>&, %1%)"; - if((boost::math::isinf)(c.param)) - return c.param < 0 ? 1.0f : 0.0f; RealType a = c.dist.location(); RealType b = c.dist.scale(); RealType result = 0; @@ -272,6 +273,9 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type(function, nullptr, Policy()); if(0 == detail::check_x(function, c.param, &result, Policy())) return result; @@ -280,7 +284,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -303,12 +307,12 @@ BOOST_MATH_GPU_ENABLED RealType quantile(const complemented2_type(function, 0, Policy()); - result = a - log(-boost::math::log1p(-q, Policy())) * b; + result = a - log(-BOOST_MATH_NAMESPACE::log1p(-q, Policy())) * b; return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const extreme_value_distribution& dist) { RealType a = dist.location(); @@ -321,7 +325,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const extreme_value_distribution() * b; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const extreme_value_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions. @@ -335,20 +339,20 @@ BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const extreme_value_di return constants::pi() * b / sqrt(static_cast(6)); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const extreme_value_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const extreme_value_distribution& dist) { using constants::ln_ln_two; return dist.location() - dist.scale() * ln_ln_two(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const extreme_value_distribution& /*dist*/) { // @@ -358,14 +362,14 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const extreme_value_distribution return static_cast(1.1395470994046486574927930193898461120875997958366L); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const extreme_value_distribution& /*dist*/) { // See http://mathworld.wolfram.com/ExtremeValueDistribution.html return RealType(27) / 5; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const extreme_value_distribution& /*dist*/) { // See http://mathworld.wolfram.com/ExtremeValueDistribution.html @@ -373,8 +377,14 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const extreme_value_distr } -} // namespace math -} // namespace boost +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType entropy(const extreme_value_distribution& dist) +{ + BOOST_MATH_STD_USING + return log(dist.scale()) + constants::euler() + 1; +} + +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER # pragma warning(pop) diff --git a/include/boost/math/distributions/find_location.hpp b/include/boost/math/distributions/find_location.hpp index c23b41eb10..e9a68043dc 100644 --- a/include/boost/math/distributions/find_location.hpp +++ b/include/boost/math/distributions/find_location.hpp @@ -19,16 +19,13 @@ // using boost::math::complement; // will be needed by users who want complement, // but NOT placed here to avoid putting it in global scope. -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN // Function to find location of random variable z // to give probability p (given scale) // Applies to normal, lognormal, extreme value, Cauchy, (and symmetrical triangular), // enforced by static_assert below. - template + BOOST_MATH_EXPORT template inline typename Dist::value_type find_location( // For example, normal mean. typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. @@ -38,22 +35,22 @@ namespace boost const Policy& pol ) { - static_assert(::boost::math::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); - static_assert(::boost::math::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); + static_assert(::BOOST_MATH_NAMESPACE::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); + static_assert(::BOOST_MATH_NAMESPACE::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); static const char* function = "boost::math::find_location&, %1%)"; - if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(p) || (p < 0) || (p > 1)) { return policies::raise_domain_error( function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, pol); } - if(!(boost::math::isfinite)(z)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(z)) { return policies::raise_domain_error( function, "z parameter was %1%, but must be finite!", z, pol); } typename Dist::value_type result; - if(!(boost::math::detail::check_scale)(function, scale, &result, pol)) + if(!(BOOST_MATH_NAMESPACE::detail::check_scale)(function, scale, &result, pol)) { return result; } @@ -63,7 +60,7 @@ namespace boost return z - (quantile(Dist(), p) * scale); } // find_location - template + BOOST_MATH_EXPORT template inline // with default policy. typename Dist::value_type find_location( // For example, normal mean. typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. @@ -77,27 +74,27 @@ namespace boost // So the user can start from the complement q = (1 - p) of the probability p, // for example, l = find_location(complement(z, q, sd)); - template + BOOST_MATH_EXPORT template inline typename Dist::value_type find_location( // Default policy. complemented3_type const& c) { static const char* function = "boost::math::find_location&, %1%)"; typename Dist::value_type p = c.param1; - if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(p) || (p < 0) || (p > 1)) { return policies::raise_domain_error( function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, policies::policy<>()); } typename Dist::value_type z = c.dist; - if(!(boost::math::isfinite)(z)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(z)) { return policies::raise_domain_error( function, "z parameter was %1%, but must be finite!", z, policies::policy<>()); } typename Dist::value_type result; typename Dist::value_type scale = c.param2; - if(!(boost::math::detail::check_scale)(function, scale, &result, policies::policy<>())) + if(!(BOOST_MATH_NAMESPACE::detail::check_scale)(function, scale, &result, policies::policy<>())) { return result; } @@ -106,27 +103,27 @@ namespace boost } // find_location complement - template + BOOST_MATH_EXPORT template inline typename Dist::value_type find_location( // Explicit policy. complemented4_type const& c) { static const char* function = "boost::math::find_location&, %1%)"; typename Dist::value_type p = c.param1; - if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(p) || (p < 0) || (p > 1)) { return policies::raise_domain_error( function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, c.param3); } typename Dist::value_type z = c.dist; - if(!(boost::math::isfinite)(z)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(z)) { return policies::raise_domain_error( function, "z parameter was %1%, but must be finite!", z, c.param3); } typename Dist::value_type result; typename Dist::value_type scale = c.param2; - if(!(boost::math::detail::check_scale)(function, scale, &result, c.param3)) + if(!(BOOST_MATH_NAMESPACE::detail::check_scale)(function, scale, &result, c.param3)) { return result; } @@ -134,8 +131,7 @@ namespace boost return z - quantile(Dist(), p) * scale; } // find_location complement - } // namespace boost -} // namespace math + BOOST_MATH_NAMESPACE_END #endif // BOOST_STATS_FIND_LOCATION_HPP diff --git a/include/boost/math/distributions/find_scale.hpp b/include/boost/math/distributions/find_scale.hpp index cd08ce95a2..7feda38368 100644 --- a/include/boost/math/distributions/find_scale.hpp +++ b/include/boost/math/distributions/find_scale.hpp @@ -19,17 +19,14 @@ // using boost::math::complement; // will be needed by users who want complement, // but NOT placed here to avoid putting it in global scope. -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN // Function to find location of random variable z // to give probability p (given scale) // Applies to normal, lognormal, extreme value, Cauchy, (and symmetrical triangular), // distributions that have scale. // BOOST_STATIC_ASSERTs, see below, are used to enforce this. - template + BOOST_MATH_EXPORT template inline typename Dist::value_type find_scale( // For example, normal mean. typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. @@ -39,29 +36,29 @@ namespace boost const Policy& pol ) { - static_assert(::boost::math::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); - static_assert(::boost::math::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); + static_assert(::BOOST_MATH_NAMESPACE::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); + static_assert(::BOOST_MATH_NAMESPACE::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); static const char* function = "boost::math::find_scale(%1%, %1%, %1%, Policy)"; - if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(p) || (p < 0) || (p > 1)) { return policies::raise_domain_error( function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, pol); } - if(!(boost::math::isfinite)(z)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(z)) { return policies::raise_domain_error( function, "find_scale z parameter was %1%, but must be finite!", z, pol); } - if(!(boost::math::isfinite)(location)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(location)) { return policies::raise_domain_error( function, "find_scale location parameter was %1%, but must be finite!", location, pol); } //cout << "z " << z << ", p " << p << ", quantile(Dist(), p) " - //<< quantile(Dist(), p) << ", z - mean " << z - location - //<<", sd " << (z - location) / quantile(Dist(), p) << endl; + // << quantile(Dist(), p) << ", z - mean " << z - location + // <<", sd " << (z - location) / quantile(Dist(), p) << endl; //quantile(N01, 0.001) -3.09023 //quantile(N01, 0.01) -2.32635 @@ -85,7 +82,7 @@ namespace boost return result; } // template find_scale - template + BOOST_MATH_EXPORT template inline // with default policy. typename Dist::value_type find_scale( // For example, normal mean. typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. @@ -96,7 +93,7 @@ namespace boost return (find_scale(z, p, location, policies::policy<>())); } // find_scale - template + BOOST_MATH_EXPORT template inline typename Dist::value_type find_scale( complemented4_type const& c) { @@ -107,26 +104,26 @@ namespace boost // << quantile(Dist(), c.param1) //q // << endl; - static_assert(::boost::math::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); - static_assert(::boost::math::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); + static_assert(::BOOST_MATH_NAMESPACE::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); + static_assert(::BOOST_MATH_NAMESPACE::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); static const char* function = "boost::math::find_scale(complement(%1%, %1%, %1%, Policy))"; // Checks on arguments, as not complemented version, // Explicit policy. typename Dist::value_type q = c.param1; - if(!(boost::math::isfinite)(q) || (q < 0) || (q > 1)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(q) || (q < 0) || (q > 1)) { return policies::raise_domain_error( function, "Probability parameter was %1%, but must be >= 0 and <= 1!", q, c.param3); } typename Dist::value_type z = c.dist; - if(!(boost::math::isfinite)(z)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(z)) { return policies::raise_domain_error( function, "find_scale z parameter was %1%, but must be finite!", z, c.param3); } typename Dist::value_type location = c.param2; - if(!(boost::math::isfinite)(location)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(location)) { return policies::raise_domain_error( function, "find_scale location parameter was %1%, but must be finite!", location, c.param3); @@ -146,7 +143,7 @@ namespace boost // So the user can start from the complement q = (1 - p) of the probability p, // for example, s = find_scale(complement(z, q, l)); - template + BOOST_MATH_EXPORT template inline typename Dist::value_type find_scale( complemented3_type const& c) { @@ -157,26 +154,26 @@ namespace boost // << quantile(Dist(), c.param1) //q // << endl; - static_assert(::boost::math::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); - static_assert(::boost::math::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); + static_assert(::BOOST_MATH_NAMESPACE::tools::is_distribution::value, "The provided distribution does not meet the conceptual requirements of a distribution."); + static_assert(::BOOST_MATH_NAMESPACE::tools::is_scaled_distribution::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); static const char* function = "boost::math::find_scale(complement(%1%, %1%, %1%, Policy))"; // Checks on arguments, as not complemented version, // default policy policies::policy<>(). typename Dist::value_type q = c.param1; - if(!(boost::math::isfinite)(q) || (q < 0) || (q > 1)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(q) || (q < 0) || (q > 1)) { return policies::raise_domain_error( function, "Probability parameter was %1%, but must be >= 0 and <= 1!", q, policies::policy<>()); } typename Dist::value_type z = c.dist; - if(!(boost::math::isfinite)(z)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(z)) { return policies::raise_domain_error( function, "find_scale z parameter was %1%, but must be finite!", z, policies::policy<>()); } typename Dist::value_type location = c.param2; - if(!(boost::math::isfinite)(location)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(location)) { return policies::raise_domain_error( function, "find_scale location parameter was %1%, but must be finite!", location, policies::policy<>()); @@ -194,7 +191,6 @@ namespace boost return result; } // template typename Dist::value_type find_scale - } // namespace boost -} // namespace math + BOOST_MATH_NAMESPACE_END #endif // BOOST_STATS_FIND_SCALE_HPP diff --git a/include/boost/math/distributions/fisher_f.hpp b/include/boost/math/distributions/fisher_f.hpp index 56b288d88e..0990b316aa 100644 --- a/include/boost/math/distributions/fisher_f.hpp +++ b/include/boost/math/distributions/fisher_f.hpp @@ -14,12 +14,144 @@ #include #include // for incomplete beta. #include // complements +#include #include // error checks #include -namespace boost{ namespace math{ +#ifndef BOOST_MATH_HAS_NVRTC +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN + namespace detail{ + template + struct fisher_degrees_of_freedom_finder + { + fisher_degrees_of_freedom_finder( + RealType x_, RealType v_, bool find_v1_, RealType p_, bool c) + : x(x_), v(v_), find_v1(find_v1_), p(p_), comp(c) {} + + RealType operator()(const RealType& input_v) + { + RealType v1 = find_v1 ? input_v : v; + RealType v2 = find_v1 ? v : input_v; + fisher_f_distribution d(v1, v2); + return comp ? + p - cdf(complement(d, x)) + : cdf(d, x) - p; + } + private: + RealType x; + RealType v; + bool find_v1; + RealType p; + bool comp; + }; + + template + RealType fisher_large_v1_approximation(RealType x, RealType v, RealType p, RealType q) + { // For v1 -> inf approximate f_degreese_of_freedom_finder with chi squared distribution + // with degrees of freedom v2 at the cdf at v2 / x + bool comp = p < q ? false : true; + RealType pval = p < q ? p : q; + chi_squared_distribution d(v); + return comp ? pval - cdf(d, v / x) : cdf(complement(d, v / x)) - pval; + } + + template + RealType fisher_large_v2_approximation(RealType x, RealType v, RealType p, RealType q) + { // For v2 -> inf approximate f_degrees_of_freedom_finder with chi squared distribution + // with degrees of freedom v1 at the cdf at x * v1 + bool comp = p < q ? false : true; + RealType pval = p < q ? p : q; + chi_squared_distribution d(v); + return comp ? pval - cdf(complement(d, v * x)) : cdf(d, v * x) - pval; + } + + template + RealType fisher_small_v1_approximation(RealType p, RealType q) + { // For v1 -> 0, chi-squared(v1) collapses to a point mass at 0, so cdf(x) -> 1 for any x > 0. + bool comp = p < q ? false : true; + RealType pval = p < q ? p : q; + return comp ? pval : 1 - pval; + } + + template + RealType fisher_small_v2_approximation(RealType p, RealType q) + { // For v2 -> 0, F diverges to infinity a.s., so cdf(x) -> 0 for any finite x. + bool comp = p < q ? false : true; + RealType pval = p < q ? p : q; + return comp ? pval - 1 : -pval; + } + + template + inline RealType find_degrees_of_freedom_fisher_f( + const RealType x, const RealType v, const bool find_v1, const RealType p, const RealType q, const Policy& pol) + { + BOOST_MATH_STD_USING + using std::fabs; + const char* function = "fisher_f_distribution<%1%>::find_degrees_of_freedom_f"; + if((p == 0) || (q == 0)) + { + // + // Can't find a thing if one of p and q is zero: + // + return policies::raise_domain_error(function, "Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%", + RealType(std::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE + } + if (x < tools::epsilon()) + { + return policies::raise_evaluation_error(function, "Can't find degrees of freedom when the abscissa value is very close to zero as all degrees of freedom generate the same CDF at x=0: try again further out in the tails!!", + RealType(std::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE + } + fisher_degrees_of_freedom_finder f(x, v, find_v1, p < q ? p : q, p < q ? false : true); + + // There are times when f has two roots - thus, two degrees of freedom can + // be found. We find this case by checking if the sign of f for large and + // small values of v have the same sign. If the sign is the same, then there + // are an even number of roots. If the signs differ, there is only one root + // and we can safely find the root. + + // Rather than evaluating f at an enormous or minuscule degrees of freedom, use its + // limits. As v1 -> infinity, F tends to v2 / chi-squared(v2); as v2 -> infinity, F + // tends to chi-squared(v1) / v1. As v1 -> 0, F collapses to a point mass at 0, so + // cdf(x) -> 1; as v2 -> 0, F diverges to infinity almost surely, so cdf(x) -> 0. + RealType large_difference; + if (find_v1) + { + large_difference = fisher_large_v1_approximation(x, v, p, q); + } + else + large_difference = fisher_large_v2_approximation(x, v, p, q); + + RealType small_difference = find_v1 + ? fisher_small_v1_approximation(p, q) + : fisher_small_v2_approximation(p, q); + + if ((large_difference < 0) == (small_difference < 0)){ + return policies::raise_evaluation_error(function, "Can't find degrees of freedom because two degrees of freedom can be found using the given parameters", + RealType(std::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE + } + + tools::eps_tolerance tol(policies::digits()); + std::uintmax_t max_iter = policies::get_max_root_iterations(); + // + // Pick an initial guess: + // + RealType guess = 1; + std::pair ir = tools::bracket_and_solve_root( + f, guess, RealType(2), f(guess) < 0 ? true : false, tol, max_iter, pol); + RealType result = ir.first + (ir.second - ir.first) / 2; + if(max_iter >= policies::get_max_root_iterations()) + { + return policies::raise_evaluation_error(function, "Unable to locate solution in a reasonable time:" // LCOV_EXCL_LINE + " or there is no answer to problem. Current best guess is %1%", result, Policy()); // LCOV_EXCL_LINE + } + return result; + } + } -template > +BOOST_MATH_EXPORT template > class fisher_f_distribution { public: @@ -44,7 +176,92 @@ class fisher_f_distribution { return m_df2; } - + BOOST_MATH_GPU_ENABLED static RealType find_v1(const RealType x, const RealType v2, const RealType p) + { + constexpr auto function = "fisher_f_distribution<%1%>::find_v1"; + typedef typename policies::evaluation::type eval_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + eval_type result = detail::find_degrees_of_freedom_fisher_f( + static_cast(x), + static_cast(v2), + true, + static_cast(p), + static_cast(1-p), + forwarding_policy()); + return policies::checked_narrowing_cast( + result, + function); + } + template + BOOST_MATH_GPU_ENABLED static RealType find_v1(const complemented3_type& c) + { + constexpr auto function = "fisher_f_distribution<%1%>::find_v1"; + typedef typename policies::evaluation::type eval_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + eval_type result = detail::find_degrees_of_freedom_fisher_f( + static_cast(c.dist), + static_cast(c.param1), + true, + static_cast(1-c.param2), + static_cast(c.param2), + forwarding_policy()); + return policies::checked_narrowing_cast( + result, + function); + } + BOOST_MATH_GPU_ENABLED static RealType find_v2(const RealType x, const RealType v2, const RealType p) + { + constexpr auto function = "fisher_f_distribution<%1%>::find_v2"; + typedef typename policies::evaluation::type eval_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + eval_type result = detail::find_degrees_of_freedom_fisher_f( + static_cast(x), + static_cast(v2), + false, + static_cast(p), + static_cast(1-p), + forwarding_policy()); + return policies::checked_narrowing_cast( + result, + function); + } + template + BOOST_MATH_GPU_ENABLED static RealType find_v2(const complemented3_type& c) + { + constexpr auto function = "fisher_f_distribution<%1%>::find_v2"; + typedef typename policies::evaluation::type eval_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + eval_type result = detail::find_degrees_of_freedom_fisher_f( + static_cast(c.dist), + static_cast(c.param1), + false, + static_cast(1-c.param2), + static_cast(c.param2), + forwarding_policy()); + return policies::checked_narrowing_cast( + result, + function); + } private: // // Data members: @@ -53,29 +270,29 @@ class fisher_f_distribution RealType m_df2; // degrees of freedom are a real number. }; -typedef fisher_f_distribution fisher_f; +BOOST_MATH_EXPORT typedef fisher_f_distribution fisher_f; #ifdef __cpp_deduction_guides -template -fisher_f_distribution(RealType,RealType)->fisher_f_distribution::type>; +BOOST_MATH_EXPORT template +fisher_f_distribution(RealType,RealType)->fisher_f_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const fisher_f_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const fisher_f_distribution& /*dist*/) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const fisher_f_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const fisher_f_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType pdf(const fisher_f_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -90,7 +307,7 @@ BOOST_MATH_GPU_ENABLED RealType pdf(const fisher_f_distribution( function, "Random variable parameter was %1%, but must be > 0 !", x, Policy()); @@ -132,7 +349,7 @@ BOOST_MATH_GPU_ENABLED RealType pdf(const fisher_f_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const fisher_f_distribution& dist, const RealType& x) { constexpr auto function = "boost::math::cdf(fisher_f_distribution<%1%> const&, %1%)"; @@ -146,7 +363,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const fisher_f_distribution( function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy()); @@ -163,11 +380,11 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const fisher_f_distribution df2 - ? boost::math::ibetac(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy()) - : boost::math::ibeta(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy()); + ? BOOST_MATH_NAMESPACE::ibetac(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy()) + : BOOST_MATH_NAMESPACE::ibeta(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy()); } // cdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const fisher_f_distribution& dist, const RealType& p) { constexpr auto function = "boost::math::quantile(fisher_f_distribution<%1%> const&, %1%)"; @@ -187,12 +404,12 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const fisher_f_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { constexpr auto function = "boost::math::cdf(fisher_f_distribution<%1%> const&, %1%)"; @@ -207,7 +424,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type( function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy()); @@ -224,11 +441,55 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type df2 - ? boost::math::ibeta(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy()) - : boost::math::ibetac(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy()); + ? BOOST_MATH_NAMESPACE::ibeta(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy()) + : BOOST_MATH_NAMESPACE::ibetac(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy()); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const fisher_f_distribution& dist, const RealType& x) +{ + constexpr auto function = "boost::math::logcdf(fisher_f_distribution<%1%> const&, %1%)"; + RealType df1 = dist.degrees_of_freedom1(); + RealType df2 = dist.degrees_of_freedom2(); + RealType error_result = 0; + if(false == (detail::check_df(function, df1, &error_result, Policy()) + && detail::check_df(function, df2, &error_result, Policy()))) + return error_result; + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) + { + return policies::raise_domain_error( + function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy()); + } + // As in cdf, keep the incomplete beta's argument away from 1: + RealType v1x = df1 * x; + return v1x > df2 + ? BOOST_MATH_NAMESPACE::libetac(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy()) + : BOOST_MATH_NAMESPACE::libeta(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy()); } -template +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) +{ + constexpr auto function = "boost::math::logcdf(fisher_f_distribution<%1%> const&, %1%)"; + RealType df1 = c.dist.degrees_of_freedom1(); + RealType df2 = c.dist.degrees_of_freedom2(); + RealType x = c.param; + RealType error_result = 0; + if(false == (detail::check_df(function, df1, &error_result, Policy()) + && detail::check_df(function, df2, &error_result, Policy()))) + return error_result; + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) + { + return policies::raise_domain_error( + function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy()); + } + RealType v1x = df1 * x; + return v1x > df2 + ? BOOST_MATH_NAMESPACE::libeta(df2 / 2, df1 / 2, df2 / (df2 + v1x), Policy()) + : BOOST_MATH_NAMESPACE::libetac(df1 / 2, df2 / 2, v1x / (df2 + v1x), Policy()); +} + +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { constexpr auto function = "boost::math::quantile(fisher_f_distribution<%1%> const&, %1%)"; @@ -247,12 +508,12 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const fisher_f_distribution& dist) { // Mean of F distribution = v. constexpr auto function = "boost::math::mean(fisher_f_distribution<%1%> const&)"; @@ -273,7 +534,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const fisher_f_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const fisher_f_distribution& dist) { // Variance of F distribution. constexpr auto function = "boost::math::variance(fisher_f_distribution<%1%> const&)"; @@ -294,7 +555,7 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const fisher_f_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const fisher_f_distribution& dist) { constexpr auto function = "boost::math::mode(fisher_f_distribution<%1%> const&)"; @@ -323,7 +584,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mode(const fisher_f_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const fisher_f_distribution& dist) { constexpr auto function = "boost::math::skewness(fisher_f_distribution<%1%> const&)"; @@ -346,16 +607,16 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const fisher_f_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType kurtosis_excess(const fisher_f_distribution& dist); -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const fisher_f_distribution& dist) { return 3 + kurtosis_excess(dist); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const fisher_f_distribution& dist) { constexpr auto function = "boost::math::kurtosis_excess(fisher_f_distribution<%1%> const&)"; @@ -382,8 +643,56 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const fisher_f_distributi return n / d; } -} // namespace math -} // namespace boost +#ifndef BOOST_MATH_HAS_NVRTC +// Not GPU enabled: the Stirling series use Bernoulli numbers. +BOOST_MATH_EXPORT template +inline RealType entropy(const fisher_f_distribution& dist) +{ + BOOST_MATH_STD_USING + // With a = df1/2, b = df2/2 and s = a + b, + // H = log(b/a) + lgamma(a) + lgamma(b) - lgamma(s) - (a - 1) digamma(a) - (b + 1) digamma(b) + s digamma(s). + // Its terms are ~s log(s) while H ~ -log(s)/2, so every parameter at or above the threshold has + // lgamma and digamma replaced by their Stirling forms, with the logs combined exactly + // (r and nu as in detail::entropy_stirling_series). + RealType a = dist.degrees_of_freedom1() / 2; + RealType b = dist.degrees_of_freedom2() / 2; + RealType s = a + b; + const RealType threshold = detail::entropy_series_threshold(); + RealType r_s, nu_s; + if (s >= threshold) + detail::entropy_stirling_series(s, r_s, nu_s, Policy()); + if ((a >= threshold) && (b >= threshold)) + { + RealType r_a, nu_a, r_b, nu_b; + detail::entropy_stirling_series(a, r_a, nu_a, Policy()); + detail::entropy_stirling_series(b, r_b, nu_b, Policy()); + return constants::log_root_two_pi() + constants::half() + log(1 / a + 1 / b) / 2 + - 1 / (2 * a) + 1 / (2 * b) + r_a + r_b - r_s + 2 * nu_b - nu_s; + } + if (b >= threshold) + { + RealType r_b, nu_b; + detail::entropy_stirling_series(b, r_b, nu_b, Policy()); + return BOOST_MATH_NAMESPACE::log1p(a / b, Policy()) / 2 + a + 1 / (2 * b) + r_b + 2 * nu_b - r_s - nu_s + - log(a) + BOOST_MATH_NAMESPACE::lgamma(a, Policy()) - (a - 1) * BOOST_MATH_NAMESPACE::digamma(a, Policy()); + } + if (a >= threshold) + { + RealType r_a, nu_a; + detail::entropy_stirling_series(a, r_a, nu_a, Policy()); + return BOOST_MATH_NAMESPACE::log1p(b / a, Policy()) / 2 + b - 1 / (2 * a) + r_a - r_s - nu_s + + log(b) + BOOST_MATH_NAMESPACE::lgamma(b, Policy()) - (b + 1) * BOOST_MATH_NAMESPACE::digamma(b, Policy()); + } + // Both small: -lgamma(s) + s digamma(s) = log(s)/2 + s - log(2 pi e)/2 - r(s) - nu(s) for large s. + RealType s_part = (s >= threshold) + ? RealType(log(s) / 2 + s - constants::log_root_two_pi() - constants::half() - r_s - nu_s) + : RealType(s * BOOST_MATH_NAMESPACE::digamma(s, Policy()) - BOOST_MATH_NAMESPACE::lgamma(s, Policy())); + return log(b / a) + BOOST_MATH_NAMESPACE::lgamma(a, Policy()) - (a - 1) * BOOST_MATH_NAMESPACE::digamma(a, Policy()) + + BOOST_MATH_NAMESPACE::lgamma(b, Policy()) - (b + 1) * BOOST_MATH_NAMESPACE::digamma(b, Policy()) + s_part; +} +#endif + +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/fwd.hpp b/include/boost/math/distributions/fwd.hpp index c231be418d..0be403a763 100644 --- a/include/boost/math/distributions/fwd.hpp +++ b/include/boost/math/distributions/fwd.hpp @@ -11,161 +11,171 @@ #ifndef BOOST_MATH_DISTRIBUTIONS_FWD_HPP #define BOOST_MATH_DISTRIBUTIONS_FWD_HPP -namespace boost{ namespace math{ +#include -template +BOOST_MATH_NAMESPACE_BEGIN + +BOOST_MATH_EXPORT template class arcsine_distribution; -template +BOOST_MATH_EXPORT template class bernoulli_distribution; -template +BOOST_MATH_EXPORT template class beta_distribution; -template +BOOST_MATH_EXPORT template class binomial_distribution; -template +BOOST_MATH_EXPORT template class cauchy_distribution; -template +BOOST_MATH_EXPORT template class chi_squared_distribution; -template +BOOST_MATH_EXPORT template class exponential_distribution; -template +BOOST_MATH_EXPORT template class extreme_value_distribution; -template +BOOST_MATH_EXPORT template class fisher_f_distribution; -template +BOOST_MATH_EXPORT template +class generalized_extreme_value_distribution; + +BOOST_MATH_EXPORT template class gamma_distribution; -template +BOOST_MATH_EXPORT template class geometric_distribution; -template +BOOST_MATH_EXPORT template class hyperexponential_distribution; -template +BOOST_MATH_EXPORT template class hypergeometric_distribution; -template +BOOST_MATH_EXPORT template class inverse_chi_squared_distribution; -template +BOOST_MATH_EXPORT template class inverse_gamma_distribution; -template +BOOST_MATH_EXPORT template class inverse_gaussian_distribution; -template +BOOST_MATH_EXPORT template class kolmogorov_smirnov_distribution; -template +BOOST_MATH_EXPORT template class landau_distribution; -template +BOOST_MATH_EXPORT template class mapairy_distribution; -template +BOOST_MATH_EXPORT template class holtsmark_distribution; -template +BOOST_MATH_EXPORT template class saspoint5_distribution; -template +BOOST_MATH_EXPORT template class laplace_distribution; -template +BOOST_MATH_EXPORT template class logistic_distribution; -template +BOOST_MATH_EXPORT template class lognormal_distribution; -template +BOOST_MATH_EXPORT template class negative_binomial_distribution; -template +BOOST_MATH_EXPORT template class non_central_beta_distribution; -template +BOOST_MATH_EXPORT template class non_central_chi_squared_distribution; -template +BOOST_MATH_EXPORT template class non_central_f_distribution; -template +BOOST_MATH_EXPORT template class non_central_t_distribution; -template +BOOST_MATH_EXPORT template class normal_distribution; -template +BOOST_MATH_EXPORT template class pareto_distribution; -template +BOOST_MATH_EXPORT template class poisson_distribution; -template +BOOST_MATH_EXPORT template class rayleigh_distribution; -template +BOOST_MATH_EXPORT template class skew_normal_distribution; -template +BOOST_MATH_EXPORT template class students_t_distribution; -template +BOOST_MATH_EXPORT template class triangular_distribution; -template +BOOST_MATH_EXPORT template class uniform_distribution; -template +BOOST_MATH_EXPORT template class weibull_distribution; -}} // namespaces +BOOST_MATH_EXPORT template +class von_mises_distribution; + +BOOST_MATH_NAMESPACE_END #define BOOST_MATH_DECLARE_DISTRIBUTIONS(Type, Policy)\ - typedef boost::math::arcsine_distribution arcsine;\ - typedef boost::math::bernoulli_distribution bernoulli;\ - typedef boost::math::beta_distribution beta;\ - typedef boost::math::binomial_distribution binomial;\ - typedef boost::math::cauchy_distribution cauchy;\ - typedef boost::math::chi_squared_distribution chi_squared;\ - typedef boost::math::exponential_distribution exponential;\ - typedef boost::math::extreme_value_distribution extreme_value;\ - typedef boost::math::fisher_f_distribution fisher_f;\ - typedef boost::math::gamma_distribution gamma;\ - typedef boost::math::geometric_distribution geometric;\ - typedef boost::math::hypergeometric_distribution hypergeometric;\ - typedef boost::math::kolmogorov_smirnov_distribution kolmogorov_smirnov;\ - typedef boost::math::inverse_chi_squared_distribution inverse_chi_squared;\ - typedef boost::math::inverse_gaussian_distribution inverse_gaussian;\ - typedef boost::math::inverse_gamma_distribution inverse_gamma;\ - typedef boost::math::landau_distribution landau;\ - typedef boost::math::mapairy_distribution mapairy;\ - typedef boost::math::holtsmark_distribution holtsmark;\ - typedef boost::math::saspoint5_distribution saspoint5;\ - typedef boost::math::laplace_distribution laplace;\ - typedef boost::math::logistic_distribution logistic;\ - typedef boost::math::lognormal_distribution lognormal;\ - typedef boost::math::negative_binomial_distribution negative_binomial;\ - typedef boost::math::non_central_beta_distribution non_central_beta;\ - typedef boost::math::non_central_chi_squared_distribution non_central_chi_squared;\ - typedef boost::math::non_central_f_distribution non_central_f;\ - typedef boost::math::non_central_t_distribution non_central_t;\ - typedef boost::math::normal_distribution normal;\ - typedef boost::math::pareto_distribution pareto;\ - typedef boost::math::poisson_distribution poisson;\ - typedef boost::math::rayleigh_distribution rayleigh;\ - typedef boost::math::skew_normal_distribution skew_normal;\ - typedef boost::math::students_t_distribution students_t;\ - typedef boost::math::triangular_distribution triangular;\ - typedef boost::math::uniform_distribution uniform;\ - typedef boost::math::weibull_distribution weibull; + typedef BOOST_MATH_NAMESPACE::arcsine_distribution arcsine;\ + typedef BOOST_MATH_NAMESPACE::bernoulli_distribution bernoulli;\ + typedef BOOST_MATH_NAMESPACE::beta_distribution beta;\ + typedef BOOST_MATH_NAMESPACE::binomial_distribution binomial;\ + typedef BOOST_MATH_NAMESPACE::cauchy_distribution cauchy;\ + typedef BOOST_MATH_NAMESPACE::chi_squared_distribution chi_squared;\ + typedef BOOST_MATH_NAMESPACE::exponential_distribution exponential;\ + typedef BOOST_MATH_NAMESPACE::extreme_value_distribution extreme_value;\ + typedef BOOST_MATH_NAMESPACE::fisher_f_distribution fisher_f;\ + typedef BOOST_MATH_NAMESPACE::gamma_distribution gamma;\ + typedef BOOST_MATH_NAMESPACE::generalized_extreme_value_distribution generalized_extreme_value;\ + typedef BOOST_MATH_NAMESPACE::geometric_distribution geometric;\ + typedef BOOST_MATH_NAMESPACE::hypergeometric_distribution hypergeometric;\ + typedef BOOST_MATH_NAMESPACE::kolmogorov_smirnov_distribution kolmogorov_smirnov;\ + typedef BOOST_MATH_NAMESPACE::inverse_chi_squared_distribution inverse_chi_squared;\ + typedef BOOST_MATH_NAMESPACE::inverse_gaussian_distribution inverse_gaussian;\ + typedef BOOST_MATH_NAMESPACE::inverse_gamma_distribution inverse_gamma;\ + typedef BOOST_MATH_NAMESPACE::landau_distribution landau;\ + typedef BOOST_MATH_NAMESPACE::mapairy_distribution mapairy;\ + typedef BOOST_MATH_NAMESPACE::holtsmark_distribution holtsmark;\ + typedef BOOST_MATH_NAMESPACE::saspoint5_distribution saspoint5;\ + typedef BOOST_MATH_NAMESPACE::laplace_distribution laplace;\ + typedef BOOST_MATH_NAMESPACE::logistic_distribution logistic;\ + typedef BOOST_MATH_NAMESPACE::lognormal_distribution lognormal;\ + typedef BOOST_MATH_NAMESPACE::negative_binomial_distribution negative_binomial;\ + typedef BOOST_MATH_NAMESPACE::non_central_beta_distribution non_central_beta;\ + typedef BOOST_MATH_NAMESPACE::non_central_chi_squared_distribution non_central_chi_squared;\ + typedef BOOST_MATH_NAMESPACE::non_central_f_distribution non_central_f;\ + typedef BOOST_MATH_NAMESPACE::non_central_t_distribution non_central_t;\ + typedef BOOST_MATH_NAMESPACE::normal_distribution normal;\ + typedef BOOST_MATH_NAMESPACE::pareto_distribution pareto;\ + typedef BOOST_MATH_NAMESPACE::poisson_distribution poisson;\ + typedef BOOST_MATH_NAMESPACE::rayleigh_distribution rayleigh;\ + typedef BOOST_MATH_NAMESPACE::skew_normal_distribution skew_normal;\ + typedef BOOST_MATH_NAMESPACE::students_t_distribution students_t;\ + typedef BOOST_MATH_NAMESPACE::triangular_distribution triangular;\ + typedef BOOST_MATH_NAMESPACE::uniform_distribution uniform;\ + typedef BOOST_MATH_NAMESPACE::weibull_distribution weibull; \ + typedef BOOST_MATH_NAMESPACE::von_mises_distribution von_mises; #endif // BOOST_MATH_DISTRIBUTIONS_FWD_HPP diff --git a/include/boost/math/distributions/gamma.hpp b/include/boost/math/distributions/gamma.hpp index 5176f906d8..cbfc270db5 100644 --- a/include/boost/math/distributions/gamma.hpp +++ b/include/boost/math/distributions/gamma.hpp @@ -19,9 +19,11 @@ #include #include #include +#ifndef BOOST_MATH_HAS_GPU_SUPPORT +#include +#endif -namespace boost{ namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -31,7 +33,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_gamma_shape( RealType shape, RealType* result, const Policy& pol) { - if((shape <= 0) || !(boost::math::isfinite)(shape)) + if((shape <= 0) || !(BOOST_MATH_NAMESPACE::isfinite)(shape)) { *result = policies::raise_domain_error( function, @@ -47,7 +49,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_gamma_x( RealType const& x, RealType* result, const Policy& pol) { - if((x < 0) || !(boost::math::isfinite)(x)) + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) { *result = policies::raise_domain_error( function, @@ -69,7 +71,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_gamma( } // namespace detail -template > +BOOST_MATH_EXPORT template > class gamma_distribution { public: @@ -103,29 +105,29 @@ class gamma_distribution // NO typedef because of clash with name of gamma function. #ifdef __cpp_deduction_guides -template -gamma_distribution(RealType)->gamma_distribution::type>; -template -gamma_distribution(RealType,RealType)->gamma_distribution::type>; +BOOST_MATH_EXPORT template +gamma_distribution(RealType)->gamma_distribution::type>; +BOOST_MATH_EXPORT template +gamma_distribution(RealType,RealType)->gamma_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const gamma_distribution& /* dist */) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const gamma_distribution& /* dist */) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const gamma_distribution& /* dist */) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const gamma_distribution& /* dist */) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - using boost::math::tools::min_value; - return boost::math::pair(min_value(), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::min_value; + return BOOST_MATH_NAMESPACE::pair(min_value(), max_value()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const gamma_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -149,18 +151,18 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logpdf(const gamma_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions - using boost::math::lgamma; + using BOOST_MATH_NAMESPACE::lgamma; constexpr auto function = "boost::math::logpdf(const gamma_distribution<%1%>&, %1%)"; RealType k = dist.shape(); RealType theta = dist.scale(); - RealType result = -boost::math::numeric_limits::infinity(); + RealType result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); if(false == detail::check_gamma(function, theta, k, &result, Policy())) return result; if(false == detail::check_gamma_x(function, x, &result, Policy())) @@ -168,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const gamma_distribution::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } result = -k*log(theta) + (k-1)*log(x) - lgamma(k) - (x/theta); @@ -176,7 +178,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const gamma_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -192,11 +194,11 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const gamma_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions @@ -220,7 +222,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -241,7 +243,35 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const gamma_distribution& dist, const RealType& x) +{ + constexpr auto function = "boost::math::logcdf(const gamma_distribution<%1%>&, %1%)"; + RealType shape = dist.shape(); + RealType scale = dist.scale(); + RealType result = 0; + if(false == detail::check_gamma(function, scale, shape, &result, Policy())) + return result; + if(false == detail::check_gamma_x(function, x, &result, Policy())) + return result; + return BOOST_MATH_NAMESPACE::lgamma_p(shape, x / scale, Policy()); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) +{ + constexpr auto function = "boost::math::logcdf(const gamma_distribution<%1%>&, %1%)"; + RealType shape = c.dist.shape(); + RealType scale = c.dist.scale(); + RealType result = 0; + if(false == detail::check_gamma(function, scale, shape, &result, Policy())) + return result; + if(false == detail::check_gamma_x(function, c.param, &result, Policy())) + return result; + return BOOST_MATH_NAMESPACE::lgamma_q(shape, c.param / scale, Policy()); +} + +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -266,7 +296,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -284,7 +314,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -302,7 +332,7 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -331,7 +361,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mode(const gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -349,7 +379,7 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -367,24 +397,50 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const gamma_distribution< return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const gamma_distribution& dist) { return kurtosis_excess(dist) + 3; } -template +#ifndef BOOST_MATH_HAS_GPU_SUPPORT +BOOST_MATH_EXPORT template +inline RealType entropy(const gamma_distribution& dist) +{ + BOOST_MATH_STD_USING + // k + log(theta) + lgamma(k) + (1 - k) digamma(k), whose terms cancel to ~log(k)/2 for large k: + return log(dist.scale()) + detail::gamma_entropy_unit_scale(dist.shape(), Policy()); +} +#else +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const gamma_distribution& dist) { BOOST_MATH_STD_USING RealType k = dist.shape(); RealType theta = dist.scale(); - return k + log(theta) + boost::math::lgamma(k) + (1-k)*digamma(k); + if (k < 10) + { + return k + log(theta) + BOOST_MATH_NAMESPACE::lgamma(k) + (1-k)*digamma(k); + } + // The same Stirling form as the host path, with the first ten Bernoulli numbers written out (Bernoulli + // numbers are not available on the device): r(k) = sum B_2j (1/((2j-1) k^(2j-1)) - 1/(2j k^2j)), whose + // tenth term is below 2e-16 of the sum for k >= 10. + constexpr double b2j[10] = {1.0 / 6, -1.0 / 30, 1.0 / 42, -1.0 / 30, 5.0 / 66, -691.0 / 2730, 7.0 / 6, + -3617.0 / 510, 43867.0 / 798, -174611.0 / 330}; + RealType r = 0; + RealType k_power = k; // k^(2j - 1) + for (int j = 1; j <= 10; ++j) + { + RealType b = static_cast(b2j[j - 1]); + r += b / ((2 * j - 1) * k_power) - b / (2 * j * k_power * k); + k_power *= k * k; + } + return log(theta) + log(k) / 2 + constants::log_root_two_pi() + constants::half() - 1 / (2 * k) + r; } +#endif -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/generalized_extreme_value.hpp b/include/boost/math/distributions/generalized_extreme_value.hpp new file mode 100644 index 0000000000..722ac01718 --- /dev/null +++ b/include/boost/math/distributions/generalized_extreme_value.hpp @@ -0,0 +1,647 @@ +// Copyright Nick Thompson 2026. +// 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) + +#ifndef BOOST_MATH_DISTRIBUTIONS_GENERALIZED_EXTREME_VALUE_HPP +#define BOOST_MATH_DISTRIBUTIONS_GENERALIZED_EXTREME_VALUE_HPP + +// The generalized extreme value distribution, with location mu, scale sigma and shape xi as in +// https://en.wikipedia.org/wiki/Generalized_extreme_value_distribution: +// +// cdf(x) = exp(-t(x)), t(x) = (1 + xi (x - mu)/sigma)^(-1/xi), or exp(-(x - mu)/sigma) for xi = 0. +// +// xi > 0 is the Frechet type, bounded below at mu - sigma/xi; xi < 0 the reversed Weibull type, bounded +// above there; xi = 0 the Gumbel distribution, extreme_value_distribution. (SciPy's genextreme takes c = -xi.) +// log t = -log1p(xi z)/xi and the quantile's expm1(-xi log y)/xi tend to their Gumbel limits as xi -> 0 +// without cancellation. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN + +BOOST_MATH_EXPORT template > +class generalized_extreme_value_distribution +{ +public: + using value_type = RealType; + using policy_type = Policy; + + explicit generalized_extreme_value_distribution(RealType location = 0, RealType scale = 1, RealType shape = 0) + : m_location(location), m_scale(scale), m_shape(shape) + { + constexpr auto function = "boost::math::generalized_extreme_value_distribution<%1%>::generalized_extreme_value_distribution"; + RealType result; + detail::check_location(function, location, &result, Policy()); + detail::check_scale(function, scale, &result, Policy()); + detail::check_finite(function, shape, &result, Policy()); + } + + RealType location() const { return m_location; } + RealType scale() const { return m_scale; } + RealType shape() const { return m_shape; } + +private: + RealType m_location; + RealType m_scale; + RealType m_shape; +}; + +BOOST_MATH_EXPORT using generalized_extreme_value = generalized_extreme_value_distribution; + +#ifdef __cpp_deduction_guides +BOOST_MATH_EXPORT template +generalized_extreme_value_distribution(RealType)->generalized_extreme_value_distribution::type>; +BOOST_MATH_EXPORT template +generalized_extreme_value_distribution(RealType, RealType)->generalized_extreme_value_distribution::type>; +BOOST_MATH_EXPORT template +generalized_extreme_value_distribution(RealType, RealType, RealType)->generalized_extreme_value_distribution::type>; +#endif + +namespace detail { + +template +inline bool check_gev(const char* function, const generalized_extreme_value_distribution& dist, RealType* result) +{ + return check_location(function, dist.location(), result, Policy()) + && check_scale(function, dist.scale(), result, Policy()) + && check_finite(function, dist.shape(), result, Policy()); +} + +// Where x lies relative to the support, and inside it L = -log t(x) = log1p(xi z)/xi, so that cdf(x) = exp(-exp(-L)). +enum class gev_region { below, inside, endpoint, above }; + +// The support is decided against the end point mu - sigma/xi that support() reports, before x is standardized, +// whose rounding could otherwise carry a point outside onto it. Inside, 1 + xi z can still round to 0 or below +// next to the end point, where the end point's limit is the answer to working precision. +template +gev_region gev_log_t(RealType x, RealType mu, RealType sigma, RealType xi, RealType* L) +{ + BOOST_MATH_STD_USING + RealType z = (x - mu) / sigma; + if (xi == 0) + { + *L = z; + return gev_region::inside; + } + RealType endpoint = mu - sigma / xi; + if (x == endpoint) + { + return gev_region::endpoint; + } + if ((xi > 0) == (x < endpoint)) + { + // Beyond the lower end point for xi > 0, the upper for xi < 0: + return xi > 0 ? gev_region::below : gev_region::above; + } + RealType s = xi * z; + if (s <= -1) + { + return gev_region::endpoint; + } + // For tiny xi z, xi z may have lost bits to underflow; log1p(s)/xi = z (1 - s/2 + ...): + *L = abs(s) < tools::epsilon() ? z * (1 - s / 2) : RealType(BOOST_MATH_NAMESPACE::log1p(s) / xi); + return gev_region::inside; +} + +// (y^(-xi) - 1)/xi, the standardized quantile at t = y; -log y for xi = 0. expm1(-xi log y) carries +// log's absolute error times xi, so where |xi log y| > 1 pow, which then has nothing to cancel, is better. +template +RealType gev_standard_quantile(RealType y, RealType log_y, RealType xi, const Policy& pol) +{ + BOOST_MATH_STD_USING + RealType a = -xi * log_y; + if (xi == 0 || abs(a) < tools::epsilon()) + { + return -log_y * (1 + a / 2); + } + if (abs(a) > 1) + { + return (pow(y, -xi) - 1) / xi; + } + return BOOST_MATH_NAMESPACE::expm1(a, pol) / xi; +} + +// expm1(x) - x, without the cancellation for small x. +template +RealType gev_expm1mx(RealType x, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (abs(x) > RealType(0.5)) + { + return BOOST_MATH_NAMESPACE::expm1(x, pol) - x; + } + RealType term = x * x / 2; + RealType sum = term; + for (unsigned n = 3; abs(term) > tools::epsilon() * abs(sum); ++n) + { + term *= x / n; + sum += term; + } + return sum; +} + +// sum_k c[k] A_k for k = 2, 3, 4, where A_k = lgamma(1 - k xi) - k lgamma(1 - xi) is the log of +// E[W^k]/E[W]^k for W = t^(-xi), the moments of which are Gamma(1 - k xi). The combinations the +// moments need cancel at leading order(s) in xi, so for small xi this sums the Taylor series +// lgamma(1 - z) = euler z + sum_{j >= 2} zeta(j) z^j / j term by term, in which they cancel exactly: +// sum_k c[k] A_k = sum_{j >= 2} zeta(j)/j sum_k c[k] (k^j - k) xi^j. +// The series converges for |k xi| < 1 with ratio |k xi|; it is used to |k xi| = 3/4 for the largest k, +// beyond which the lgamma differences lose at most a digit or so. +template +RealType gev_log_moment_combination(const int (&c)[3], RealType xi, const Policy& pol) +{ + BOOST_MATH_STD_USING + int k_max = c[2] != 0 ? 4 : (c[1] != 0 ? 3 : 2); + if (k_max * abs(xi) > RealType(0.75)) + { + RealType l1 = BOOST_MATH_NAMESPACE::lgamma(1 - xi, pol); + RealType sum = 0; + for (int k = 2; k <= 4; ++k) + { + if (c[k - 2] != 0) + { + sum += c[k - 2] * (BOOST_MATH_NAMESPACE::lgamma(1 - k * xi, pol) - k * l1); + } + } + return sum; + } + RealType power[3] = { 2, 3, 4 }; // k^j + RealType xi_j = xi; // xi^j + RealType sum = 0; + const std::uintmax_t max_terms = policies::get_max_series_iterations(); + for (std::uintmax_t j = 2; ; ++j) + { + RealType weight = 0; + for (int k = 2; k <= 4; ++k) + { + power[k - 2] *= k; + weight += c[k - 2] * (power[k - 2] - k); + } + xi_j *= xi; + RealType term = BOOST_MATH_NAMESPACE::zeta(RealType(j), pol) / j * weight * xi_j; + sum += term; + // The weights of the leading orders are zero, so only stop on a nonzero term: + if (weight != 0 && abs(term) <= tools::epsilon() * abs(sum)) + { + return sum; + } + if (j > max_terms) + { + return policies::raise_evaluation_error("boost::math::generalized_extreme_value moments", "Series did not converge for shape %1%.", xi, pol); + } + } +} + +// The moments of xi this small are their Gumbel limits to working precision. +template +bool gev_is_gumbel(RealType xi) +{ + BOOST_MATH_STD_USING + return abs(xi) < tools::epsilon(); +} + +// The mean for xi >= 1 and the variance for xi >= 1/2, which diverge to +infinity (max_value for a type without one). +template +RealType gev_infinity() +{ + return std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : tools::max_value(); +} + +template +RealType gev_undefined_moment(const char* function, const char* message, RealType xi) +{ + return policies::raise_domain_error(function, message, xi, Policy()); +} + +} // namespace detail + +BOOST_MATH_EXPORT template +inline std::pair range(const generalized_extreme_value_distribution& /*dist*/) +{ // Range of permissible values for random variable x; the pdf is zero outside the support. + using BOOST_MATH_NAMESPACE::tools::max_value; + return std::pair( + std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -max_value(), + std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : max_value()); +} + +BOOST_MATH_EXPORT template +inline std::pair support(const generalized_extreme_value_distribution& dist) +{ // Range where the cdf rises from 0 to 1: bounded at mu - sigma/xi below for xi > 0, above for xi < 0. + using BOOST_MATH_NAMESPACE::tools::max_value; + RealType xi = dist.shape(); + RealType endpoint = xi == 0 ? RealType(0) : RealType(dist.location() - dist.scale() / xi); + if (xi > 0) + { + return std::pair(endpoint, max_value()); + } + if (xi < 0) + { + return std::pair(-max_value(), endpoint); + } + return std::pair(-max_value(), max_value()); +} + +BOOST_MATH_EXPORT template +inline RealType logpdf(const generalized_extreme_value_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING + constexpr auto function = "boost::math::logpdf(const generalized_extreme_value_distribution<%1%>&, %1%)"; + RealType result = 0; + if (!detail::check_gev(function, dist, &result) || !detail::check_x_not_NaN(function, x, &result, Policy())) + { + return result; + } + RealType xi = dist.shape(); + if ((BOOST_MATH_NAMESPACE::isinf)(x)) + { + return -std::numeric_limits::infinity(); + } + RealType L; + switch (detail::gev_log_t(x, dist.location(), dist.scale(), xi, &L)) + { + case detail::gev_region::inside: + break; + case detail::gev_region::endpoint: + // The bounded end, where t = 0 for xi < 0 and the density is t^(1 + xi)/sigma; t = infinity for xi > 0. + if (xi == -1) + { + return -log(dist.scale()); + } + if (xi < -1) + { + return policies::raise_overflow_error(function, nullptr, Policy()); + } + return -std::numeric_limits::infinity(); + default: + return -std::numeric_limits::infinity(); + } + // log pdf = -log sigma + (1 + xi) log t - t, with log t = -L: + RealType t = exp(-L); + if ((BOOST_MATH_NAMESPACE::isinf)(t)) + { + return -std::numeric_limits::infinity(); + } + return -log(dist.scale()) - (1 + xi) * L - t; +} + +BOOST_MATH_EXPORT template +inline RealType pdf(const generalized_extreme_value_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING + constexpr auto function = "boost::math::pdf(const generalized_extreme_value_distribution<%1%>&, %1%)"; + RealType result = 0; + if (!detail::check_gev(function, dist, &result) || !detail::check_x_not_NaN(function, x, &result, Policy())) + { + return result; + } + RealType xi = dist.shape(); + if ((BOOST_MATH_NAMESPACE::isinf)(x)) + { + return 0; + } + RealType L; + switch (detail::gev_log_t(x, dist.location(), dist.scale(), xi, &L)) + { + case detail::gev_region::inside: + break; + case detail::gev_region::endpoint: + if (xi == -1) + { + return 1 / dist.scale(); + } + if (xi < -1) + { + return policies::raise_overflow_error(function, nullptr, Policy()); + } + return 0; + default: + return 0; + } + RealType t = exp(-L); + if ((BOOST_MATH_NAMESPACE::isinf)(t)) + { + return 0; + } + // t^(1 + xi) exp(-t) / sigma: + return exp(-(1 + xi) * L - t) / dist.scale(); +} + +namespace detail { + +// cdf, its complement, and their logs; region and t decide them all. +template +RealType gev_cdf_imp(const generalized_extreme_value_distribution& dist, const RealType& x, bool complement, bool take_log, const char* function) +{ + BOOST_MATH_STD_USING + RealType result = 0; + if (!check_gev(function, dist, &result) || !check_x_not_NaN(function, x, &result, Policy())) + { + return result; + } + const RealType zero = take_log ? RealType(-std::numeric_limits::infinity()) : RealType(0); + const RealType one = take_log ? RealType(0) : RealType(1); + if ((BOOST_MATH_NAMESPACE::isinf)(x)) + { + return (x < 0) != complement ? zero : one; + } + RealType xi = dist.shape(); + RealType L; + switch (gev_log_t(x, dist.location(), dist.scale(), xi, &L)) + { + case gev_region::inside: + break; + case gev_region::endpoint: + return (xi > 0) != complement ? zero : one; + case gev_region::below: + return complement ? one : zero; + default: + return complement ? zero : one; + } + RealType t = exp(-L); + if (!complement) + { + return take_log ? RealType(-t) : RealType(exp(-t)); + } + RealType q = -BOOST_MATH_NAMESPACE::expm1(-t, Policy()); + if (!take_log) + { + return q; + } + // log(1 - exp(-t)): log t - t/2 = -L - t/2 once t is below epsilon (t may have underflowed), through q + // while it is small, else through log1p: + if (t < tools::epsilon()) + { + return -L - t / 2; + } + return t () ? RealType(log(q)) : RealType(BOOST_MATH_NAMESPACE::log1p(-exp(-t), Policy())); +} + +template +RealType gev_quantile_imp(const generalized_extreme_value_distribution& dist, const RealType& p, bool complement, const char* function) +{ + BOOST_MATH_STD_USING + RealType result = 0; + if (!check_gev(function, dist, &result) || !check_probability(function, p, &result, Policy())) + { + return result; + } + RealType xi = dist.shape(); + RealType mu = dist.location(); + RealType sigma = dist.scale(); + // P = cdf(x): + bool lower_end = complement ? p == 1 : p == 0; + bool upper_end = complement ? p == 0 : p == 1; + if (lower_end) + { + return xi > 0 ? RealType(mu - sigma / xi) : RealType(-policies::raise_overflow_error(function, nullptr, Policy())); + } + if (upper_end) + { + return xi < 0 ? RealType(mu - sigma / xi) : policies::raise_overflow_error(function, nullptr, Policy()); + } + // t = -log P: + RealType y = complement ? RealType(-BOOST_MATH_NAMESPACE::log1p(-p, Policy())) : RealType(-log(p)); + return mu + sigma * gev_standard_quantile(y, RealType(log(y)), xi, Policy()); +} + +} // namespace detail + +BOOST_MATH_EXPORT template +inline RealType cdf(const generalized_extreme_value_distribution& dist, const RealType& x) +{ + return detail::gev_cdf_imp(dist, x, false, false, "boost::math::cdf(const generalized_extreme_value_distribution<%1%>&, %1%)"); +} + +BOOST_MATH_EXPORT template +inline RealType cdf(const complemented2_type, RealType>& c) +{ + return detail::gev_cdf_imp(c.dist, c.param, true, false, "boost::math::cdf(const generalized_extreme_value_distribution<%1%>&, %1%)"); +} + +BOOST_MATH_EXPORT template +inline RealType logcdf(const generalized_extreme_value_distribution& dist, const RealType& x) +{ + return detail::gev_cdf_imp(dist, x, false, true, "boost::math::logcdf(const generalized_extreme_value_distribution<%1%>&, %1%)"); +} + +BOOST_MATH_EXPORT template +inline RealType logcdf(const complemented2_type, RealType>& c) +{ + return detail::gev_cdf_imp(c.dist, c.param, true, true, "boost::math::logcdf(const generalized_extreme_value_distribution<%1%>&, %1%)"); +} + +BOOST_MATH_EXPORT template +inline RealType quantile(const generalized_extreme_value_distribution& dist, const RealType& p) +{ + return detail::gev_quantile_imp(dist, p, false, "boost::math::quantile(const generalized_extreme_value_distribution<%1%>&, %1%)"); +} + +BOOST_MATH_EXPORT template +inline RealType quantile(const complemented2_type, RealType>& c) +{ + return detail::gev_quantile_imp(c.dist, c.param, true, "boost::math::quantile(const generalized_extreme_value_distribution<%1%>&, %1%)"); +} + +BOOST_MATH_EXPORT template +inline RealType mean(const generalized_extreme_value_distribution& dist) +{ + constexpr auto function = "boost::math::mean(const generalized_extreme_value_distribution<%1%>&)"; + RealType result = 0; + if (!detail::check_gev(function, dist, &result)) + { + return result; + } + RealType xi = dist.shape(); + if (xi >= 1) + { + // The right tail decays like x^(-1/xi), so the mean is +infinity: + return detail::gev_infinity(); + } + if (detail::gev_is_gumbel(xi)) + { + return mean(extreme_value_distribution(dist.location(), dist.scale())); + } + // mu + sigma (Gamma(1 - xi) - 1)/xi: + return dist.location() + dist.scale() * BOOST_MATH_NAMESPACE::tgamma1pm1(-xi, Policy()) / xi; +} + +BOOST_MATH_EXPORT template +inline RealType variance(const generalized_extreme_value_distribution& dist) +{ + constexpr auto function = "boost::math::variance(const generalized_extreme_value_distribution<%1%>&)"; + RealType result = 0; + if (!detail::check_gev(function, dist, &result)) + { + return result; + } + RealType xi = dist.shape(); + if (2 * xi >= 1) + { + // The second moment diverges, so the variance is +infinity: + return detail::gev_infinity(); + } + RealType sigma = dist.scale(); + if (detail::gev_is_gumbel(xi)) + { + return sigma * sigma * constants::pi_sqr() / 6; + } + // sigma^2 (Gamma(1 - 2 xi) - Gamma(1 - xi)^2)/xi^2 = (sigma Gamma(1 - xi)/xi)^2 expm1(A_2): + const int a2[3] = { 1, 0, 0 }; + RealType g1 = BOOST_MATH_NAMESPACE::tgamma(1 - xi, Policy()); + RealType s = sigma * g1 / xi; + return s * s * BOOST_MATH_NAMESPACE::expm1(detail::gev_log_moment_combination(a2, xi, Policy()), Policy()); +} + +BOOST_MATH_EXPORT template +inline RealType standard_deviation(const generalized_extreme_value_distribution& dist) +{ + BOOST_MATH_STD_USING + return sqrt(variance(dist)); +} + +BOOST_MATH_EXPORT template +inline RealType skewness(const generalized_extreme_value_distribution& dist) +{ + BOOST_MATH_STD_USING + constexpr auto function = "boost::math::skewness(const generalized_extreme_value_distribution<%1%>&)"; + RealType result = 0; + if (!detail::check_gev(function, dist, &result)) + { + return result; + } + RealType xi = dist.shape(); + if (3 * xi >= 1) + { + return detail::gev_undefined_moment(function, "The skewness is undefined for shape >= 1/3, but got %1%.", xi); + } + if (detail::gev_is_gumbel(xi)) + { + return skewness(extreme_value_distribution()); + } + // sign(xi) (g3 - 3 g1 g2 + 2 g1^3)/(g2 - g1^2)^(3/2) with g_k = Gamma(1 - k xi); over g1^3 the numerator + // is expm1(A_3) - 3 expm1(A_2) = (A_3 - 3 A_2) + expm1mx(A_3) - 3 expm1mx(A_2), which is O(xi^3): + const int a2[3] = { 1, 0, 0 }; + const int a3[3] = { 0, 1, 0 }; + const int b[3] = { -3, 1, 0 }; + RealType A2 = detail::gev_log_moment_combination(a2, xi, Policy()); + RealType A3 = detail::gev_log_moment_combination(a3, xi, Policy()); + RealType numerator = detail::gev_log_moment_combination(b, xi, Policy()) + detail::gev_expm1mx(A3, Policy()) - 3 * detail::gev_expm1mx(A2, Policy()); + RealType v = BOOST_MATH_NAMESPACE::expm1(A2, Policy()); + RealType skew = numerator / (v * sqrt(v)); + return xi > 0 ? skew : RealType(-skew); +} + +BOOST_MATH_EXPORT template +inline RealType kurtosis_excess(const generalized_extreme_value_distribution& dist) +{ + constexpr auto function = "boost::math::kurtosis_excess(const generalized_extreme_value_distribution<%1%>&)"; + RealType result = 0; + if (!detail::check_gev(function, dist, &result)) + { + return result; + } + RealType xi = dist.shape(); + if (4 * xi >= 1) + { + return detail::gev_undefined_moment(function, "The kurtosis is undefined for shape >= 1/4, but got %1%.", xi); + } + if (detail::gev_is_gumbel(xi)) + { + return kurtosis_excess(extreme_value_distribution()); + } + // (g4 - 4 g1 g3 + 6 g1^2 g2 - 3 g1^4)/(g2 - g1^2)^2 - 3; over g1^4 the numerator is + // expm1(A_4) - 4 expm1(A_3) + 6 expm1(A_2), whose part linear in the A_k is O(xi^4): + const int a2[3] = { 1, 0, 0 }; + const int a3[3] = { 0, 1, 0 }; + const int a4[3] = { 0, 0, 1 }; + const int c[3] = { 6, -4, 1 }; + RealType A2 = detail::gev_log_moment_combination(a2, xi, Policy()); + RealType A3 = detail::gev_log_moment_combination(a3, xi, Policy()); + RealType A4 = detail::gev_log_moment_combination(a4, xi, Policy()); + RealType numerator = detail::gev_log_moment_combination(c, xi, Policy()) + + detail::gev_expm1mx(A4, Policy()) - 4 * detail::gev_expm1mx(A3, Policy()) + 6 * detail::gev_expm1mx(A2, Policy()); + RealType v = BOOST_MATH_NAMESPACE::expm1(A2, Policy()); + return numerator / (v * v) - 3; +} + +BOOST_MATH_EXPORT template +inline RealType kurtosis(const generalized_extreme_value_distribution& dist) +{ + return kurtosis_excess(dist) + 3; +} + +BOOST_MATH_EXPORT template +inline RealType mode(const generalized_extreme_value_distribution& dist) +{ + BOOST_MATH_STD_USING + constexpr auto function = "boost::math::mode(const generalized_extreme_value_distribution<%1%>&)"; + RealType result = 0; + if (!detail::check_gev(function, dist, &result)) + { + return result; + } + RealType xi = dist.shape(); + if (xi <= -1) + { + // The density increases to the upper endpoint: + return dist.location() - dist.scale() / xi; + } + // mu + sigma ((1 + xi)^(-xi) - 1)/xi, where t = 1 + xi: + return dist.location() + dist.scale() * detail::gev_standard_quantile(RealType(1 + xi), RealType(BOOST_MATH_NAMESPACE::log1p(xi, Policy())), xi, Policy()); +} + +BOOST_MATH_EXPORT template +inline RealType median(const generalized_extreme_value_distribution& dist) +{ + constexpr auto function = "boost::math::median(const generalized_extreme_value_distribution<%1%>&)"; + RealType result = 0; + if (!detail::check_gev(function, dist, &result)) + { + return result; + } + // t = log 2: + return dist.location() + dist.scale() * detail::gev_standard_quantile(constants::ln_two(), constants::ln_ln_two(), dist.shape(), Policy()); +} + +BOOST_MATH_EXPORT template +inline RealType entropy(const generalized_extreme_value_distribution& dist) +{ + BOOST_MATH_STD_USING + constexpr auto function = "boost::math::entropy(const generalized_extreme_value_distribution<%1%>&)"; + RealType result = 0; + if (!detail::check_gev(function, dist, &result)) + { + return result; + } + return log(dist.scale()) + constants::euler() * (1 + dist.shape()) + 1; +} + +BOOST_MATH_NAMESPACE_END + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#endif // BOOST_MATH_DISTRIBUTIONS_GENERALIZED_EXTREME_VALUE_HPP diff --git a/include/boost/math/distributions/geometric.hpp b/include/boost/math/distributions/geometric.hpp index 0a7b383c24..ac8d47b8fc 100644 --- a/include/boost/math/distributions/geometric.hpp +++ b/include/boost/math/distributions/geometric.hpp @@ -55,17 +55,14 @@ // in domain_error_imp in error_handling. #endif -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace geometric_detail { // Common error checking routines for geometric distribution function: template BOOST_MATH_GPU_ENABLED inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& pol) { - if( !(boost::math::isfinite)(p) || (p < 0) || (p > 1) ) + if( !(BOOST_MATH_NAMESPACE::isfinite)(p) || (p < 0) || (p > 1) ) { *result = policies::raise_domain_error( function, @@ -88,7 +85,7 @@ namespace boost { return false; } - if( !(boost::math::isfinite)(k) || (k < 0) ) + if( !(BOOST_MATH_NAMESPACE::isfinite)(k) || (k < 0) ) { // Check k failures. *result = policies::raise_domain_error( function, @@ -109,7 +106,7 @@ namespace boost } // check_dist_and_prob } // namespace geometric_detail - template > + BOOST_MATH_EXPORT template > class geometric_distribution { public: @@ -235,29 +232,29 @@ namespace boost RealType m_p; // success_fraction }; // template class geometric_distribution - typedef geometric_distribution geometric; // Reserved name of type double. + BOOST_MATH_EXPORT typedef geometric_distribution geometric; // Reserved name of type double. #ifdef __cpp_deduction_guides - template - geometric_distribution(RealType)->geometric_distribution::type>; + BOOST_MATH_EXPORT template + geometric_distribution(RealType)->geometric_distribution::type>; #endif - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const geometric_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const geometric_distribution& /* dist */) { // Range of permissible values for random variable k. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // max_integer? + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // max_integer? } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const geometric_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const geometric_distribution& /* dist */) { // Range of supported values for random variable k. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // max_integer? + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // max_integer? } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const geometric_distribution& dist) { // Mean of geometric distribution = (1-p)/p. return (1 - dist.success_fraction() ) / dist.success_fraction(); @@ -265,21 +262,21 @@ namespace boost // median implemented via quantile(half) in derived accessors. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const geometric_distribution&) { // Mode of geometric distribution = zero. BOOST_MATH_STD_USING // ADL of std functions. return 0; } // mode - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const geometric_distribution& dist) { // Variance of Binomial distribution = (1-p) / p^2. return (1 - dist.success_fraction()) / (dist.success_fraction() * dist.success_fraction()); } // variance - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const geometric_distribution& dist) { // skewness of geometric distribution = 2-p / (sqrt(r(1-p)) BOOST_MATH_STD_USING // ADL of std functions. @@ -287,7 +284,7 @@ namespace boost return (2 - p) / sqrt(1 - p); } // skewness - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const geometric_distribution& dist) { // kurtosis of geometric distribution // http://en.wikipedia.org/wiki/geometric is kurtosis_excess so add 3 @@ -295,7 +292,7 @@ namespace boost return 3 + (p*p - 6*p + 6) / (1 - p); } // kurtosis - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const geometric_distribution& dist) { // kurtosis excess of geometric distribution // http://mathworld.wolfram.com/Kurtosis.html table of kurtosis_excess @@ -310,7 +307,7 @@ namespace boost // RealType chf(const geometric_distribution& dist) // chf of geometric distribution provided by derived accessors. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const geometric_distribution& dist, const RealType& k) { // Probability Density/Mass Function. BOOST_FPU_EXCEPTION_GUARD @@ -348,7 +345,7 @@ namespace boost return result; } // geometric_pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const geometric_distribution& dist, const RealType& k) { // Cumulative Distribution Function of geometric. constexpr auto function = "boost::math::cdf(const geometric_distribution<%1%>&, %1%)"; @@ -373,13 +370,13 @@ namespace boost //RealType q = 1 - p; // Bad for small p //RealType probability = 1 - std::pow(q, k+1); - RealType z = boost::math::log1p(-p, Policy()) * (k + 1); - RealType probability = -boost::math::expm1(z, Policy()); + RealType z = BOOST_MATH_NAMESPACE::log1p(-p, Policy()) * (k + 1); + RealType probability = -BOOST_MATH_NAMESPACE::expm1(z, Policy()); return probability; } // cdf Cumulative Distribution Function geometric. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const geometric_distribution& dist, const RealType& k) { // Cumulative Distribution Function of geometric. BOOST_MATH_STD_USING @@ -396,7 +393,7 @@ namespace boost k, &result, Policy())) { - return -boost::math::numeric_limits::infinity(); + return -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } if(k == 0) { @@ -405,11 +402,11 @@ namespace boost //RealType q = 1 - p; // Bad for small p //RealType probability = 1 - std::pow(q, k+1); - RealType z = boost::math::log1p(-p, Policy()) * (k + 1); + RealType z = BOOST_MATH_NAMESPACE::log1p(-p, Policy()) * (k + 1); return log1p(-exp(z), Policy()); } // logcdf Cumulative Distribution Function geometric. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function geometric. BOOST_MATH_STD_USING @@ -429,12 +426,12 @@ namespace boost { return result; } - RealType z = boost::math::log1p(-p, Policy()) * (k+1); + RealType z = BOOST_MATH_NAMESPACE::log1p(-p, Policy()) * (k+1); RealType probability = exp(z); return probability; } // cdf Complemented Cumulative Distribution Function geometric. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function geometric. BOOST_MATH_STD_USING @@ -452,13 +449,13 @@ namespace boost k, &result, Policy())) { - return -boost::math::numeric_limits::infinity(); + return -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } - return boost::math::log1p(-p, Policy()) * (k+1); + return BOOST_MATH_NAMESPACE::log1p(-p, Policy()) * (k+1); } // logcdf Complemented Cumulative Distribution Function geometric. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const geometric_distribution& dist, const RealType& x) { // Quantile, percentile/100 or Percent Point geometric function. // Return the number of expected failures k for a given probability p. @@ -492,8 +489,9 @@ namespace boost { // No failures are expected if P = 0. return 0; // Total trials will be just dist.successes. } - // if (P <= pow(dist.success_fraction(), 1)) - if (x <= success_fraction) + // Compare with the cdf itself, not the success fraction it equals + // mathematically, so that the rounding below agrees with cdf(): + if (x <= cdf(dist, RealType(0))) { // p <= pdf(dist, 0) == cdf(dist, 0) return 0; } @@ -503,13 +501,12 @@ namespace boost } // log(1-x) /log(1-success_fraction) -1; but use log1p in case success_fraction is small - result = boost::math::log1p(-x, Policy()) / boost::math::log1p(-success_fraction, Policy()) - 1; - // Subtract a few epsilons here too? - // to make sure it doesn't slip over, so ceil would be one too many. - return result; + result = BOOST_MATH_NAMESPACE::log1p(-x, Policy()) / BOOST_MATH_NAMESPACE::log1p(-success_fraction, Policy()) - 1; + // Round as the discrete_quantile policy asks, settling on the cdf at integers: + return detail::round_discrete_quantile(dist, result, x, false, typename Policy::discrete_quantile_type()); } // RealType quantile(const geometric_distribution dist, p) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { // Quantile or Percent Point Binomial function. // Return the number of expected failures k for a given @@ -536,9 +533,9 @@ namespace boost // since the probability of zero failures may be non-zero, return 0; // but zero is the best we can do: } - if (-x <= boost::math::powm1(dist.success_fraction(), dist.successes(), Policy())) - { // q <= cdf(complement(dist, 0)) == pdf(dist, 0) - return 0; // + if (x >= cdf(complement(dist, RealType(0)))) + { // As above, q >= cdf(complement(dist, 0)) == 1 - pdf(dist, 0). + return 0; } if(x == 0) { // Probability 1 - Q == 1 so infinite failures to achieve certainty. @@ -551,13 +548,23 @@ namespace boost // unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR } // log(x) /log(1-success_fraction) -1; but use log1p in case success_fraction is small - result = log(x) / boost::math::log1p(-success_fraction, Policy()) - 1; - return result; + result = log(x) / BOOST_MATH_NAMESPACE::log1p(-success_fraction, Policy()) - 1; + return detail::round_discrete_quantile(dist, result, x, true, typename Policy::discrete_quantile_type()); } // quantile complement - } // namespace math -} // namespace boost + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline RealType entropy(const geometric_distribution& dist) + { + BOOST_MATH_STD_USING + // -[(1 - p) log(1 - p) + p log(p)] / p: both terms are positive. + RealType p = dist.success_fraction(); + if (p == 1) + return 0; + return -(1 - p) * BOOST_MATH_NAMESPACE::log1p(-p, Policy()) / p - log(p); + } + + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/holtsmark.hpp b/include/boost/math/distributions/holtsmark.hpp index 04f5484f4e..b077bbfd1b 100644 --- a/include/boost/math/distributions/holtsmark.hpp +++ b/include/boost/math/distributions/holtsmark.hpp @@ -29,18 +29,20 @@ #ifndef BOOST_MATH_HAS_NVRTC #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #endif +#endif -namespace boost { namespace math { -template +BOOST_MATH_NAMESPACE_BEGIN +BOOST_MATH_EXPORT template class holtsmark_distribution; namespace detail { template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -270,7 +272,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_plus_imp_prec(const RealTyp template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -622,14 +624,14 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_plus_imp_prec(const RealTyp template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_imp_prec(const RealType& x, const boost::math::integral_constant &tag) { +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant &tag) { BOOST_MATH_STD_USING // for ADL of std functions return holtsmark_pdf_plus_imp_prec(abs(x), tag); } template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_imp_prec(const RealType& x, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant& tag) { BOOST_MATH_STD_USING // for ADL of std functions return holtsmark_pdf_plus_imp_prec(abs(x), tag); @@ -662,7 +664,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_pdf_imp(const holtsmark_distrib typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -904,7 +906,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_plus_imp_prec(const RealTyp } else { RealType x_cube = x * x * x; - RealType t = static_cast((boost::math::isnormal)(x_cube) ? 1 / sqrt(x_cube) : 1 / pow(sqrt(x), 3)); + RealType t = static_cast((BOOST_MATH_NAMESPACE::isnormal)(x_cube) ? 1 / sqrt(x_cube) : 1 / pow(sqrt(x), 3)); // Rational Approximation // Maximum Relative Error: 4.2897e-18 @@ -927,7 +929,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_plus_imp_prec(const RealTyp } template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1280,7 +1282,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_plus_imp_prec(const RealTyp } else { RealType x_cube = x * x * x; - RealType t = (boost::math::isnormal)(x_cube) ? 1 / sqrt(x_cube) : 1 / pow(sqrt(x), 3); + RealType t = (BOOST_MATH_NAMESPACE::isnormal)(x_cube) ? 1 / sqrt(x_cube) : 1 / pow(sqrt(x), 3); // Rational Approximation // Maximum Relative Error: 5.4677e-35 @@ -1310,7 +1312,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_plus_imp_prec(const RealTyp } template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_imp_prec(const RealType& x, bool complement, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_imp_prec(const RealType& x, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return complement ? holtsmark_cdf_plus_imp_prec(x, tag) : 1 - holtsmark_cdf_plus_imp_prec(x, tag); } @@ -1318,12 +1320,12 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_imp_prec(const RealType& x, return complement ? 1 - holtsmark_cdf_plus_imp_prec(-x, tag) : holtsmark_cdf_plus_imp_prec(-x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_imp_prec(const RealType& x, bool complement, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_imp_prec(const RealType& x, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return complement ? holtsmark_cdf_plus_imp_prec(x, tag) : 1 - holtsmark_cdf_plus_imp_prec(x, tag); } @@ -1331,7 +1333,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_imp_prec(const RealType& x, return complement ? 1 - holtsmark_cdf_plus_imp_prec(-x, tag) : holtsmark_cdf_plus_imp_prec(-x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } @@ -1362,7 +1364,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_cdf_imp(const holtsmark_distrib typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_upper_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_upper_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1625,14 +1627,14 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_upper_imp_prec(const R RealType p_square = p * p; - if ((boost::math::isnormal)(p_square)) { + if ((BOOST_MATH_NAMESPACE::isnormal)(p_square)) { result = 1 / (cbrt(p_square) * c); } else if (p > 0) { result = 1 / (cbrt(p) * cbrt(p) * c); } else { - result = boost::math::numeric_limits::infinity(); + result = BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } } @@ -1641,7 +1643,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_upper_imp_prec(const R template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_upper_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_upper_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -2222,14 +2224,14 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_upper_imp_prec(const R RealType p_square = p * p; - if ((boost::math::isnormal)(p_square)) { + if ((BOOST_MATH_NAMESPACE::isnormal)(p_square)) { result = 1 / (cbrt(p_square) * c); } else if (p > 0) { result = 1 / (cbrt(p) * cbrt(p) * c); } else { - result = boost::math::numeric_limits::infinity(); + result = BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } } @@ -2237,7 +2239,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_upper_imp_prec(const R } template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_imp_prec(const RealType& p, bool complement, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_imp_prec(const RealType& p, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (p > 0.5) { return !complement ? holtsmark_quantile_upper_imp_prec(1 - p, tag) : -holtsmark_quantile_upper_imp_prec(1 - p, tag); @@ -2247,7 +2249,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_imp_prec(const RealTyp } template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_imp_prec(const RealType& p, bool complement, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_imp_prec(const RealType& p, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (p > 0.5) { return !complement ? holtsmark_quantile_upper_imp_prec(1 - p, tag) : -holtsmark_quantile_upper_imp_prec(1 - p, tag); @@ -2284,7 +2286,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_quantile_imp(const holtsmark_di typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_entropy_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_entropy_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return static_cast(2.06944850513462440032); } template -BOOST_MATH_GPU_ENABLED inline RealType holtsmark_entropy_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType holtsmark_entropy_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return BOOST_MATH_BIG_CONSTANT(RealType, 113, 2.0694485051346244003155800384542166381); } @@ -2327,7 +2329,7 @@ BOOST_MATH_GPU_ENABLED inline RealType holtsmark_entropy_imp(const holtsmark_dis typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant > +BOOST_MATH_EXPORT template > class holtsmark_distribution { public: @@ -2372,99 +2374,99 @@ class holtsmark_distribution RealType c; // The scale parameter. }; -typedef holtsmark_distribution holtsmark; +BOOST_MATH_EXPORT typedef holtsmark_distribution holtsmark; #ifdef __cpp_deduction_guides -template -holtsmark_distribution(RealType) -> holtsmark_distribution::type>; -template -holtsmark_distribution(RealType, RealType) -> holtsmark_distribution::type>; +BOOST_MATH_EXPORT template +holtsmark_distribution(RealType) -> holtsmark_distribution::type>; +BOOST_MATH_EXPORT template +holtsmark_distribution(RealType, RealType) -> holtsmark_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const holtsmark_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const holtsmark_distribution&) { // Range of permissible values for random variable x. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + max. } } -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const holtsmark_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const holtsmark_distribution&) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-tools::max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-tools::max_value(), max_value()); // - to + max. } } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const holtsmark_distribution& dist, const RealType& x) { return detail::holtsmark_pdf_imp(dist, x); } // pdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const holtsmark_distribution& dist, const RealType& x) { return detail::holtsmark_cdf_imp(dist, x, false); } // cdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const holtsmark_distribution& dist, const RealType& p) { return detail::holtsmark_quantile_imp(dist, p, false); } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { return detail::holtsmark_cdf_imp(c.dist, c.param, true); } // cdf complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { return detail::holtsmark_quantile_imp(c.dist, c.param, true); } // quantile complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const holtsmark_distribution &dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const holtsmark_distribution& /*dist*/) { - return boost::math::numeric_limits::infinity(); + return BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const holtsmark_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const holtsmark_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const holtsmark_distribution& /*dist*/) { // There is no skewness: @@ -2475,10 +2477,10 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const holtsmark_distribution&)", "The Holtsmark distribution does not have a skewness: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); // infinity? + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); // infinity? } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const holtsmark_distribution& /*dist*/) { // There is no kurtosis: @@ -2489,10 +2491,10 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const holtsmark_distribution&)", "The Holtsmark distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const holtsmark_distribution& /*dist*/) { // There is no kurtosis excess: @@ -2503,16 +2505,16 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const holtsmark_distribut "boost::math::kurtosis_excess(holtsmark<%1%>&)", "The Holtsmark distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const holtsmark_distribution& dist) { return detail::holtsmark_entropy_imp(dist); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_STATS_HOLTSMARK_HPP diff --git a/include/boost/math/distributions/hyperexponential.hpp b/include/boost/math/distributions/hyperexponential.hpp index 49f967d0fa..aa7b3af958 100644 --- a/include/boost/math/distributions/hyperexponential.hpp +++ b/include/boost/math/distributions/hyperexponential.hpp @@ -24,6 +24,7 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -32,6 +33,7 @@ #include #include #include +#endif #ifdef _MSC_VER @@ -40,7 +42,9 @@ # pragma warning(disable:4389) // '==' : signed/unsigned mismatch in test_tools #endif // _MSC_VER -namespace boost { namespace math { +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -50,11 +54,11 @@ typename Dist::value_type generic_quantile(const Dist& dist, const typename Dist } // Namespace detail -template +BOOST_MATH_EXPORT template class hyperexponential_distribution; -namespace /**/ { namespace hyperexp_detail { +namespace hyperexp_detail { template void normalize(std::vector& v) @@ -84,7 +88,7 @@ bool check_probabilities(char const* function, std::vector const& probabi { if (probabilities[i] < 0 || probabilities[i] > 1 - || !(boost::math::isfinite)(probabilities[i])) + || !(BOOST_MATH_NAMESPACE::isfinite)(probabilities[i])) { *presult = policies::raise_domain_error(function, "The elements of parameter \"probabilities\" must be >= 0 and <= 1, but at least one of them was: %1%.", @@ -118,7 +122,7 @@ bool check_rates(char const* function, std::vector const& rates, RealT* p for (std::size_t i = 0; i < n; ++i) { if (rates[i] <= 0 - || !(boost::math::isfinite)(rates[i])) + || !(BOOST_MATH_NAMESPACE::isfinite)(rates[i])) { *presult = policies::raise_domain_error(function, "The elements of parameter \"rates\" must be > 0, but at least one of them is: %1%.", @@ -150,7 +154,7 @@ bool check_dist(char const* function, std::vector const& probabilities, s template bool check_x(char const* function, RealT x, RealT* presult, PolicyT const& pol) { - if (x < 0 || (boost::math::isnan)(x)) + if (x < 0 || (BOOST_MATH_NAMESPACE::isnan)(x)) { *presult = policies::raise_domain_error(function, "The random variable must be >= 0, but is: %1%.", x, pol); return false; @@ -161,7 +165,7 @@ bool check_x(char const* function, RealT x, RealT* presult, PolicyT const& pol) template bool check_probability(char const* function, RealT p, RealT* presult, PolicyT const& pol) { - if (p < 0 || p > 1 || (boost::math::isnan)(p)) + if (p < 0 || p > 1 || (BOOST_MATH_NAMESPACE::isnan)(p)) { *presult = policies::raise_domain_error(function, "The probability be >= 0 and <= 1, but is: %1%.", p, pol); return false; @@ -235,10 +239,10 @@ RealT quantile_impl(hyperexponential_distribution const& dist, R return result; } -}} // Namespace ::hyperexp_detail +} // Namespace hyperexp_detail -template > +BOOST_MATH_EXPORT template > class hyperexponential_distribution { public: typedef RealT value_type; @@ -279,7 +283,7 @@ class hyperexponential_distribution }; template - struct is_iterator::difference_type>> + struct is_iterator::difference_type>> { // std::iterator_traits::difference_type returns void for invalid types static constexpr bool value = !std::is_same::difference_type, void>::value; @@ -395,11 +399,11 @@ public: hyperexponential_distribution(std::initializer_list l1) // Convenient type synonym for double. -typedef hyperexponential_distribution hyperexponential; +BOOST_MATH_EXPORT typedef hyperexponential_distribution hyperexponential; // Range of permissible values for random variable x -template +BOOST_MATH_EXPORT template std::pair range(hyperexponential_distribution const&) { if (std::numeric_limits::has_infinity) @@ -412,13 +416,13 @@ std::pair range(hyperexponential_distribution const& // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. -template +BOOST_MATH_EXPORT template std::pair support(hyperexponential_distribution const&) { return std::make_pair(tools::min_value(), tools::max_value()); // to +. } -template +BOOST_MATH_EXPORT template RealT pdf(hyperexponential_distribution const& dist, RealT const& x) { BOOST_MATH_STD_USING @@ -444,7 +448,7 @@ RealT pdf(hyperexponential_distribution const& dist, RealT const return result; } -template +BOOST_MATH_EXPORT template RealT cdf(hyperexponential_distribution const& dist, RealT const& x) { RealT result = 0; @@ -468,13 +472,13 @@ RealT cdf(hyperexponential_distribution const& dist, RealT const return result; } -template +BOOST_MATH_EXPORT template RealT quantile(hyperexponential_distribution const& dist, RealT const& p) { return hyperexp_detail::quantile_impl(dist, p , false); } -template +BOOST_MATH_EXPORT template RealT cdf(complemented2_type, RealT> const& c) { RealT const& x = c.param; @@ -502,7 +506,7 @@ RealT cdf(complemented2_type, RealT } -template +BOOST_MATH_EXPORT template RealT quantile(complemented2_type, RealT> const& c) { RealT const& p = c.param; @@ -511,7 +515,7 @@ RealT quantile(complemented2_type, return hyperexp_detail::quantile_impl(dist, p , true); } -template +BOOST_MATH_EXPORT template RealT mean(hyperexponential_distribution const& dist) { RealT result = 0; @@ -530,7 +534,7 @@ RealT mean(hyperexponential_distribution const& dist) return result; } -template +BOOST_MATH_EXPORT template RealT variance(hyperexponential_distribution const& dist) { RealT result = 0; @@ -544,14 +548,14 @@ RealT variance(hyperexponential_distribution const& dist) result += probs[i]/(rates[i]*rates[i]); } - const RealT mean = boost::math::mean(dist); + const RealT mean = BOOST_MATH_NAMESPACE::mean(dist); result = 2*result-mean*mean; return result; } -template +BOOST_MATH_EXPORT template RealT skewness(hyperexponential_distribution const& dist) { BOOST_MATH_STD_USING @@ -582,7 +586,7 @@ RealT skewness(hyperexponential_distribution const& dist) return num / pow(den, static_cast(1.5)); } -template +BOOST_MATH_EXPORT template RealT kurtosis(hyperexponential_distribution const& dist) { const std::size_t n = dist.num_phases(); @@ -615,19 +619,50 @@ RealT kurtosis(hyperexponential_distribution const& dist) return num/(den*den); } -template +BOOST_MATH_EXPORT template RealT kurtosis_excess(hyperexponential_distribution const& dist) { return kurtosis(dist) - 3; } -template +BOOST_MATH_EXPORT template RealT mode(hyperexponential_distribution const& /*dist*/) { return 0; } -}} // namespace boost::math +// Not GPU enabled: uses quadrature. +BOOST_MATH_EXPORT template +inline RealT entropy(const hyperexponential_distribution& dist) +{ + BOOST_MATH_STD_USING + // -int_0^inf f log(f) for the mixture f(x) = sum p_i lambda_i exp(-lambda_i x), which has no closed + // form. The integral is taken for U = c X, c = 1/E[X], so that the integrand's scale is ~1: + // H(X) = H(U) - log(c). + const std::vector probs = dist.probabilities(); + const std::vector rates = dist.rates(); + RealT c = 1 / mean(dist); + RealT min_rate = rates[0] / c; + for (std::size_t i = 1; i < rates.size(); ++i) + min_rate = (std::min)(min_rate, RealT(rates[i] / c)); + auto integrand = [&](RealT u) -> RealT + { + // f(u) = exp(-min_rate u) g(u), g(u) = sum p_i lambda_i exp(-(lambda_i - min_rate) u): + RealT g = 0; + for (std::size_t i = 0; i < rates.size(); ++i) + { + RealT l = rates[i] / c; + g += probs[i] * l * exp(-(l - min_rate) * u); + } + RealT log_f = log(g) - min_rate * u; + RealT f = exp(log_f); + return f == 0 ? RealT(0) : RealT(-f * log_f); + }; + quadrature::exp_sinh integrator; + return integrator.integrate(integrand, policies::get_epsilon() * 8) - log(c); +} + +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning (pop) diff --git a/include/boost/math/distributions/hypergeometric.hpp b/include/boost/math/distributions/hypergeometric.hpp index d7d1b6a069..6d51d1aa4b 100644 --- a/include/boost/math/distributions/hypergeometric.hpp +++ b/include/boost/math/distributions/hypergeometric.hpp @@ -15,12 +15,17 @@ #include #include #include +#include #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif + +#include -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN - template > + BOOST_MATH_EXPORT template > class hypergeometric_distribution { public: @@ -54,13 +59,13 @@ namespace boost { namespace math { { if(m_r > m_N) { - *result = boost::math::policies::raise_domain_error( + *result = BOOST_MATH_NAMESPACE::policies::raise_domain_error( function, "Parameter r out of range: must be <= N but got %1%", static_cast(m_r), Policy()); return false; } if(m_n > m_N) { - *result = boost::math::policies::raise_domain_error( + *result = BOOST_MATH_NAMESPACE::policies::raise_domain_error( function, "Parameter n out of range: must be <= N but got %1%", static_cast(m_n), Policy()); return false; } @@ -70,13 +75,13 @@ namespace boost { namespace math { { if(x < static_cast((std::max)(INT64_C(0), static_cast(m_n + m_r) - static_cast(m_N)))) { - *result = boost::math::policies::raise_domain_error( + *result = BOOST_MATH_NAMESPACE::policies::raise_domain_error( function, "Random variable out of range: must be > 0 and > m + r - N but got %1%", static_cast(x), Policy()); return false; } if(x > (std::min)(m_r, m_n)) { - *result = boost::math::policies::raise_domain_error( + *result = BOOST_MATH_NAMESPACE::policies::raise_domain_error( function, "Random variable out of range: must be less than both n and r but got %1%", static_cast(x), Policy()); return false; } @@ -91,9 +96,9 @@ namespace boost { namespace math { }; // class hypergeometric_distribution - typedef hypergeometric_distribution hypergeometric; + BOOST_MATH_EXPORT typedef hypergeometric_distribution hypergeometric; - template + BOOST_MATH_EXPORT template inline const std::pair range(const hypergeometric_distribution& dist) { // Range of permissible values for random variable x. #ifdef _MSC_VER @@ -111,13 +116,13 @@ namespace boost { namespace math { #endif } - template + BOOST_MATH_EXPORT template inline const std::pair support(const hypergeometric_distribution& d) { return range(d); } - template + BOOST_MATH_EXPORT template inline RealType pdf(const hypergeometric_distribution& dist, const std::uint64_t& x) { static const char* function = "boost::math::pdf(const hypergeometric_distribution<%1%>&, const %1%&)"; @@ -127,26 +132,38 @@ namespace boost { namespace math { if(!dist.check_x(x, function, &result)) return result; - return boost::math::detail::hypergeometric_pdf( + return BOOST_MATH_NAMESPACE::detail::hypergeometric_pdf( x, dist.defective(), dist.sample_count(), dist.total(), Policy()); } - template + BOOST_MATH_EXPORT template inline RealType pdf(const hypergeometric_distribution& dist, const U& x) { BOOST_MATH_STD_USING static const char* function = "boost::math::pdf(const hypergeometric_distribution<%1%>&, const %1%&)"; RealType r = static_cast(x); auto u = static_cast(lltrunc(r, typename policies::normalise >::type())); - if(u != r) + if(u == r) { - return boost::math::policies::raise_domain_error( - function, "Random variable out of range: must be an integer but got %1%", r, Policy()); + return pdf(dist, u); + } + // Non-integer x: the analytic continuation of C(r, x) C(N - r, n - x) / C(N, n). + RealType result = 0; + if(!dist.check_params(function, &result)) + return result; + const RealType lower = static_cast((std::max)(INT64_C(0), static_cast(dist.sample_count() + dist.defective()) - static_cast(dist.total()))); + const RealType upper = static_cast((std::min)(dist.defective(), dist.sample_count())); + if(!(BOOST_MATH_NAMESPACE::isfinite)(r) || !(r > lower) || !(r < upper)) + { + return BOOST_MATH_NAMESPACE::policies::raise_domain_error( + function, "Random variable out of range: must be between max(0, n + r - N) and min(n, r) but got %1%", r, Policy()); } - return pdf(dist, u); + // Here x > 0, so its truncation u is floor(x). + return BOOST_MATH_NAMESPACE::detail::hypergeometric_pdf_noninteger( + r, u, dist.defective(), dist.sample_count(), dist.total(), Policy()); } - template + BOOST_MATH_EXPORT template inline RealType cdf(const hypergeometric_distribution& dist, const std::uint64_t& x) { static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)"; @@ -156,11 +173,11 @@ namespace boost { namespace math { if(!dist.check_x(x, function, &result)) return result; - return boost::math::detail::hypergeometric_cdf( + return BOOST_MATH_NAMESPACE::detail::hypergeometric_cdf( x, dist.defective(), dist.sample_count(), dist.total(), false, Policy()); } - template + BOOST_MATH_EXPORT template inline RealType cdf(const hypergeometric_distribution& dist, const U& x) { BOOST_MATH_STD_USING @@ -169,13 +186,13 @@ namespace boost { namespace math { auto u = static_cast(lltrunc(r, typename policies::normalise >::type())); if(u != r) { - return boost::math::policies::raise_domain_error( + return BOOST_MATH_NAMESPACE::policies::raise_domain_error( function, "Random variable out of range: must be an integer but got %1%", r, Policy()); } return cdf(dist, u); } - template + BOOST_MATH_EXPORT template inline RealType cdf(const complemented2_type, std::uint64_t>& c) { static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)"; @@ -185,11 +202,11 @@ namespace boost { namespace math { if(!c.dist.check_x(c.param, function, &result)) return result; - return boost::math::detail::hypergeometric_cdf( + return BOOST_MATH_NAMESPACE::detail::hypergeometric_cdf( c.param, c.dist.defective(), c.dist.sample_count(), c.dist.total(), true, Policy()); } - template + BOOST_MATH_EXPORT template inline RealType cdf(const complemented2_type, U>& c) { BOOST_MATH_STD_USING @@ -198,13 +215,59 @@ namespace boost { namespace math { auto u = static_cast(lltrunc(r, typename policies::normalise >::type())); if(u != r) { - return boost::math::policies::raise_domain_error( + return BOOST_MATH_NAMESPACE::policies::raise_domain_error( function, "Random variable out of range: must be an integer but got %1%", r, Policy()); } return cdf(complement(c.dist, u)); } - template + namespace detail { + // + // hypergeometric_quantile sums the pdf to find the answer. Away from a + // step of the cdf that sum decides it; within rounding error of one the + // comparison with p is made using cdf() itself, as for the other discrete + // distributions, so that quantile(cdf(k)) == k. + // + template + inline typename Dist::value_type hypergeometric_round_quantile(const Dist& d, const hypergeometric_quantile_result& s, typename Dist::value_type p, bool c, const policies::discrete_quantile& tag) + { + typedef typename Dist::value_type value_type; + return s.ambiguous ? round_discrete_quantile(d, value_type(s.up), p, c, tag) : value_type(s.up); + } + template + inline typename Dist::value_type hypergeometric_round_quantile(const Dist& d, const hypergeometric_quantile_result& s, typename Dist::value_type p, bool c, const policies::discrete_quantile& tag) + { + typedef typename Dist::value_type value_type; + if (s.ambiguous) + return round_discrete_quantile(d, value_type(value_type(s.up) - 1), p, c, tag); + // cdf(up) > p clearly, so the answer is the integer below it, if any: + return s.up > support(d).first ? value_type(s.up - 1) : value_type(s.up); + } + template + inline typename Dist::value_type hypergeometric_round_quantile(const Dist& d, const hypergeometric_quantile_result& s, typename Dist::value_type p, bool c, const policies::discrete_quantile&) + { + return is_lower_quantile(p, c) + ? hypergeometric_round_quantile(d, s, p, c, policies::discrete_quantile()) + : hypergeometric_round_quantile(d, s, p, c, policies::discrete_quantile()); + } + template + inline typename Dist::value_type hypergeometric_round_quantile(const Dist& d, const hypergeometric_quantile_result& s, typename Dist::value_type p, bool c, const policies::discrete_quantile&) + { + return is_lower_quantile(p, c) + ? hypergeometric_round_quantile(d, s, p, c, policies::discrete_quantile()) + : hypergeometric_round_quantile(d, s, p, c, policies::discrete_quantile()); + } + template + inline typename Dist::value_type hypergeometric_round_quantile(const Dist& d, const hypergeometric_quantile_result& s, typename Dist::value_type p, bool c, const policies::discrete_quantile& tag) + { + // The nearer of up - 1 and up, as for the other distributions (which + // also never return more than up): + typedef typename Dist::value_type value_type; + return s.ambiguous ? round_discrete_quantile(d, value_type(s.nearest), p, c, tag) : value_type(s.nearest); + } + } // namespace detail + + BOOST_MATH_EXPORT template inline RealType quantile(const hypergeometric_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions @@ -218,10 +281,16 @@ namespace boost { namespace math { if(false == detail::check_probability(function, p, &result, Policy())) return result; - return static_cast(detail::hypergeometric_quantile(p, RealType(1 - p), dist.defective(), dist.sample_count(), dist.total(), Policy())); + // Only the ends of the support have cdf == 0 or 1 exactly, but the + // computed cdf can round to 0 or 1 further in, so handle them here: + if (p == 0) + return static_cast(support(dist).first); + if (p == 1) + return static_cast(support(dist).second); + return detail::hypergeometric_round_quantile(dist, detail::hypergeometric_quantile(p, RealType(1 - p), false, dist.defective(), dist.sample_count(), dist.total(), Policy()), p, false, typename Policy::discrete_quantile_type()); } // quantile - template + BOOST_MATH_EXPORT template inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -234,18 +303,23 @@ namespace boost { namespace math { if (false == detail::check_probability(function, c.param, &result, Policy())) return result; - return static_cast(detail::hypergeometric_quantile(RealType(1 - c.param), c.param, c.dist.defective(), c.dist.sample_count(), c.dist.total(), Policy())); + // As above: + if (c.param == 1) + return static_cast(support(c.dist).first); + if (c.param == 0) + return static_cast(support(c.dist).second); + return detail::hypergeometric_round_quantile(c.dist, detail::hypergeometric_quantile(RealType(1 - c.param), c.param, true, c.dist.defective(), c.dist.sample_count(), c.dist.total(), Policy()), c.param, true, typename Policy::discrete_quantile_type()); } // quantile // https://www.wolframalpha.com/input/?i=kurtosis+hypergeometric+distribution - template + BOOST_MATH_EXPORT template inline RealType mean(const hypergeometric_distribution& dist) { return static_cast(dist.defective() * dist.sample_count()) / dist.total(); } // RealType mean(const hypergeometric_distribution& dist) - template + BOOST_MATH_EXPORT template inline RealType variance(const hypergeometric_distribution& dist) { RealType r = static_cast(dist.defective()); @@ -254,7 +328,7 @@ namespace boost { namespace math { return n * r * (N - r) * (N - n) / (N * N * (N - 1)); } // RealType variance(const hypergeometric_distribution& dist) - template + BOOST_MATH_EXPORT template inline RealType mode(const hypergeometric_distribution& dist) { BOOST_MATH_STD_USING @@ -264,7 +338,7 @@ namespace boost { namespace math { return floor((r + 1) * (n + 1) / (N + 2)); } - template + BOOST_MATH_EXPORT template inline RealType skewness(const hypergeometric_distribution& dist) { BOOST_MATH_STD_USING @@ -274,7 +348,7 @@ namespace boost { namespace math { return (N - 2 * r) * sqrt(N - 1) * (N - 2 * n) / (sqrt(n * r * (N - r) * (N - n)) * (N - 2)); } // RealType skewness(const hypergeometric_distribution& dist) - template + BOOST_MATH_EXPORT template inline RealType kurtosis_excess(const hypergeometric_distribution& dist) { // https://www.wolframalpha.com/input/?i=kurtosis+hypergeometric+distribution shown as plain text: @@ -296,12 +370,111 @@ namespace boost { namespace math { return result; } // RealType kurtosis_excess(const hypergeometric_distribution& dist) - template + BOOST_MATH_EXPORT template inline RealType kurtosis(const hypergeometric_distribution& dist) { return kurtosis_excess(dist) + 3; } // RealType kurtosis_excess(const hypergeometric_distribution& dist) -}} // namespaces + // Not GPU enabled: the large-variance path uses Bernoulli numbers. + BOOST_MATH_EXPORT template + inline RealType entropy(const hypergeometric_distribution& dist) + { + BOOST_MATH_STD_USING + // No closed form: -sum p log(p) from the log ratios of the probabilities (detail::discrete_entropy_sum). + constexpr auto function = "boost::math::entropy(const hypergeometric_distribution<%1%>&)"; + RealType result = 0; + if (!dist.check_params(function, &result)) + return result; + const std::uint64_t r = dist.defective(); + const std::uint64_t n = dist.sample_count(); + const std::uint64_t N = dist.total(); + const std::uint64_t k_min = (n + r > N) ? n + r - N : 0; + const std::uint64_t k_max = (std::min)(n, r); + if (k_min == k_max) + return 0; + const RealType rr = static_cast(r); + const RealType nn = static_cast(n); + const RealType NN = static_cast(N); + // The mode, floor((r + 1)(n + 1) / (N + 2)); only the starting point of the sums: + std::uint64_t mode = (r + 1 <= UINT64_MAX / (n + 1)) + ? ((r + 1) * (n + 1)) / (N + 2) + : static_cast(std::floor(static_cast(r + 1) * static_cast(n + 1) / static_cast(N + 2))); + mode = (std::max)(k_min, (std::min)(k_max, mode)); + const RealType sigmas = detail::discrete_entropy_tail_sigmas(); + const RealType threshold = detail::entropy_series_threshold(); + RealType sigma = sqrt(nn * (rr / NN) * (1 - rr / NN) * (NN - nn) / (NN - 1)); + // log p(k) = -lgamma(k + 1) - lgamma(r - k + 1) - lgamma(n - k + 1) - lgamma(N - r - n + k + 1) + const: + const RealType z1 = static_cast(mode + 1); + const RealType z2 = static_cast(r - mode + 1); + const RealType z3 = static_cast(n - mode + 1); + const RealType z4 = static_cast(N + mode + 1 - r - n); + RealType margin = sigmas * sigma + threshold + 2; + if ((sigma >= 2 * sigmas) && ((std::min)((std::min)(z1, z2), (std::min)(z3, z4)) >= margin)) + { + // Trapezoidal rule on the continuation, with linear coefficient alpha = log(z2 z3 / (z1 z4)): + RealType alpha = BOOST_MATH_NAMESPACE::log1p(RealType(detail::difference_of_products(z2, z3, z1, z4) / (z1 * z4)), Policy()); + RealType h = sigma / detail::discrete_entropy_step_ratio(); + auto s_of = [&](RealType t) + { + return t * alpha - detail::entropy_lgamma_delta(z1, t, Policy()) - detail::entropy_lgamma_delta(z2, RealType(-t), Policy()) + - detail::entropy_lgamma_delta(z3, RealType(-t), Policy()) - detail::entropy_lgamma_delta(z4, t, Policy()); + }; + int j_right = 0; + int j_left = 0; + auto right = [&](RealType& s, RealType&) + { + RealType t = (++j_right) * h; + if ((std::min)(z2, z3) - t < threshold) + return false; + s = s_of(t); + return true; + }; + auto left = [&](RealType& s, RealType&) + { + RealType t = -(++j_left) * h; + if ((std::min)(z1, z4) + t < threshold) + return false; + s = s_of(t); + return true; + }; + return detail::discrete_entropy_sum(right, left, h, RealType(0), function, Policy()); + } + // Direct sum from the mode, with p(k + 1) / p(k) = (r - k)(n - k) / ((k + 1)(N - r - n + k + 1)), + // whose numerator minus denominator is (r + 1)(n + 1) - (k + 1)(N + 2): + std::uint64_t k_right = mode; + std::uint64_t k_left = mode; + detail::compensated_sum s_right; + detail::compensated_sum s_left; + auto log_ratio = [&](std::uint64_t k, RealType& ratio, bool left) + { + RealType kk = static_cast(k); + RealType num = (rr - kk) * (nn - kk); + RealType den = (kk + 1) * static_cast(N + k + 1 - r - n); + RealType d = detail::difference_of_products(RealType(rr + 1), RealType(nn + 1), RealType(kk + 1), RealType(NN + 2)); + return detail::entropy_log_ratio(num, den, d, ratio, left, Policy()); + }; + auto right = [&](RealType& s, RealType& ratio) + { + if (k_right == k_max) + return false; + s_right.add(log_ratio(k_right, ratio, false)); + k_right += 1; + s = s_right.value(); + return true; + }; + auto left = [&](RealType& s, RealType& ratio) + { + if (k_left == k_min) + return false; + k_left -= 1; + s_left.add(-log_ratio(k_left, ratio, true)); + s = s_left.value(); + return true; + }; + return detail::discrete_entropy_sum(right, left, RealType(1), RealType(0), function, Policy()); + } + +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/inverse_chi_squared.hpp b/include/boost/math/distributions/inverse_chi_squared.hpp index ca7e7f87e7..26b2fe1694 100644 --- a/include/boost/math/distributions/inverse_chi_squared.hpp +++ b/include/boost/math/distributions/inverse_chi_squared.hpp @@ -26,7 +26,11 @@ // Weisstein, Eric W. "Inverse Chi-Squared Distribution." From MathWorld--A Wolfram Web Resource. // http://mathworld.wolfram.com/InverseChi-SquaredDistribution.html -namespace boost{ namespace math{ +#ifndef BOOST_MATH_HAS_NVRTC +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -44,7 +48,7 @@ namespace detail } // bool check_inverse_chi_squared } // namespace detail -template > +BOOST_MATH_EXPORT template > class inverse_chi_squared_distribution { public: @@ -95,30 +99,30 @@ class inverse_chi_squared_distribution }; // class chi_squared_distribution -typedef inverse_chi_squared_distribution inverse_chi_squared; +BOOST_MATH_EXPORT typedef inverse_chi_squared_distribution inverse_chi_squared; #ifdef __cpp_deduction_guides -template -inverse_chi_squared_distribution(RealType)->inverse_chi_squared_distribution::type>; -template -inverse_chi_squared_distribution(RealType,RealType)->inverse_chi_squared_distribution::type>; +BOOST_MATH_EXPORT template +inverse_chi_squared_distribution(RealType)->inverse_chi_squared_distribution::type>; +BOOST_MATH_EXPORT template +inverse_chi_squared_distribution(RealType,RealType)->inverse_chi_squared_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const inverse_chi_squared_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const inverse_chi_squared_distribution& /*dist*/) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // 0 to + infinity. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // 0 to + infinity. } -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const inverse_chi_squared_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const inverse_chi_squared_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - return boost::math::pair(static_cast(0), tools::max_value()); // 0 to + infinity. + return BOOST_MATH_NAMESPACE::pair(static_cast(0), tools::max_value()); // 0 to + infinity. } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType pdf(const inverse_chi_squared_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions. @@ -134,7 +138,7 @@ BOOST_MATH_GPU_ENABLED RealType pdf(const inverse_chi_squared_distribution( function, "inverse Chi Square parameter was %1%, but must be >= 0 !", x, Policy()); @@ -158,7 +162,7 @@ BOOST_MATH_GPU_ENABLED RealType pdf(const inverse_chi_squared_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const inverse_chi_squared_distribution& dist, const RealType& x) { constexpr auto function = "boost::math::cdf(const inverse_chi_squared_distribution<%1%>&, %1%)"; @@ -172,7 +176,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const inverse_chi_squared_distributio { // Bad distribution. return error_result; } - if((x < 0) || !(boost::math::isfinite)(x)) + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) { // Bad x. return policies::raise_domain_error( function, "inverse Chi Square parameter was %1%, but must be >= 0 !", x, Policy()); @@ -184,13 +188,13 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const inverse_chi_squared_distributio // RealType shape = df /2; // inv_gamma shape, // RealType scale = df * scale/2; // inv_gamma scale, // result = boost::math::gamma_q(shape, scale / x, Policy()); // inverse_gamma code. - return boost::math::gamma_q(df / 2, (df * (scale / 2)) / x, Policy()); + return BOOST_MATH_NAMESPACE::gamma_q(df / 2, (df * (scale / 2)) / x, Policy()); } // cdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const inverse_chi_squared_distribution& dist, const RealType& p) { - using boost::math::gamma_q_inv; + using BOOST_MATH_NAMESPACE::gamma_q_inv; RealType df = dist.degrees_of_freedom(); RealType scale = dist.scale(); @@ -219,10 +223,10 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const inverse_chi_squared_distri return result; } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { - using boost::math::gamma_q_inv; + using BOOST_MATH_NAMESPACE::gamma_q_inv; RealType const& df = c.dist.degrees_of_freedom(); RealType const& scale = c.dist.scale(); RealType const& x = c.param; @@ -238,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type( function, "inverse Chi Square parameter was %1%, but must be > 0 !", x, Policy()); @@ -250,10 +254,50 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const inverse_chi_squared_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING + constexpr auto function = "boost::math::logcdf(const inverse_chi_squared_distribution<%1%>&, %1%)"; + RealType df = dist.degrees_of_freedom(); + RealType scale = dist.scale(); + RealType error_result; + if(false == detail::check_inverse_chi_squared(function, df, scale, &error_result, Policy())) + return error_result; + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) + { + return policies::raise_domain_error( + function, "inverse Chi Square parameter was %1%, but must be >= 0 !", x, Policy()); + } + if (x == 0) + return log(RealType(0)); + return BOOST_MATH_NAMESPACE::lgamma_q(df / 2, (df * (scale / 2)) / x, Policy()); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) +{ + RealType const& df = c.dist.degrees_of_freedom(); + RealType const& scale = c.dist.scale(); + RealType const& x = c.param; + constexpr auto function = "boost::math::logcdf(const inverse_chi_squared_distribution<%1%>&, %1%)"; + RealType error_result; + if(false == detail::check_df(function, df, &error_result, Policy())) + return error_result; + if (x == 0) + return 0; + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) + { + return policies::raise_domain_error( + function, "inverse Chi Square parameter was %1%, but must be > 0 !", x, Policy()); + } + return BOOST_MATH_NAMESPACE::lgamma_p(df / 2, (df * scale / 2) / x, Policy()); +} + +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { - using boost::math::gamma_q_inv; + using BOOST_MATH_NAMESPACE::gamma_q_inv; RealType const& df = c.dist.degrees_of_freedom(); RealType const& scale = c.dist.scale(); @@ -279,7 +323,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const inverse_chi_squared_distribution& dist) { // Mean of inverse Chi-Squared distribution. RealType df = dist.degrees_of_freedom(); @@ -294,7 +338,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const inverse_chi_squared_distributi return (df * scale) / (df - 2); } // mean -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const inverse_chi_squared_distribution& dist) { // Variance of inverse Chi-Squared distribution. RealType df = dist.degrees_of_freedom(); @@ -310,7 +354,7 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const inverse_chi_squared_distri return 2 * df * df * scale * scale / ((df - 2)*(df - 2) * (df - 4)); } // variance -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const inverse_chi_squared_distribution& dist) { // mode is not defined in Mathematica. // See Discussion section http://en.wikipedia.org/wiki/Talk:Scaled-inverse-chi-square_distribution @@ -340,7 +384,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mode(const inverse_chi_squared_distributi //} // Now implemented via quantile(half) in derived accessors. -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const inverse_chi_squared_distribution& dist) { BOOST_MATH_STD_USING // For ADL @@ -355,7 +399,7 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const inverse_chi_squared_distri return 4 * sqrt (2 * (df - 4)) / (df - 6); // Not a function of scale. } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const inverse_chi_squared_distribution& dist) { RealType df = dist.degrees_of_freedom(); @@ -369,7 +413,7 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const inverse_chi_squared_distri return kurtosis_excess(dist) + 3; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const inverse_chi_squared_distribution& dist) { RealType df = dist.degrees_of_freedom(); @@ -387,8 +431,19 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const inverse_chi_squared // Parameter estimation comes last: // -} // namespace math -} // namespace boost +#ifndef BOOST_MATH_HAS_NVRTC +// Not GPU enabled: the Stirling series use Bernoulli numbers. +BOOST_MATH_EXPORT template +inline RealType entropy(const inverse_chi_squared_distribution& dist) +{ + BOOST_MATH_STD_USING + // An inverse_gamma(df/2, df scale/2) distribution: + RealType df = dist.degrees_of_freedom(); + return log(df * dist.scale() / 2) + detail::inverse_gamma_entropy_unit_scale(RealType(df / 2), Policy()); +} +#endif + +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/inverse_gamma.hpp b/include/boost/math/distributions/inverse_gamma.hpp index 6aa798ed82..6c9b1f5776 100644 --- a/include/boost/math/distributions/inverse_gamma.hpp +++ b/include/boost/math/distributions/inverse_gamma.hpp @@ -31,8 +31,11 @@ #include #include -namespace boost{ namespace math -{ +#ifndef BOOST_MATH_HAS_NVRTC +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -47,7 +50,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_inverse_gamma_shape( // returning pdf and cdf zero (but not < 0). // (Functions like mean, variance with other limits on shape are checked // in version including an operator & limit below). - if((shape < 0) || !(boost::math::isfinite)(shape)) + if((shape < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(shape)) { *result = policies::raise_domain_error( function, @@ -63,7 +66,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_inverse_gamma_x( RealType const& x, RealType* result, const Policy& pol) { - if((x < 0) || !(boost::math::isfinite)(x)) + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) { *result = policies::raise_domain_error( function, @@ -86,7 +89,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_inverse_gamma( } // namespace detail -template > +BOOST_MATH_EXPORT template > class inverse_gamma_distribution { public: @@ -119,36 +122,36 @@ class inverse_gamma_distribution RealType m_scale; // distribution scale }; -using inverse_gamma = inverse_gamma_distribution; +BOOST_MATH_EXPORT using inverse_gamma = inverse_gamma_distribution; // typedef - but potential clash with name of inverse gamma *function*. // but there is a typedef for the gamma distribution (gamma) #ifdef __cpp_deduction_guides -template -inverse_gamma_distribution(RealType)->inverse_gamma_distribution::type>; -template -inverse_gamma_distribution(RealType,RealType)->inverse_gamma_distribution::type>; +BOOST_MATH_EXPORT template +inverse_gamma_distribution(RealType)->inverse_gamma_distribution::type>; +BOOST_MATH_EXPORT template +inverse_gamma_distribution(RealType,RealType)->inverse_gamma_distribution::type>; #endif // Allow random variable x to be zero, treated as a special case (unlike some definitions). -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const inverse_gamma_distribution& /* dist */) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const inverse_gamma_distribution& /* dist */) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const inverse_gamma_distribution& /* dist */) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const inverse_gamma_distribution& /* dist */) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - using boost::math::tools::min_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::min_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const inverse_gamma_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -195,18 +198,18 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const inverse_gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logpdf(const inverse_gamma_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions - using boost::math::lgamma; + using BOOST_MATH_NAMESPACE::lgamma; constexpr auto function = "boost::math::logpdf(const inverse_gamma_distribution<%1%>&, %1%)"; RealType shape = dist.shape(); RealType scale = dist.scale(); - RealType result = -boost::math::numeric_limits::infinity(); + RealType result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy())) { // distribution parameters bad. return result; @@ -224,7 +227,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const inverse_gamma_distribution(function, "PDF is infinite.", Policy()); } @@ -232,7 +235,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const inverse_gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const inverse_gamma_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -255,16 +258,16 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const inverse_gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const inverse_gamma_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions - using boost::math::gamma_q_inv; + using BOOST_MATH_NAMESPACE::gamma_q_inv; constexpr auto function = "boost::math::quantile(const inverse_gamma_distribution<%1%>&, %1%)"; @@ -287,7 +290,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const inverse_gamma_distribution return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -310,7 +313,40 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const inverse_gamma_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING + constexpr auto function = "boost::math::logcdf(const inverse_gamma_distribution<%1%>&, %1%)"; + RealType shape = dist.shape(); + RealType scale = dist.scale(); + RealType result = 0; + if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy())) + return result; + if (x == 0) + return log(RealType(0)); + if(false == detail::check_inverse_gamma_x(function, x, &result, Policy())) + return result; + return BOOST_MATH_NAMESPACE::lgamma_q(shape, scale / x, Policy()); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) +{ + constexpr auto function = "boost::math::logcdf(const inverse_gamma_distribution<%1%>&, %1%)"; + RealType shape = c.dist.shape(); + RealType scale = c.dist.scale(); + RealType result = 0; + if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy())) + return result; + if(false == detail::check_inverse_gamma_x(function, c.param, &result, Policy())) + return result; + if(c.param == 0) + return 0; + return BOOST_MATH_NAMESPACE::lgamma_p(shape, scale / c.param, Policy()); +} + +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -338,7 +374,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const inverse_gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -354,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const inverse_gamma_distribution( function, @@ -365,7 +401,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const inverse_gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const inverse_gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -380,7 +416,7 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const inverse_gamma_distribution { return result; } - if((shape <= 2) || !(boost::math::isfinite)(shape)) + if((shape <= 2) || !(BOOST_MATH_NAMESPACE::isfinite)(shape)) { result = policies::raise_domain_error( function, @@ -391,7 +427,7 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const inverse_gamma_distribution return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const inverse_gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -418,7 +454,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mode(const inverse_gamma_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const inverse_gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -433,7 +469,7 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const inverse_gamma_distribution { return result; } - if((shape <= 3) || !(boost::math::isfinite)(shape)) + if((shape <= 3) || !(BOOST_MATH_NAMESPACE::isfinite)(shape)) { result = policies::raise_domain_error( function, @@ -444,7 +480,7 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const inverse_gamma_distribution return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const inverse_gamma_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -459,7 +495,7 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const inverse_gamma_distr { return result; } - if((shape <= 4) || !(boost::math::isfinite)(shape)) + if((shape <= 4) || !(BOOST_MATH_NAMESPACE::isfinite)(shape)) { result = policies::raise_domain_error( function, @@ -470,7 +506,7 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const inverse_gamma_distr return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const inverse_gamma_distribution& dist) { constexpr auto function = "boost::math::kurtosis(const inverse_gamma_distribution<%1%>&)"; @@ -483,7 +519,7 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const inverse_gamma_distribution { return result; } - if((shape <= 4) || !(boost::math::isfinite)(shape)) + if((shape <= 4) || !(BOOST_MATH_NAMESPACE::isfinite)(shape)) { result = policies::raise_domain_error( function, @@ -493,8 +529,18 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const inverse_gamma_distribution return kurtosis_excess(dist) + 3; } -} // namespace math -} // namespace boost +#ifndef BOOST_MATH_HAS_NVRTC +// Not GPU enabled: the Stirling series use Bernoulli numbers. +BOOST_MATH_EXPORT template +inline RealType entropy(const inverse_gamma_distribution& dist) +{ + BOOST_MATH_STD_USING + // a + log(scale) + lgamma(a) - (1 + a) digamma(a): + return log(dist.scale()) + detail::inverse_gamma_entropy_unit_scale(dist.shape(), Policy()); +} +#endif + +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/inverse_gaussian.hpp b/include/boost/math/distributions/inverse_gaussian.hpp index 795ad23d4a..b3ff82f9fe 100644 --- a/include/boost/math/distributions/inverse_gaussian.hpp +++ b/include/boost/math/distributions/inverse_gaussian.hpp @@ -62,9 +62,18 @@ #include #include -namespace boost{ namespace math{ +#ifndef BOOST_MATH_HAS_NVRTC +#include +#endif + +#ifndef BOOST_MATH_HAS_NVRTC +#include +#include +#endif -template > +BOOST_MATH_NAMESPACE_BEGIN + +BOOST_MATH_EXPORT template > class inverse_gaussian_distribution { public: @@ -110,31 +119,31 @@ class inverse_gaussian_distribution RealType m_scale; // distribution standard deviation or scale, aka lambda. }; // class normal_distribution -using inverse_gaussian = inverse_gaussian_distribution; +BOOST_MATH_EXPORT using inverse_gaussian = inverse_gaussian_distribution; #ifdef __cpp_deduction_guides -template -inverse_gaussian_distribution(RealType)->inverse_gaussian_distribution::type>; -template -inverse_gaussian_distribution(RealType,RealType)->inverse_gaussian_distribution::type>; +BOOST_MATH_EXPORT template +inverse_gaussian_distribution(RealType)->inverse_gaussian_distribution::type>; +BOOST_MATH_EXPORT template +inverse_gaussian_distribution(RealType,RealType)->inverse_gaussian_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const inverse_gaussian_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const inverse_gaussian_distribution& /*dist*/) { // Range of permissible values for random variable x, zero to max. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0.), max_value()); // - to + max value. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0.), max_value()); // - to + max value. } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const inverse_gaussian_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const inverse_gaussian_distribution& /*dist*/) { // Range of supported values for random variable x, zero to max. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0.), max_value()); // - to + max value. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0.), max_value()); // - to + max value. } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const inverse_gaussian_distribution& dist, const RealType& x) { // Probability Density Function BOOST_MATH_STD_USING // for ADL of std functions @@ -171,14 +180,14 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const inverse_gaussian_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logpdf(const inverse_gaussian_distribution& dist, const RealType& x) { // Probability Density Function BOOST_MATH_STD_USING // for ADL of std functions RealType scale = dist.scale(); RealType mean = dist.mean(); - RealType result = -boost::math::numeric_limits::infinity(); + RealType result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); constexpr auto function = "boost::math::logpdf(const inverse_gaussian_distribution<%1%>&, %1%)"; if(false == detail::check_scale(function, scale, &result, Policy())) { @@ -199,16 +208,39 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const inverse_gaussian_distributio if (x == 0) { - return boost::math::numeric_limits::quiet_NaN(); // Convenient, even if not defined mathematically. log(0) + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // Convenient, even if not defined mathematically. log(0) } - const RealType two_pi = boost::math::constants::two_pi(); + const RealType two_pi = BOOST_MATH_NAMESPACE::constants::two_pi(); result = (-scale*pow(mean - x, RealType(2))/(mean*mean*x) + log(scale) - 3*log(x) - log(two_pi)) / 2; return result; } // pdf +namespace detail { + template +BOOST_MATH_GPU_ENABLED inline RealType inverse_gaussian_cdf_second_term(RealType a, RealType b, RealType shape) +{ + BOOST_MATH_STD_USING + // Phi(-b) underflows, and loses its digits as a subnormal first, long before the result does: + if ((shape < tools::log_max_value() / 4) && (b * b < -tools::log_min_value())) + return exp(2 * shape) * cdf(complement(normal_distribution(), b)); + + // exp(2 * shape) * Phi(-b) = exp(-a*a/2) * erfcx(b/sqrt(2)) / 2. + RealType e = exp(-a * a / 2); + if (e == 0) + return 0; + // z*z >= 2*shape, so the continued fraction is only used for large z. + RealType z = b / constants::root_two(); + RealType z_squared = z * z; + return e * z * upper_gamma_fraction(RealType(0.5f), z_squared, policies::get_epsilon()) + / (2 * constants::root_pi()); +} + +} // namespace detail + +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const inverse_gaussian_distribution& dist, const RealType& x) { // Cumulative Density Function. BOOST_MATH_STD_USING // for ADL of std functions. @@ -246,11 +278,9 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const inverse_gaussian_distribution(n0, n3, scale / mean); return result; } // cdf @@ -258,41 +288,41 @@ template struct inverse_gaussian_quantile_functor { - BOOST_MATH_GPU_ENABLED inverse_gaussian_quantile_functor(const boost::math::inverse_gaussian_distribution dist, RealType const& p) + BOOST_MATH_GPU_ENABLED inverse_gaussian_quantile_functor(const BOOST_MATH_NAMESPACE::inverse_gaussian_distribution dist, RealType const& p) : distribution(dist), prob(p) { } - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(RealType const& x) + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(RealType const& x) { RealType c = cdf(distribution, x); RealType fx = c - prob; // Difference cdf - value - to minimize. RealType dx = pdf(distribution, x); // pdf is 1st derivative. // return both function evaluation difference f(x) and 1st derivative f'(x). - return boost::math::make_tuple(fx, dx); + return BOOST_MATH_NAMESPACE::make_tuple(fx, dx); } private: - const boost::math::inverse_gaussian_distribution distribution; + const BOOST_MATH_NAMESPACE::inverse_gaussian_distribution distribution; RealType prob; }; template struct inverse_gaussian_quantile_complement_functor { - BOOST_MATH_GPU_ENABLED inverse_gaussian_quantile_complement_functor(const boost::math::inverse_gaussian_distribution dist, RealType const& p) + BOOST_MATH_GPU_ENABLED inverse_gaussian_quantile_complement_functor(const BOOST_MATH_NAMESPACE::inverse_gaussian_distribution dist, RealType const& p) : distribution(dist), prob(p) { } - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(RealType const& x) + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(RealType const& x) { RealType c = cdf(complement(distribution, x)); RealType fx = c - prob; // Difference cdf - value - to minimize. RealType dx = -pdf(distribution, x); // pdf is 1st derivative. // return both function evaluation difference f(x) and 1st derivative f'(x). //return std::tr1::make_tuple(fx, dx); if available. - return boost::math::make_tuple(fx, dx); + return BOOST_MATH_NAMESPACE::make_tuple(fx, dx); } private: - const boost::math::inverse_gaussian_distribution distribution; + const BOOST_MATH_NAMESPACE::inverse_gaussian_distribution distribution; RealType prob; }; @@ -302,11 +332,11 @@ namespace detail BOOST_MATH_GPU_ENABLED inline RealType guess_ig(RealType p, RealType q, RealType mu, RealType lambda) { // guess at random variate value x for inverse gaussian quantile. BOOST_MATH_STD_USING - using boost::math::policies::policy; + using BOOST_MATH_NAMESPACE::policies::policy; // Error type. - using boost::math::policies::overflow_error; + using BOOST_MATH_NAMESPACE::policies::overflow_error; // Action. - using boost::math::policies::ignore_error; + using BOOST_MATH_NAMESPACE::policies::ignore_error; using no_overthrow_policy = policy>; @@ -339,7 +369,7 @@ namespace detail } // guess_ig } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const inverse_gaussian_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions. @@ -370,7 +400,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const inverse_gaussian_distribut } RealType guess = detail::guess_ig(p, RealType(1 - p), dist.mean(), dist.scale()); - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; RealType min = static_cast(0); // Minimum possible value is bottom of range of distribution. RealType max = max_value();// Maximum possible value is top of range. @@ -378,13 +408,13 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const inverse_gaussian_distribut // digits used to control how accurate to try to make the result. // To allow user to control accuracy versus speed, int get_digits = policies::digits();// get digits from policy, - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); // and max iterations. - using boost::math::tools::newton_raphson_iterate; + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); // and max iterations. + using BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate; inverse_gaussian_quantile_functor func(dist, p); // // Our guess is often not very good, so lets bracket the root just in case: // - RealType f0 = boost::math::get<0>(func(guess)); + RealType f0 = BOOST_MATH_NAMESPACE::get<0>(func(guess)); if (f0 < 0) tools::detail::bracket_root_towards_max(func, guess, f0, min, max, max_iter); else @@ -401,7 +431,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const inverse_gaussian_distribut return result; } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions. @@ -426,18 +456,13 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type(n0, n3, scale / mean); return result; } // cdf complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -458,17 +483,17 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type(0); // Minimum possible value is bottom of range of distribution. RealType max = max_value();// Maximum possible value is top of range. // int digits = std::numeric_limits::digits; // Maximum possible binary digits accuracy for type T. // digits used to control how accurate to try to make the result. int get_digits = policies::digits(); - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); - using boost::math::tools::newton_raphson_iterate; + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); + using BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate; inverse_gaussian_quantile_complement_functor func(c.dist, q); - RealType f0 = boost::math::get<0>(func(guess)); + RealType f0 = BOOST_MATH_NAMESPACE::get<0>(func(guess)); if (f0 > 0) tools::detail::bracket_root_towards_max(func, guess, f0, min, max, max_iter); else @@ -486,7 +511,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const inverse_gaussian_distribution& dist) { // aka mu return dist.mean(); @@ -504,7 +529,7 @@ BOOST_MATH_GPU_ENABLED inline RealType shape(const inverse_gaussian_distribution return dist.shape(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const inverse_gaussian_distribution& dist) { BOOST_MATH_STD_USING @@ -514,7 +539,7 @@ BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const inverse_gaussian return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const inverse_gaussian_distribution& dist) { BOOST_MATH_STD_USING @@ -525,7 +550,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mode(const inverse_gaussian_distribution< return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const inverse_gaussian_distribution& dist) { BOOST_MATH_STD_USING @@ -535,7 +560,7 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const inverse_gaussian_distribut return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const inverse_gaussian_distribution& dist) { RealType scale = dist.scale(); @@ -544,7 +569,7 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const inverse_gaussian_distribut return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const inverse_gaussian_distribution& dist) { RealType scale = dist.scale(); @@ -553,8 +578,74 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const inverse_gaussian_di return result; } -} // namespace math -} // namespace boost +#ifndef BOOST_MATH_HAS_NVRTC +namespace detail { +// exp(x) E1(x) for x >= 1. +template +inline RealType inverse_gaussian_scaled_e1(RealType x, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (x < 50) + return exp(x) * BOOST_MATH_NAMESPACE::expint(1, x, pol); + // Continued fraction 1/(x + 1 - 1/(x + 3 - 4/(x + 5 - ...))), by the modified Lentz method: + const RealType eps = policies::get_epsilon(); + const RealType tiny = tools::min_value() * 16; + RealType f = x + 1; + RealType c = f; + RealType d = 0; + for (int n = 1; n < 1000; ++n) + { + RealType an = -RealType(n) * n; + RealType bn = x + 2 * n + 1; + d = bn + an * d; + if (d == 0) d = tiny; + c = bn + an / c; + if (c == 0) c = tiny; + d = 1 / d; + RealType delta = c * d; + f *= delta; + if (fabs(delta - 1) <= eps) + break; + } + return 1 / f; +} +} // namespace detail + +// Not GPU enabled: uses expint. +BOOST_MATH_EXPORT template +inline RealType entropy(const inverse_gaussian_distribution& dist) +{ + BOOST_MATH_STD_USING + // With phi = lambda/mu, E[log X] = log(mu) - exp(2 phi) E1(2 phi), so + // H = log(mu) + log(2 pi e / phi)/2 - (3/2) exp(2 phi) E1(2 phi). + RealType mu = dist.mean(); + RealType lambda = dist.scale(); + RealType phi = lambda / mu; + RealType x = 2 * phi; + if (x < 1) + { + // log(mu) = log(lambda) - log(phi), and log(phi) + exp(x) E1(x) cancels for small x; with + // E1(x) = -euler - log(x) + Ein(x), Ein(x) = sum_{k >= 1} (-1)^(k+1) x^k / (k k!), it is + // -expm1(x) log(x) + exp(x) (Ein(x) - euler) - log(2). + const RealType eps = policies::get_epsilon(); + RealType ein = 0; + RealType term = 1; + for (int k = 1; k < 1000; ++k) + { + term *= -x / k; + ein -= term / k; + if (fabs(term) <= eps * fabs(ein) * k) + break; + } + RealType bracket = -BOOST_MATH_NAMESPACE::expm1(x, Policy()) * log(x) + exp(x) * (ein - constants::euler()) - constants::ln_two(); + return log(lambda) + constants::log_root_two_pi() + constants::half() - 3 * bracket / 2; + } + return log(mu) + constants::log_root_two_pi() + constants::half() - log(phi) / 2 + - 3 * detail::inverse_gaussian_scaled_e1(x, Policy()) / 2; +} +#endif + +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to @@ -562,5 +653,3 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const inverse_gaussian_di #include #endif // BOOST_STATS_INVERSE_GAUSSIAN_HPP - - diff --git a/include/boost/math/distributions/kolmogorov_smirnov.hpp b/include/boost/math/distributions/kolmogorov_smirnov.hpp index 0934344134..c4ae33ff8d 100644 --- a/include/boost/math/distributions/kolmogorov_smirnov.hpp +++ b/include/boost/math/distributions/kolmogorov_smirnov.hpp @@ -79,15 +79,26 @@ // The PDF is a hand-coded derivative of that function. Actually, there are two // (independent) derivatives, as separate code paths are used for "small x" // (2*x*x*n < pi) and "large x", mirroring the separate code paths in the -// Jacobi Theta implementation to achieve fast convergence. Quantiles are -// computed using a Newton-Raphson iteration from an initial guess that I -// arrived at by trial and error. +// Jacobi Theta implementation to achieve fast convergence. Each path evaluates +// a single exponential and obtains the remaining terms of the series by +// multiplication; the rounding error in the exponent x*x*n is tracked +// explicitly so that it is not amplified by the size of the exponent. +// +// Quantiles are computed by a Newton-Raphson iteration, but not directly in x: +// the lower tail is solved in terms of W = pi^2/(8*x*x*n) and the upper tail +// in terms of V = x*x*n, using the logarithm of the CDF (or its complement) as +// the residual. In these variables the residual is very nearly linear, so the +// iteration converges from anywhere, and the starting point (an inversion of +// the leading terms of the series) is already accurate to a fraction of a +// percent, and to working precision in the tails. // // The mean and variance are implemented using simple closed-form expressions. // Skewness and kurtosis use slightly more complicated closed-form expressions -// that involve the zeta function. The mode is calculated at run-time by -// maximizing the PDF. If you have an analytical solution for the mode, feel -// free to plop it in. +// that involve the zeta function; since these (like the mode and the median) +// do not depend on n except through a factor of sqrt(n), they are stored as +// constants of the standardized (n=1) distribution accurate to 100 decimal +// digits, and only computed at run-time for types with more precision than +// that. // // The CDF and PDF could almost certainly be re-implemented and sped up using a // polynomial or rational approximation, since the only meaningful argument is @@ -111,82 +122,192 @@ #include #include #include +#include +#include +#include #include #include // Newton-Raphson -#include // For the mode -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { + +// Constants of the standardized (n=1) distribution, accurate to 100 decimal +// digits. Each accessor scales by the appropriate power of n. Types with more +// precision than the constant (as requested by the policy) fall back to a +// run-time computation. +template +inline bool kolmogorov_smirnov_use_constants(const Policy&) { + return policies::digits() <= 330; +} + +template +inline RealType kolmogorov_smirnov_mode_constant() { + return BOOST_MATH_BIG_CONSTANT(RealType, 1000, 0.7354679079165719820624448513051825390913503143340225122926732679283442751250018638342479353073554823); +} + template -inline RealType kolmogorov_smirnov_quantile_guess(RealType p) { - // Choose a starting point for the Newton-Raphson iteration - if (p > 0.9) - return RealType(1.8) - 5 * (1 - p); - if (p < 0.3) - return p + RealType(0.45); - return p + RealType(0.3); +inline RealType kolmogorov_smirnov_median_constant() { + return BOOST_MATH_BIG_CONSTANT(RealType, 1000, 0.8275735551899076901138270828889768075843727832232029452002281054669822747682290224084911530683945353); } -// d/dk (theta2(0, 1/(2*k*k/M_PI))/sqrt(2*k*k*M_PI)) +template +inline RealType kolmogorov_smirnov_skewness_constant() { + return BOOST_MATH_BIG_CONSTANT(RealType, 1000, 0.8604261371436682558667183685173007452393495203060929924698665373211030237490355834020123201092217303); +} + +template +inline RealType kolmogorov_smirnov_kurtosis_excess_constant() { + return BOOST_MATH_BIG_CONSTANT(RealType, 1000, 0.8816189679105236704015538304328295408355055629289034536289160037385510119639244078254098968815665536); +} + +// Given u = x*x*n as computed in floating point, returns the rounding error +// in u, so that exp(-c*u) can be evaluated as exp(-c*u) * (1 - c*err) +// without the rounding error of u being amplified by the size of the +// exponent c*u. +template +inline RealType kolmogorov_smirnov_x2n_error(RealType x, RealType n, RealType u) { + two_product product; + RealType x2 = x * x; + RealType e1 = product.error(x, x, x2); + RealType e2 = product.error(x2, n, u); + return e2 + e1 * n; // x*x*n == u + err +} + +// The nome q = exp(-2*x*x*n) of the theta function in the CDF, with the +// rounding of x*x*n compensated. Passing q rather than tau = 2*x*x*n/pi +// matters when 2*x*x*n > pi: the theta function then raises q to integer +// powers, so nothing amplifies the rounding, whereas any rounding of tau is +// multiplied back by the size of the exponent. +template +inline RealType kolmogorov_smirnov_nome(RealType x, RealType n) { + BOOST_MATH_STD_USING + RealType u = x * x * n; + RealType q = exp(-2 * u); + if (q == 0) + return q; + RealType err = kolmogorov_smirnov_x2n_error(x, n, u); + return q * (1 - 2 * err); // exp(-2 (u + err)) +} + +// Returns pi^2/8 as hi + lo, where hi is exactly representable and lo is +// its complement to about 120 bits, so that W = (pi^2/8)/u can be computed +// without the rounding error of the constant being amplified by W. Types +// with more than 116 bits of precision simply use their own rounding of the +// constant (lo = 0). +template +inline RealType kolmogorov_smirnov_pi_sqr_div_eight(RealType& lo) { + BOOST_MATH_STD_USING + if (tools::digits() > 116) { + lo = 0; + return constants::pi_sqr() / 8; + } + // Five pieces of 24 significant bits each; every one is exact in any + // binary floating-point type with at least 24 bits. + lo = ldexp(RealType(5108270), -47) + ldexp(RealType(15913558), -71) + ldexp(RealType(14839001), -95) + ldexp(RealType(8424474), -119); + return ldexp(RealType(10349030), -23); +} + +// d/dx (theta2(0, pi/(2*x*x*n))/sqrt(2*x*x*n)) - valid for all x but converges +// quickly when 2*x*x*n < pi. With u = x*x*n and W = pi^2/(8u): +// +// pdf = sqrt(2*pi*n)/u^2 * SUM_{i>=0} exp(-(2i+1)^2 W) * ((i+1/2)^2 pi^2 - u) template RealType kolmogorov_smirnov_pdf_small_x(RealType x, RealType n, const Policy&) { BOOST_MATH_STD_USING - RealType value = RealType(0), delta = RealType(0), last_delta = RealType(0); RealType eps = policies::get_epsilon(); - int i = 0; RealType pi2 = constants::pi_sqr(); - RealType x2n = x*x*n; - if (x2n*x2n == 0.0) { + RealType u = x * x * n; + if (u == 0) return static_cast(0); + RealType c_lo; + RealType c_hi = kolmogorov_smirnov_pi_sqr_div_eight(c_lo); + RealType W = (c_hi + c_lo) / u; + RealType r = exp(-W); + RealType half = 0; + if (r < tools::min_value()) { + // exp(-W) is subnormal or zero although the result, which is larger + // by a factor of order 1/u^2, may not be: only the leading term + // contributes, and it is evaluated below as a square of exp(-W/2) + // to avoid the intermediate underflow. + half = exp(-W / 2); + if (half == 0) + return static_cast(0); } - while (true) { - delta = exp(-RealType(i+0.5)*RealType(i+0.5)*pi2/(2*x2n)) * (RealType(i+0.5)*RealType(i+0.5)*pi2 - x2n); - - if (delta == 0.0) - break; - - if (last_delta != 0.0 && fabs(delta/last_delta) < eps) - break; + // The rounding errors in the constant, in u and in the division, to + // second order, so that exp(-W) can be corrected by a factor (1 - delta): + // W_exact = W + delta, delta = ((c_hi + c_lo) - W*u - W*err) / u, u_exact = u + err + RealType err = kolmogorov_smirnov_x2n_error(x, n, u); + RealType Wu, eWu; + two_product()(W, u, Wu, eWu); + RealType delta = ((((c_hi - Wu) - eWu) + c_lo) - W * err) / u; + if (half != 0) { + RealType leading = half * (1 - delta / 2) * sqrt(constants::root_two_pi() * sqrt(n) * (pi2 / 4 - u)) / u; + return leading * leading; + } + r *= (1 - delta); // exp(-(W + delta)) + RealType r8 = r * r; + r8 *= r8; + r8 *= r8; - value += delta + delta; - last_delta = delta; + // pw = r^((2i+1)^2), mult = r^(8(i+1)): pw_{i+1} = pw_i * mult_i + RealType sum = 0, term, pw = r, mult = r8; + int i = 0; + do { + term = pw * (RealType(i + 0.5) * RealType(i + 0.5) * pi2 - u); + sum += term; + pw *= mult; + mult *= r8; i++; - } + } while (term > eps * sum); - return value * sqrt(n) * constants::root_half_pi() / (x2n*x2n); + return sum * constants::root_two_pi() * sqrt(n) / (u * u); } -// d/dx (theta4(0, 2*x*x*n/M_PI)) +// d/dx (theta4(0, 2*x*x*n/pi)) - valid for all x but converges quickly when +// 2*x*x*n > pi. With u = x*x*n: +// +// pdf = 8*x*n * SUM_{i>=1} (-1)^(i+1) i^2 exp(-2 i^2 u) template inline RealType kolmogorov_smirnov_pdf_large_x(RealType x, RealType n, const Policy&) { BOOST_MATH_STD_USING - RealType value = RealType(0), delta = RealType(0), last_delta = RealType(0); RealType eps = policies::get_epsilon(); - int i = 1; - while (true) { - delta = 8*x*i*i*exp(-2*i*i*x*x*n); - - if (delta == 0.0) - break; - - if (last_delta != 0.0 && fabs(delta / last_delta) < eps) - break; - - if (i%2 == 0) - delta = -delta; + RealType u = x * x * n; + RealType r = exp(-2 * u); + if (r < tools::min_value()) { + // As above: evaluate the leading term as a square so that it does + // not lose precision to an intermediate underflow. + RealType half = exp(-u); + if (half == 0) + return static_cast(0); + RealType err = kolmogorov_smirnov_x2n_error(x, n, u); + RealType leading = half * (1 - err) * sqrt(8 * x * n); + return leading * leading; + } + RealType err = kolmogorov_smirnov_x2n_error(x, n, u); + r *= (1 - 2 * err); // exp(-2 (u + err)) + RealType r2 = r * r; - value += delta; - last_delta = delta; + // pw = r^(i^2), odd = r^(2i+1): pw_{i+1} = pw_i * odd_i + RealType sum = 0, term, pw = r, odd = r2 * r; + int i = 1; + do { + term = RealType(i) * RealType(i) * pw; + if (i % 2 == 0) + sum -= term; + else + sum += term; + pw *= odd; + odd *= r2; i++; - } + } while (term > eps * sum); - return value * n; + return 8 * x * n * sum; } } // detail -template > +BOOST_MATH_EXPORT template > class kolmogorov_smirnov_distribution { public: @@ -211,83 +332,192 @@ template > RealType n_obs_; // positive integer }; -typedef kolmogorov_smirnov_distribution kolmogorov_k; // Convenience typedef for double version. +BOOST_MATH_EXPORT typedef kolmogorov_smirnov_distribution kolmogorov_k; // Convenience typedef for double version. #ifdef __cpp_deduction_guides -template -kolmogorov_smirnov_distribution(RealType)->kolmogorov_smirnov_distribution::type>; +BOOST_MATH_EXPORT template +kolmogorov_smirnov_distribution(RealType)->kolmogorov_smirnov_distribution::type>; #endif namespace detail { + +// The quantile is found by Newton-Raphson iteration in a transformed variable +// in which the (logarithm of the) CDF is very nearly linear: +// +// Lower tail, W = pi^2 / (8*x*x*n): +// ln cdf(x) = ln(4/sqrt(pi)) + ln(W)/2 - W + ln(1 + exp(-8W) + exp(-24W) + ...) +// +// Upper tail, V = x*x*n: +// ln(1 - cdf(x)) = ln(2) - 2V + ln(1 - exp(-6V) + exp(-16V) - ...) +// +// The lower form is used when the lower tail probability p is less than 0.6, +// and the upper form otherwise (with q = 1 - p). The starting values below +// invert the first two terms of each expansion; the neglected terms are +// smaller than the working precision for most of each region, in which case +// the iteration returns after a single evaluation. + +// Solves W - ln(W)/2 - ln(1 + exp(-8W)) = L for the starting value of W, +// L = ln(4/sqrt(pi)) - ln(p). The iteration converges quadratically from +// the asymptotic starting point L + ln(L)/2. +template +inline RealType kolmogorov_smirnov_lower_guess(RealType p) { + BOOST_MATH_STD_USING + RealType L = 2 * constants::ln_two() - constants::log_pi() / 2 - log(p); + RealType W = (L > 1) ? L + log(L) / 2 : RealType(1); + for (int i = 0; i < 3; i++) { + RealType e = exp(-8 * W); + RealType h = W - log(W) / 2 - BOOST_MATH_NAMESPACE::log1p(e) - L; + RealType dh = 1 - 1 / (2 * W) + 8 * e / (1 + e); + W -= h / dh; + } + return W; +} + +// Solves 2 * (t - t^4 + t^9 - t^16) = q for t = exp(-2V), a polynomial +// equation that converges in a few steps from t = q/2 when q <= 0.4, and +// returns the starting value V = -ln(t)/2. The iteration is carried out on +// the ratio r = t / (q/2) so that q may be arbitrarily small. +template +inline RealType kolmogorov_smirnov_upper_guess(RealType q) { + BOOST_MATH_STD_USING + RealType t0 = q / 2; + RealType a = t0 * t0 * t0; + RealType b = a * a * t0 * t0; + RealType c = b * a * a * t0; + RealType r = 1; + for (int i = 0; i < 3; i++) { + RealType r3 = r * r * r; + RealType r8 = r3 * r3 * r * r; + RealType r15 = r8 * r3 * r3 * r; + RealType phi = (r - 1) - a * r3 * r + b * r8 * r - c * r15 * r; + RealType dphi = 1 - 4 * a * r3 + 9 * b * r8 - 16 * c * r15; + r -= phi / dphi; + } + return -(log(q) - constants::ln_two() + BOOST_MATH_NAMESPACE::log1p(r - 1)) / 2; +} + template -struct kolmogorov_smirnov_quantile_functor +struct kolmogorov_smirnov_lower_quantile_functor { - kolmogorov_smirnov_quantile_functor(const boost::math::kolmogorov_smirnov_distribution dist, RealType const& p) - : distribution(dist), prob(p) - { - } - - boost::math::tuple operator()(RealType const& x) - { - RealType fx = cdf(distribution, x) - prob; // Difference cdf - value - to minimize. - RealType dx = pdf(distribution, x); // pdf is 1st derivative. - // return both function evaluation difference f(x) and 1st derivative f'(x). - return boost::math::make_tuple(fx, dx); - } + kolmogorov_smirnov_lower_quantile_functor(const kolmogorov_smirnov_distribution& dist, RealType const& p) + : distribution(dist), scale(constants::pi_sqr() / (8 * dist.number_of_observations())) + { + BOOST_MATH_STD_USING // not in scope in a member initializer + log_prob = log(p); + } + + BOOST_MATH_NAMESPACE::tuple operator()(RealType const& W) + { + BOOST_MATH_STD_USING + RealType x = sqrt(scale / W); + RealType F = cdf(distribution, x); + RealType f = pdf(distribution, x); + // g(W) = ln F(x(W)) - ln p ; dg/dW = (f/F) * dx/dW, dx/dW = -x/(2W) + return BOOST_MATH_NAMESPACE::make_tuple(log(F) - log_prob, -f * x / (2 * W * F)); + } private: - const boost::math::kolmogorov_smirnov_distribution distribution; - RealType prob; + const kolmogorov_smirnov_distribution& distribution; + RealType log_prob; + RealType scale; }; template -struct kolmogorov_smirnov_complementary_quantile_functor +struct kolmogorov_smirnov_upper_quantile_functor { - kolmogorov_smirnov_complementary_quantile_functor(const boost::math::kolmogorov_smirnov_distribution dist, RealType const& p) - : distribution(dist), prob(p) - { - } - - boost::math::tuple operator()(RealType const& x) - { - RealType fx = cdf(complement(distribution, x)) - prob; // Difference cdf - value - to minimize. - RealType dx = -pdf(distribution, x); // pdf is the negative of the derivative of (1-CDF) - // return both function evaluation difference f(x) and 1st derivative f'(x). - return boost::math::make_tuple(fx, dx); - } + kolmogorov_smirnov_upper_quantile_functor(const kolmogorov_smirnov_distribution& dist, RealType const& q) + : distribution(dist), n(dist.number_of_observations()) + { + BOOST_MATH_STD_USING // not in scope in a member initializer + log_prob = log(q); + } + + BOOST_MATH_NAMESPACE::tuple operator()(RealType const& V) + { + BOOST_MATH_STD_USING + RealType x = sqrt(V / n); + RealType Q = cdf(complement(distribution, x)); + RealType f = pdf(distribution, x); + // g(V) = ln Q(x(V)) - ln q ; dg/dV = -(f/Q) * dx/dV, dx/dV = x/(2V) + return BOOST_MATH_NAMESPACE::make_tuple(log(Q) - log_prob, -f * x / (2 * V * Q)); + } private: - const boost::math::kolmogorov_smirnov_distribution distribution; - RealType prob; + const kolmogorov_smirnov_distribution& distribution; + RealType log_prob; + RealType n; }; +// Common implementation of quantile() and quantile(complement()): p is the +// lower tail probability and q = 1 - p the upper tail probability, whichever +// was supplied by the caller having been computed from the other. template -struct kolmogorov_smirnov_negative_pdf_functor +RealType kolmogorov_smirnov_quantile_imp(const kolmogorov_smirnov_distribution& dist, RealType p, RealType q, const char* function) { - RealType operator()(RealType const& x) { - if (2*x*x < constants::pi()) { - return -kolmogorov_smirnov_pdf_small_x(x, static_cast(1), Policy()); + BOOST_MATH_STD_USING + RealType n = dist.number_of_observations(); + if (p == 0) + return 0; + if (q == 0) + return policies::raise_overflow_error(function, 0, Policy()); + + // Newton-Raphson in W or V is quadratically convergent from a starting + // point that is accurate to at least 1e-5, so the last step overestimates + // the remaining error by many orders of magnitude and a couple of bits + // can be dropped from the convergence criterion. + const int digits = policies::digits() - 2; + const std::uintmax_t max_root_iterations = policies::get_max_root_iterations(); + std::uintmax_t max_iter = max_root_iterations; + RealType result; + if (p < RealType(0.6)) { + RealType W = kolmogorov_smirnov_lower_guess(p); + // Below a thousand times the smallest normalized number, the CDF can + // no longer be evaluated to full precision; the starting value is + // exact to working precision there anyway. + if (p >= 1000 * tools::min_value()) { + W = tools::newton_raphson_iterate( + kolmogorov_smirnov_lower_quantile_functor(dist, p), + W, RealType(0), tools::max_value(), digits, max_iter); + } else { + max_iter = 0; } - return -kolmogorov_smirnov_pdf_large_x(x, static_cast(1), Policy()); + result = sqrt(constants::pi_sqr() / (8 * n * W)); + } else { + RealType V = kolmogorov_smirnov_upper_guess(q); + if (q >= 1000 * tools::min_value()) { + V = tools::newton_raphson_iterate( + kolmogorov_smirnov_upper_quantile_functor(dist, q), + V, RealType(0), tools::max_value(), digits, max_iter); + } else { + max_iter = 0; + } + result = sqrt(V / n); } -}; + if (max_iter >= max_root_iterations) + { + return policies::raise_evaluation_error(function, "Unable to locate solution in a reasonable time:" // LCOV_EXCL_LINE + " either there is no answer to quantile or the answer is infinite. Current best guess is %1%", result, Policy()); // LCOV_EXCL_LINE + } + return result; +} + } // namespace detail -template +BOOST_MATH_EXPORT template inline const std::pair range(const kolmogorov_smirnov_distribution& /*dist*/) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; return std::pair(static_cast(0), max_value()); } -template +BOOST_MATH_EXPORT template inline const std::pair support(const kolmogorov_smirnov_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. // In the exact distribution, the upper limit would be 1. - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; return std::pair(static_cast(0), max_value()); } -template +BOOST_MATH_EXPORT template inline RealType pdf(const kolmogorov_smirnov_distribution& dist, const RealType& x) { BOOST_FPU_EXCEPTION_GUARD @@ -302,7 +532,7 @@ inline RealType pdf(const kolmogorov_smirnov_distribution& dis if(false == detail::check_df(function, n, &error_result, Policy())) return error_result; - if (x < 0 || !(boost::math::isfinite)(x)) + if (x < 0 || !(BOOST_MATH_NAMESPACE::isfinite)(x)) { return policies::raise_domain_error( function, "Kolmogorov-Smirnov parameter was %1%, but must be > 0 !", x, Policy()); @@ -315,7 +545,7 @@ inline RealType pdf(const kolmogorov_smirnov_distribution& dis return detail::kolmogorov_smirnov_pdf_large_x(x, n, Policy()); } // pdf -template +BOOST_MATH_EXPORT template inline RealType cdf(const kolmogorov_smirnov_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std function exp. @@ -326,7 +556,7 @@ inline RealType cdf(const kolmogorov_smirnov_distribution& dis return error_result; if(false == detail::check_df(function, n, &error_result, Policy())) return error_result; - if((x < 0) || !(boost::math::isfinite)(x)) { + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) { return policies::raise_domain_error( function, "Random variable parameter was %1%, but must be between > 0 !", x, Policy()); } @@ -334,10 +564,17 @@ inline RealType cdf(const kolmogorov_smirnov_distribution& dis if (x*x*n == 0) return 0; + if (2*x*x*n > constants::pi()) { + RealType q = detail::kolmogorov_smirnov_nome(x, n); + if (q == 0) + return 1; + return RealType(1) + jacobi_theta4m1(RealType(0), q, Policy()); + } + return jacobi_theta4tau(RealType(0), 2*x*x*n/constants::pi(), Policy()); } // cdf -template +BOOST_MATH_EXPORT template inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std function exp. RealType x = c.param; @@ -351,23 +588,26 @@ inline RealType cdf(const complemented2_type( function, "Random variable parameter was %1%, but must be between > 0 !", x, Policy()); if (x*x*n == 0) return 1; - if (2*x*x*n > constants::pi()) - return -jacobi_theta4m1tau(RealType(0), 2*x*x*n/constants::pi(), Policy()); + if (2*x*x*n > constants::pi()) { + RealType q = detail::kolmogorov_smirnov_nome(x, n); + if (q == 0) + return 0; + return -jacobi_theta4m1(RealType(0), q, Policy()); + } return RealType(1) - jacobi_theta4tau(RealType(0), 2*x*x*n/constants::pi(), Policy()); } // cdf (complemented) -template +BOOST_MATH_EXPORT template inline RealType quantile(const kolmogorov_smirnov_distribution& dist, const RealType& p) { - BOOST_MATH_STD_USING static const char* function = "boost::math::quantile(const kolmogorov_smirnov_distribution<%1%>&, %1%)"; // Error check: RealType error_result; @@ -377,52 +617,26 @@ inline RealType quantile(const kolmogorov_smirnov_distribution if(false == detail::check_df(function, n, &error_result, Policy())) return error_result; - RealType k = detail::kolmogorov_smirnov_quantile_guess(p) / sqrt(n); - const int get_digits = policies::digits();// get digits from policy, - std::uintmax_t max_iter = policies::get_max_root_iterations(); // and max iterations. - - RealType result = tools::newton_raphson_iterate(detail::kolmogorov_smirnov_quantile_functor(dist, p), - k, RealType(0), RealType(1), get_digits, max_iter); - if (max_iter >= policies::get_max_root_iterations()) - { - return policies::raise_evaluation_error(function, "Unable to locate solution in a reasonable time:" // LCOV_EXCL_LINE - " either there is no answer to quantile or the answer is infinite. Current best guess is %1%", result, Policy()); // LCOV_EXCL_LINE - } - return result; + return detail::kolmogorov_smirnov_quantile_imp(dist, p, RealType(1 - p), function); } // quantile -template +BOOST_MATH_EXPORT template inline RealType quantile(const complemented2_type, RealType>& c) { - BOOST_MATH_STD_USING - static const char* function = "boost::math::quantile(const kolmogorov_smirnov_distribution<%1%>&, %1%)"; + static const char* function = "boost::math::quantile(const complemented2_type&, %1%>)"; kolmogorov_smirnov_distribution const& dist = c.dist; RealType n = dist.number_of_observations(); // Error check: RealType error_result; - RealType p = c.param; - - if(false == detail::check_probability(function, p, &error_result, Policy())) + RealType q = c.param; + if(false == detail::check_probability(function, q, &error_result, Policy())) return error_result; if(false == detail::check_df(function, n, &error_result, Policy())) return error_result; - RealType k = detail::kolmogorov_smirnov_quantile_guess(RealType(1-p)) / sqrt(n); - - const int get_digits = policies::digits();// get digits from policy, - std::uintmax_t max_iter = policies::get_max_root_iterations(); // and max iterations. - - RealType result = tools::newton_raphson_iterate( - detail::kolmogorov_smirnov_complementary_quantile_functor(dist, p), - k, RealType(0), RealType(1), get_digits, max_iter); - if (max_iter >= policies::get_max_root_iterations()) - { - return policies::raise_evaluation_error(function, "Unable to locate solution in a reasonable time:" // LCOV_EXCL_LINE - " either there is no answer to quantile or the answer is infinite. Current best guess is %1%", result, Policy()); // LCOV_EXCL_LINE - } - return result; + return detail::kolmogorov_smirnov_quantile_imp(dist, RealType(1 - q), q, function); } // quantile (complemented) -template +BOOST_MATH_EXPORT template inline RealType mode(const kolmogorov_smirnov_distribution& dist) { BOOST_MATH_STD_USING @@ -432,15 +646,55 @@ inline RealType mode(const kolmogorov_smirnov_distribution& di if(false == detail::check_df(function, n, &error_result, Policy())) return error_result; - std::pair r = boost::math::tools::brent_find_minima( - detail::kolmogorov_smirnov_negative_pdf_functor(), - static_cast(0), static_cast(1), policies::digits()); - return r.first / sqrt(n); + RealType k = detail::kolmogorov_smirnov_mode_constant(); + if (!detail::kolmogorov_smirnov_use_constants(Policy())) { + // Refine by Newton-Raphson on the stationarity condition of the PDF. + // With u = k*k and a_i = (i+1/2)^2 pi^2, the derivative of the small-x + // PDF series with respect to u vanishes when + // + // G(u) = SUM_{i>=0} exp(-a_i/(2u)) (a_i^2/(2u) - 5 a_i/2 + u) = 0 + RealType eps = policies::get_epsilon(); + RealType pi2 = constants::pi_sqr(); + RealType u = k * k; + for (int iter = 0; iter < 100; iter++) { + RealType G = 0, dG = 0, term; + int i = 0; + do { + RealType a = RealType(i + 0.5) * RealType(i + 0.5) * pi2; + RealType e = exp(-a / (2 * u)); + RealType poly = a * a / (2 * u) - 5 * a / 2 + u; + term = e * poly; + G += term; + dG += e * (a / (2 * u * u) * poly - a * a / (2 * u * u) + 1); + i++; + } while (!(fabs(term) <= eps * fabs(G))); + RealType step = G / dG; + u -= step; + if (fabs(step) <= eps * u) + break; + } + k = sqrt(u); + } + return k / sqrt(n); +} + +BOOST_MATH_EXPORT template +inline RealType median(const kolmogorov_smirnov_distribution& dist) +{ + BOOST_MATH_STD_USING + static const char* function = "boost::math::median(const kolmogorov_smirnov_distribution<%1%>&)"; + RealType n = dist.number_of_observations(); + RealType error_result; + if(false == detail::check_df(function, n, &error_result, Policy())) + return error_result; + if (!detail::kolmogorov_smirnov_use_constants(Policy())) + return quantile(dist, RealType(0.5)); + return detail::kolmogorov_smirnov_median_constant() / sqrt(n); } // Mean and variance come directly from // https://www.jstatsoft.org/article/view/v008i18 Section 3 -template +BOOST_MATH_EXPORT template inline RealType mean(const kolmogorov_smirnov_distribution& dist) { BOOST_MATH_STD_USING @@ -452,7 +706,7 @@ inline RealType mean(const kolmogorov_smirnov_distribution& di return constants::root_half_pi() * constants::ln_two() / sqrt(n); } -template +BOOST_MATH_EXPORT template inline RealType variance(const kolmogorov_smirnov_distribution& dist) { static const char* function = "boost::math::variance(const kolmogorov_smirnov_distribution<%1%>&)"; @@ -466,7 +720,7 @@ inline RealType variance(const kolmogorov_smirnov_distribution // Skewness and kurtosis come from integrating the PDF // The alternating series pops out a Dirichlet eta function which is related to the zeta function -template +BOOST_MATH_EXPORT template inline RealType skewness(const kolmogorov_smirnov_distribution& dist) { BOOST_MATH_STD_USING @@ -475,37 +729,47 @@ inline RealType skewness(const kolmogorov_smirnov_distribution RealType error_result; if(false == detail::check_df(function, n, &error_result, Policy())) return error_result; + if (detail::kolmogorov_smirnov_use_constants(Policy())) + return detail::kolmogorov_smirnov_skewness_constant(); RealType ex3 = RealType(0.5625) * constants::root_half_pi() * constants::zeta_three() / n / sqrt(n); - RealType mean = boost::math::mean(dist); - RealType var = boost::math::variance(dist); + RealType mean = BOOST_MATH_NAMESPACE::mean(dist); + RealType var = BOOST_MATH_NAMESPACE::variance(dist); return (ex3 - 3 * mean * var - mean * mean * mean) / var / sqrt(var); } -template -inline RealType kurtosis(const kolmogorov_smirnov_distribution& dist) +BOOST_MATH_EXPORT template +inline RealType kurtosis_excess(const kolmogorov_smirnov_distribution& dist) { BOOST_MATH_STD_USING - static const char* function = "boost::math::kurtosis(const kolmogorov_smirnov_distribution<%1%>&)"; + static const char* function = "boost::math::kurtosis_excess(const kolmogorov_smirnov_distribution<%1%>&)"; RealType n = dist.number_of_observations(); RealType error_result; if(false == detail::check_df(function, n, &error_result, Policy())) return error_result; + if (detail::kolmogorov_smirnov_use_constants(Policy())) + return detail::kolmogorov_smirnov_kurtosis_excess_constant(); RealType ex4 = 7 * constants::pi_sqr_div_six() * constants::pi_sqr_div_six() / 20 / n / n; - RealType mean = boost::math::mean(dist); - RealType var = boost::math::variance(dist); - RealType skew = boost::math::skewness(dist); - return (ex4 - 4 * mean * skew * var * sqrt(var) - 6 * mean * mean * var - mean * mean * mean * mean) / var / var; + RealType mean = BOOST_MATH_NAMESPACE::mean(dist); + RealType var = BOOST_MATH_NAMESPACE::variance(dist); + RealType skew = BOOST_MATH_NAMESPACE::skewness(dist); + return (ex4 - 4 * mean * skew * var * sqrt(var) - 6 * mean * mean * var - mean * mean * mean * mean) / var / var - 3; } -template -inline RealType kurtosis_excess(const kolmogorov_smirnov_distribution& dist) +BOOST_MATH_EXPORT template +inline RealType kurtosis(const kolmogorov_smirnov_distribution& dist) { - static const char* function = "boost::math::kurtosis_excess(const kolmogorov_smirnov_distribution<%1%>&)"; - RealType n = dist.number_of_observations(); - RealType error_result; - if(false == detail::check_df(function, n, &error_result, Policy())) - return error_result; - return kurtosis(dist) - 3; + return kurtosis_excess(dist) + 3; } -}} +BOOST_MATH_EXPORT template +inline RealType entropy(const kolmogorov_smirnov_distribution& dist) +{ + BOOST_MATH_STD_USING + // The Kolmogorov limit distribution of sqrt(n) D_n, scaled by 1/sqrt(n). Its entropy, + // -int K' log(K'), has no closed form; this is its value from mpmath quadrature at 120 digits. + const RealType h_kolmogorov = BOOST_MATH_BIG_CONSTANT(RealType, 290, + 0.000890322654402673706663823838286072983848397531327230497524635227050594202535194227074830683369); + return h_kolmogorov - log(dist.number_of_observations()) / 2; +} + +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/distributions/landau.hpp b/include/boost/math/distributions/landau.hpp index e8e9420be1..ddd738247e 100644 --- a/include/boost/math/distributions/landau.hpp +++ b/include/boost/math/distributions/landau.hpp @@ -28,18 +28,20 @@ #ifndef BOOST_MATH_HAS_NVRTC #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #endif +#endif -namespace boost { namespace math { -template +BOOST_MATH_NAMESPACE_BEGIN +BOOST_MATH_EXPORT template class landau_distribution; namespace detail { template -BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -352,7 +354,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_plus_imp_prec(const RealType& template -BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -880,7 +882,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_plus_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_minus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_minus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1020,7 +1022,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_minus_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_minus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_minus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1231,7 +1233,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_minus_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_imp_prec(const RealType& x, const boost::math::integral_constant &tag) { +BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant &tag) { if (x >= 0) { return landau_pdf_plus_imp_prec(x, tag); } @@ -1239,12 +1241,12 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_imp_prec(const RealType& x, co return landau_pdf_minus_imp_prec(x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } template -BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_imp_prec(const RealType& x, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return landau_pdf_plus_imp_prec(x, tag); } @@ -1252,7 +1254,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_imp_prec(const RealType& x, co return landau_pdf_minus_imp_prec(x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } @@ -1284,7 +1286,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_pdf_imp(const landau_distribution< typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1607,7 +1609,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_plus_imp_prec(const RealType& template -BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -2130,7 +2132,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_plus_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_minus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_minus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -2273,7 +2275,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_minus_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_minus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_minus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -2489,7 +2491,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_minus_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_imp_prec(const RealType& x, bool complement, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_imp_prec(const RealType& x, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return complement ? landau_cdf_plus_imp_prec(x, tag) : 1 - landau_cdf_plus_imp_prec(x, tag); } @@ -2497,12 +2499,12 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_imp_prec(const RealType& x, bo return complement ? 1 - landau_cdf_minus_imp_prec(x, tag) : landau_cdf_minus_imp_prec(x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } template -BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_imp_prec(const RealType& x, bool complement, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_imp_prec(const RealType& x, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return complement ? landau_cdf_plus_imp_prec(x, tag) : 1 - landau_cdf_plus_imp_prec(x, tag); } @@ -2510,7 +2512,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_imp_prec(const RealType& x, bo return complement ? 1 - landau_cdf_minus_imp_prec(x, tag) : landau_cdf_minus_imp_prec(x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } @@ -2542,7 +2544,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_cdf_imp(const landau_distribution< typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_lower_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_lower_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -2881,7 +2883,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_lower_imp_prec(const Real result = tools::evaluate_polynomial(P, t) / tools::evaluate_polynomial(Q, t); } else{ - result = -boost::math::numeric_limits::infinity(); + result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } return result; @@ -2889,7 +2891,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_lower_imp_prec(const Real template -BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_lower_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_lower_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -3542,14 +3544,14 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_lower_imp_prec(const Real result = tools::evaluate_polynomial(P, t) / tools::evaluate_polynomial(Q, t); } else { - result = -boost::math::numeric_limits::infinity(); + result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } return result; } template -BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_upper_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_upper_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -3789,7 +3791,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_upper_imp_prec(const Real template -BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_upper_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_upper_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -4236,7 +4238,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_upper_imp_prec(const Real } template -BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_imp_prec(const RealType& p, bool complement, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_imp_prec(const RealType& p, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (p > 0.5) { @@ -4247,7 +4249,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_imp_prec(const RealType& p, bool complement, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_imp_prec(const RealType& p, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (p > 0.5) { @@ -4286,7 +4288,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_quantile_imp(const landau_distribu typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType landau_mode_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_mode_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return static_cast(-0.42931452986133525017); } template -BOOST_MATH_GPU_ENABLED inline RealType landau_mode_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_mode_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return BOOST_MATH_BIG_CONSTANT(RealType, 113, -0.42931452986133525016556463510885028346); } @@ -4335,7 +4337,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_mode_imp(const landau_distribution typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType landau_median_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_median_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return static_cast(0.57563014394507821440); } template -BOOST_MATH_GPU_ENABLED inline RealType landau_median_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_median_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return BOOST_MATH_BIG_CONSTANT(RealType, 113, 0.57563014394507821439627930892257517269); } @@ -4384,7 +4386,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_median_imp(const landau_distributi typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType landau_entropy_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_entropy_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return static_cast(2.37263644000448182448); } template -BOOST_MATH_GPU_ENABLED inline RealType landau_entropy_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType landau_entropy_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return BOOST_MATH_BIG_CONSTANT(RealType, 113, 2.3726364400044818244844049010588577710); } @@ -4427,7 +4429,7 @@ BOOST_MATH_GPU_ENABLED inline RealType landau_entropy_imp(const landau_distribut typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant > +BOOST_MATH_EXPORT template > class landau_distribution { public: @@ -4481,75 +4483,75 @@ class landau_distribution RealType location_bias; // = -2 / pi * log(c) }; -typedef landau_distribution landau; +BOOST_MATH_EXPORT typedef landau_distribution landau; #ifdef __cpp_deduction_guides -template -landau_distribution(RealType) -> landau_distribution::type>; -template -landau_distribution(RealType, RealType) -> landau_distribution::type>; +BOOST_MATH_EXPORT template +landau_distribution(RealType) -> landau_distribution::type>; +BOOST_MATH_EXPORT template +landau_distribution(RealType, RealType) -> landau_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const landau_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const landau_distribution&) { // Range of permissible values for random variable x. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + max. } } -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const landau_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const landau_distribution&) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-tools::max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-tools::max_value(), max_value()); // - to + max. } } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const landau_distribution& dist, const RealType& x) { return detail::landau_pdf_imp(dist, x); } // pdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const landau_distribution& dist, const RealType& x) { return detail::landau_cdf_imp(dist, x, false); } // cdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const landau_distribution& dist, const RealType& p) { return detail::landau_quantile_imp(dist, p, false); } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { return detail::landau_cdf_imp(c.dist, c.param, true); } // cdf complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { return detail::landau_quantile_imp(c.dist, c.param, true); } // quantile complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const landau_distribution&) { // There is no mean: typedef typename Policy::assert_undefined_type assert_type; @@ -4559,10 +4561,10 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const landau_distribution&)", "The Landau distribution does not have a mean: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const landau_distribution& /*dist*/) { // There is no variance: @@ -4573,22 +4575,22 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const landau_distribution&)", "The Landau distribution does not have a variance: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const landau_distribution& dist) { return detail::landau_mode_imp(dist); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const landau_distribution& dist) { return detail::landau_median_imp(dist); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const landau_distribution& /*dist*/) { // There is no skewness: @@ -4599,10 +4601,10 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const landau_distribution&)", "The Landau distribution does not have a skewness: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); // infinity? + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); // infinity? } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const landau_distribution& /*dist*/) { // There is no kurtosis: @@ -4613,10 +4615,10 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const landau_distribution&)", "The Landau distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const landau_distribution& /*dist*/) { // There is no kurtosis excess: @@ -4627,16 +4629,16 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const landau_distribution "boost::math::kurtosis_excess(landau<%1%>&)", "The Landau distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const landau_distribution& dist) { return detail::landau_entropy_imp(dist); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_STATS_LANDAU_HPP diff --git a/include/boost/math/distributions/laplace.hpp b/include/boost/math/distributions/laplace.hpp index 81a0abe1ab..24466bb6d8 100644 --- a/include/boost/math/distributions/laplace.hpp +++ b/include/boost/math/distributions/laplace.hpp @@ -28,14 +28,14 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable:4127) // conditional expression is constant #endif -template > +BOOST_MATH_EXPORT template > class laplace_distribution { public: @@ -84,47 +84,47 @@ class laplace_distribution // // Convenient type synonym for double. -using laplace = laplace_distribution; +BOOST_MATH_EXPORT using laplace = laplace_distribution; #ifdef __cpp_deduction_guides -template -laplace_distribution(RealType)->laplace_distribution::type>; -template -laplace_distribution(RealType,RealType)->laplace_distribution::type>; +BOOST_MATH_EXPORT template +laplace_distribution(RealType)->laplace_distribution::type>; +BOOST_MATH_EXPORT template +laplace_distribution(RealType,RealType)->laplace_distribution::type>; #endif // // Non-member functions. -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const laplace_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const laplace_distribution&) { - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { // Can use infinity. - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + max value. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + max value. } } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const laplace_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const laplace_distribution&) { - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { // Can Use infinity. - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + max value. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + max value. } } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const laplace_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -136,7 +136,7 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const laplace_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logpdf(const laplace_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions // Checking function argument - RealType result = -boost::math::numeric_limits::infinity(); + RealType result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); constexpr auto function = "boost::math::logpdf(const laplace_distribution<%1%>&, %1%))"; // Check scale and location. @@ -171,7 +171,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const laplace_distribution::epsilon()) + if(abs(b) < BOOST_MATH_NAMESPACE::numeric_limits::epsilon()) { result = log(pdf(dist, x)); } else { // General case - const RealType log2 = boost::math::constants::ln_two(); + const RealType log2 = BOOST_MATH_NAMESPACE::constants::ln_two(); result = -abs(x-mu)/b - log(b) - log2; } return result; } // logpdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const laplace_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // For ADL of std functions. @@ -210,7 +210,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const laplace_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const laplace_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // For ADL of std functions. @@ -246,14 +246,10 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const laplace_distribution(function, nullptr, Policy()) : RealType(0); } if (false == detail::check_x(function, x, &result, Policy())) @@ -267,7 +263,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const laplace_distribution(); + result = ((x - location) / scale) - BOOST_MATH_NAMESPACE::constants::ln_two(); } else { @@ -277,7 +273,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const laplace_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const laplace_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions. @@ -315,7 +311,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const laplace_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { // Calculate complement of cdf. @@ -333,7 +329,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) { // Calculate complement of logcdf. @@ -369,22 +365,17 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type(function, nullptr, Policy()); } if(false == detail::check_x(function, x, &result, Policy()))return result; // Cdf interval value. if (-x < -location) { - result = (-x+location)/scale - boost::math::constants::ln_two(); + result = (-x+location)/scale - BOOST_MATH_NAMESPACE::constants::ln_two(); } else { @@ -393,7 +384,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions. @@ -411,11 +402,11 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type::infinity(); + return BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } if(q == 1) { - return -boost::math::numeric_limits::infinity(); + return -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } if(false == detail::check_probability(function, q, &result, Policy())) return result; @@ -428,49 +419,49 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const laplace_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const laplace_distribution& dist) { return constants::root_two() * dist.scale(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const laplace_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const laplace_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const laplace_distribution& /*dist*/) { return 0; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const laplace_distribution& /*dist*/) { return 6; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const laplace_distribution& /*dist*/) { return 3; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const laplace_distribution & dist) { using std::log; @@ -481,8 +472,7 @@ BOOST_MATH_GPU_ENABLED inline RealType entropy(const laplace_distribution #include -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN - template > + BOOST_MATH_EXPORT template > class logistic_distribution { public: @@ -57,33 +57,33 @@ namespace boost { namespace math { }; // class logistic_distribution - typedef logistic_distribution logistic; + BOOST_MATH_EXPORT typedef logistic_distribution logistic; #ifdef __cpp_deduction_guides - template - logistic_distribution(RealType)->logistic_distribution::type>; - template - logistic_distribution(RealType,RealType)->logistic_distribution::type>; + BOOST_MATH_EXPORT template + logistic_distribution(RealType)->logistic_distribution::type>; + BOOST_MATH_EXPORT template + logistic_distribution(RealType,RealType)->logistic_distribution::type>; #endif - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const logistic_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const logistic_distribution& /* dist */) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair( - boost::math::numeric_limits::has_infinity ? -boost::math::numeric_limits::infinity() : -max_value(), - boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair( + BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? -BOOST_MATH_NAMESPACE::numeric_limits::infinity() : -max_value(), + BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : max_value()); } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const logistic_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const logistic_distribution& /* dist */) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + infinity + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + infinity } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const logistic_distribution& dist, const RealType& x) { constexpr auto function = "boost::math::pdf(const logistic_distribution<%1%>&, %1%)"; @@ -100,7 +100,7 @@ namespace boost { namespace math { return result; } - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) { return 0; // pdf + and - infinity is zero. } @@ -120,7 +120,7 @@ namespace boost { namespace math { return (exp_term) / (scale * (1 + exp_term) * (1 + exp_term)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const logistic_distribution& dist, const RealType& x) { RealType scale = dist.scale(); @@ -136,7 +136,7 @@ namespace boost { namespace math { return result; } - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) { if(x < 0) return 0; // -infinity return 1; // + infinity @@ -152,7 +152,7 @@ namespace boost { namespace math { return logistic_sigmoid(power, policies::make_forwarding_policy_t()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const logistic_distribution& dist, const RealType& x) { RealType scale = dist.scale(); @@ -168,13 +168,10 @@ namespace boost { namespace math { return result; } - if((boost::math::isinf)(x)) + // The log of the cdf at -infinity is an exact -infinity, which goes to the overflow policy: + if((BOOST_MATH_NAMESPACE::isinf)(x)) { - if(x < 0) - { - return 0; // -infinity - } - return 1; // + infinity + return x < 0 ? -policies::raise_overflow_error(function, nullptr, Policy()) : RealType(0); } if(false == detail::check_x(function, x, &result, Policy())) @@ -195,7 +192,7 @@ namespace boost { namespace math { return -log1p(exp(power)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const logistic_distribution& dist, const RealType& p) { RealType location = dist.location(); @@ -223,7 +220,7 @@ namespace boost { namespace math { return location + scale * logit(p, Policy()); } // RealType quantile(const logistic_distribution& dist, const RealType& p) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { RealType location = c.dist.location(); @@ -240,7 +237,7 @@ namespace boost { namespace math { { return result; } - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) { if(x < 0) return 1; // cdf complement -infinity is unity. return 0; // cdf complement +infinity is zero. @@ -255,7 +252,7 @@ namespace boost { namespace math { return logistic_sigmoid(power, policies::make_forwarding_policy_t()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING @@ -273,10 +270,10 @@ namespace boost { namespace math { { return result; } - if((boost::math::isinf)(x)) + // The log of the complement at +infinity is an exact -infinity, which goes to the overflow policy: + if((BOOST_MATH_NAMESPACE::isinf)(x)) { - if(x < 0) return 1; // cdf complement -infinity is unity. - return 0; // cdf complement +infinity is zero. + return x < 0 ? RealType(0) : -policies::raise_overflow_error(function, nullptr, Policy()); } if(false == detail::check_x(function, x, &result, Policy())) { @@ -291,7 +288,7 @@ namespace boost { namespace math { return -log1p(exp(power)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { RealType scale = c.dist.scale(); @@ -305,7 +302,7 @@ namespace boost { namespace math { RealType q = c.param; if(false == detail::check_probability(function, q, &result, Policy())) return result; - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; if(q == 1) { @@ -319,56 +316,56 @@ namespace boost { namespace math { return location - scale * logit(q, Policy()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const logistic_distribution& dist) { return dist.location(); } // RealType mean(const logistic_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const logistic_distribution& dist) { BOOST_MATH_STD_USING RealType scale = dist.scale(); - return boost::math::constants::pi()*boost::math::constants::pi()*scale*scale/3; + return BOOST_MATH_NAMESPACE::constants::pi()*BOOST_MATH_NAMESPACE::constants::pi()*scale*scale/3; } // RealType variance(const logistic_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const logistic_distribution& dist) { return dist.location(); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const logistic_distribution& dist) { return dist.location(); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const logistic_distribution& /*dist*/) { return 0; } // RealType skewness(const logistic_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const logistic_distribution& /*dist*/) { return static_cast(6)/5; } // RealType kurtosis_excess(const logistic_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const logistic_distribution& dist) { return kurtosis_excess(dist) + 3; } // RealType kurtosis_excess(const logistic_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const logistic_distribution& dist) { using std::log; return 2 + log(dist.scale()); } - }} + BOOST_MATH_NAMESPACE_END // Must come at the end: diff --git a/include/boost/math/distributions/lognormal.hpp b/include/boost/math/distributions/lognormal.hpp index dfc3e4b2a2..171b00d466 100644 --- a/include/boost/math/distributions/lognormal.hpp +++ b/include/boost/math/distributions/lognormal.hpp @@ -21,8 +21,7 @@ #include #include -namespace boost{ namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -32,7 +31,7 @@ namespace detail RealType const& x, RealType* result, const Policy& pol) { - if((x < 0) || !(boost::math::isfinite)(x)) + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) { *result = policies::raise_domain_error( function, @@ -45,7 +44,7 @@ namespace detail } // namespace detail -template > +BOOST_MATH_EXPORT template > class lognormal_distribution { public: @@ -77,31 +76,31 @@ class lognormal_distribution RealType m_scale; // distribution scale. }; -typedef lognormal_distribution lognormal; +BOOST_MATH_EXPORT typedef lognormal_distribution lognormal; #ifdef __cpp_deduction_guides -template -lognormal_distribution(RealType)->lognormal_distribution::type>; -template -lognormal_distribution(RealType,RealType)->lognormal_distribution::type>; +BOOST_MATH_EXPORT template +lognormal_distribution(RealType)->lognormal_distribution::type>; +BOOST_MATH_EXPORT template +lognormal_distribution(RealType,RealType)->lognormal_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const lognormal_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const lognormal_distribution& /*dist*/) { // Range of permissible values for random variable x is >0 to +infinity. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const lognormal_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const lognormal_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType pdf(const lognormal_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -132,7 +131,7 @@ BOOST_MATH_GPU_ENABLED RealType pdf(const lognormal_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const lognormal_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -154,7 +153,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const lognormal_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const lognormal_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions @@ -178,7 +177,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const lognormal_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -200,7 +199,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -224,7 +223,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const lognormal_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -241,7 +240,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const lognormal_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const lognormal_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -255,10 +254,10 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const lognormal_distribution&)", mu, &result, Policy())) return result; - return boost::math::expm1(sigma * sigma, Policy()) * exp(2 * mu + sigma * sigma); + return BOOST_MATH_NAMESPACE::expm1(sigma * sigma, Policy()) * exp(2 * mu + sigma * sigma); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const lognormal_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -275,7 +274,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mode(const lognormal_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const lognormal_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -283,7 +282,7 @@ BOOST_MATH_GPU_ENABLED inline RealType median(const lognormal_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const lognormal_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -300,10 +299,10 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const lognormal_distribution&)", dist.location(), &result, Policy())) return result; - return (ess + 2) * sqrt(boost::math::expm1(ss, Policy())); + return (ess + 2) * sqrt(BOOST_MATH_NAMESPACE::expm1(ss, Policy())); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const lognormal_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -321,7 +320,7 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const lognormal_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const lognormal_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -339,7 +338,7 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const lognormal_distribut return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 6; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const lognormal_distribution& dist) { BOOST_MATH_STD_USING @@ -348,8 +347,7 @@ BOOST_MATH_GPU_ENABLED inline RealType entropy(const lognormal_distribution()*constants::e()*sigma*sigma)/2; } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/mapairy.hpp b/include/boost/math/distributions/mapairy.hpp index 8bf1f990c1..9326530bd4 100644 --- a/include/boost/math/distributions/mapairy.hpp +++ b/include/boost/math/distributions/mapairy.hpp @@ -28,17 +28,19 @@ #ifndef BOOST_MATH_HAS_NVRTC #include +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif -namespace boost { namespace math { -template +BOOST_MATH_NAMESPACE_BEGIN +BOOST_MATH_EXPORT template class mapairy_distribution; namespace detail { template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -260,7 +262,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_plus_imp_prec(const RealType& template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -589,7 +591,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_plus_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_minus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_minus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -762,7 +764,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_minus_imp_prec(const RealType } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_minus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_minus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1053,7 +1055,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_minus_imp_prec(const RealType } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_imp_prec(const RealType& x, const boost::math::integral_constant &tag) { +BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant &tag) { if (x >= 0) { return mapairy_pdf_plus_imp_prec(x, tag); } @@ -1061,12 +1063,12 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_imp_prec(const RealType& x, c return mapairy_pdf_minus_imp_prec(x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_imp_prec(const RealType& x, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return mapairy_pdf_plus_imp_prec(x, tag); } @@ -1074,7 +1076,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_imp_prec(const RealType& x, c return mapairy_pdf_minus_imp_prec(x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } @@ -1105,7 +1107,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_pdf_imp(const mapairy_distributio typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1312,7 +1314,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_plus_imp_prec(const RealType& } else { RealType x_cube = x * x * x; - RealType t = static_cast((boost::math::isnormal)(x_cube) ? 1 / sqrt(x_cube) : 1 / pow(sqrt(x), 3)); + RealType t = static_cast((BOOST_MATH_NAMESPACE::isnormal)(x_cube) ? 1 / sqrt(x_cube) : 1 / pow(sqrt(x), 3)); // Rational Approximation // Maximum Relative Error: 6.2709e-17 @@ -1336,7 +1338,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_plus_imp_prec(const RealType& template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1629,7 +1631,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_plus_imp_prec(const RealType& } else { RealType x_cube = x * x * x; - RealType t = (boost::math::isnormal)(x_cube) ? 1 / sqrt(x_cube) : 1 / pow(sqrt(x), 3); + RealType t = (BOOST_MATH_NAMESPACE::isnormal)(x_cube) ? 1 / sqrt(x_cube) : 1 / pow(sqrt(x), 3); // Rational Approximation // Maximum Relative Error: 3.5865e-37 @@ -1661,7 +1663,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_plus_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_minus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_minus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1838,7 +1840,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_minus_imp_prec(const RealType } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_minus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_minus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -2138,7 +2140,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_minus_imp_prec(const RealType } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_imp_prec(const RealType& x, bool complement, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_imp_prec(const RealType& x, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return complement ? mapairy_cdf_plus_imp_prec(x, tag) : 1 - mapairy_cdf_plus_imp_prec(x, tag); } @@ -2146,12 +2148,12 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_imp_prec(const RealType& x, b return complement ? 1 - mapairy_cdf_minus_imp_prec(x, tag) : mapairy_cdf_minus_imp_prec(x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_imp_prec(const RealType& x, bool complement, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_imp_prec(const RealType& x, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return complement ? mapairy_cdf_plus_imp_prec(x, tag) : 1 - mapairy_cdf_plus_imp_prec(x, tag); } @@ -2159,7 +2161,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_imp_prec(const RealType& x, b return complement ? 1 - mapairy_cdf_minus_imp_prec(x, tag) : mapairy_cdf_minus_imp_prec(x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } @@ -2190,7 +2192,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_cdf_imp(const mapairy_distributio typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_lower_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_lower_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -2531,7 +2533,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_lower_imp_prec(const Rea result = tools::evaluate_polynomial(P, t) / tools::evaluate_polynomial(Q, t); } else { - result = -boost::math::numeric_limits::infinity(); + result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } return result; @@ -2539,7 +2541,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_lower_imp_prec(const Rea template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_lower_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_lower_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -3234,14 +3236,14 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_lower_imp_prec(const Rea result = tools::evaluate_polynomial(P, t) / tools::evaluate_polynomial(Q, t); } else { - result = -boost::math::numeric_limits::infinity(); + result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } return result; } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_upper_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_upper_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -3429,14 +3431,14 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_upper_imp_prec(const Rea else { RealType p_square = p * p; - if ((boost::math::isnormal)(p_square)) { + if ((BOOST_MATH_NAMESPACE::isnormal)(p_square)) { result = 1 / cbrt(p_square * constants::two_pi()); } else if (p > 0) { result = 1 / (cbrt(p) * cbrt(p) * cbrt(constants::two_pi())); } else { - result = boost::math::numeric_limits::infinity(); + result = BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } } @@ -3445,7 +3447,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_upper_imp_prec(const Rea template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_upper_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_upper_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -3828,14 +3830,14 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_upper_imp_prec(const Rea else { RealType p_square = p * p; - if ((boost::math::isnormal)(p_square)) { + if ((BOOST_MATH_NAMESPACE::isnormal)(p_square)) { result = 1 / cbrt(p_square * constants::two_pi()); } else if (p > 0) { result = 1 / (cbrt(p) * cbrt(p) * cbrt(constants::two_pi())); } else { - result = boost::math::numeric_limits::infinity(); + result = BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } } @@ -3843,7 +3845,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_upper_imp_prec(const Rea } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_imp_prec(const RealType& p, bool complement, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_imp_prec(const RealType& p, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (p > 0.5) { return !complement ? mapairy_quantile_upper_imp_prec(1 - p, tag) : mapairy_quantile_lower_imp_prec(1 - p, tag); @@ -3853,7 +3855,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_imp_prec(const RealType& } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_imp_prec(const RealType& p, bool complement, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_imp_prec(const RealType& p, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (p > 0.5) { return !complement ? mapairy_quantile_upper_imp_prec(1 - p, tag) : mapairy_quantile_lower_imp_prec(1 - p, tag); @@ -3890,7 +3892,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_quantile_imp(const mapairy_distri typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType mapairy_mode_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_mode_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return static_cast(-1.16158727113597068525); } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_mode_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_mode_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return BOOST_MATH_BIG_CONSTANT(RealType, 113, -1.1615872711359706852500000803029112987); } @@ -3938,7 +3940,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_mode_imp(const mapairy_distributi typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType mapairy_median_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_median_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return static_cast(-0.71671068545502205332); } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_median_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_median_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return BOOST_MATH_BIG_CONSTANT(RealType, 113, -0.71671068545502205331700196278067230944440); } @@ -3986,7 +3988,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_median_imp(const mapairy_distribu typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType mapairy_entropy_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_entropy_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return static_cast(2.00727681841065634600); } template -BOOST_MATH_GPU_ENABLED inline RealType mapairy_entropy_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType mapairy_entropy_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return BOOST_MATH_BIG_CONSTANT(RealType, 113, 2.0072768184106563460003025875575283708); } @@ -4029,7 +4031,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mapairy_entropy_imp(const mapairy_distrib typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant > +BOOST_MATH_EXPORT template > class mapairy_distribution { public: @@ -4074,99 +4076,99 @@ class mapairy_distribution RealType c; // The scale parameter. }; -typedef mapairy_distribution mapairy; +BOOST_MATH_EXPORT typedef mapairy_distribution mapairy; #ifdef __cpp_deduction_guides -template -mapairy_distribution(RealType) -> mapairy_distribution::type>; -template -mapairy_distribution(RealType, RealType) -> mapairy_distribution::type>; +BOOST_MATH_EXPORT template +mapairy_distribution(RealType) -> mapairy_distribution::type>; +BOOST_MATH_EXPORT template +mapairy_distribution(RealType, RealType) -> mapairy_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const mapairy_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const mapairy_distribution&) { // Range of permissible values for random variable x. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + max. } } -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const mapairy_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const mapairy_distribution&) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-tools::max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-tools::max_value(), max_value()); // - to + max. } } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const mapairy_distribution& dist, const RealType& x) { return detail::mapairy_pdf_imp(dist, x); } // pdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const mapairy_distribution& dist, const RealType& x) { return detail::mapairy_cdf_imp(dist, x, false); } // cdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const mapairy_distribution& dist, const RealType& p) { return detail::mapairy_quantile_imp(dist, p, false); } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { return detail::mapairy_cdf_imp(c.dist, c.param, true); } // cdf complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { return detail::mapairy_quantile_imp(c.dist, c.param, true); } // quantile complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const mapairy_distribution &dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const mapairy_distribution& /*dist*/) { - return boost::math::numeric_limits::infinity(); + return BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const mapairy_distribution& dist) { return detail::mapairy_mode_imp(dist); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const mapairy_distribution& dist) { return detail::mapairy_median_imp(dist); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const mapairy_distribution& /*dist*/) { // There is no skewness: @@ -4177,10 +4179,10 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const mapairy_distribution&)", "The Map-Airy distribution does not have a skewness: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); // infinity? + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); // infinity? } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const mapairy_distribution& /*dist*/) { // There is no kurtosis: @@ -4191,10 +4193,10 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const mapairy_distribution&)", "The Map-Airy distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const mapairy_distribution& /*dist*/) { // There is no kurtosis excess: @@ -4205,16 +4207,16 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const mapairy_distributio "boost::math::kurtosis_excess(mapairy<%1%>&)", "The Map-Airy distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const mapairy_distribution& dist) { return detail::mapairy_entropy_imp(dist); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_STATS_MAPAIRY_HPP diff --git a/include/boost/math/distributions/negative_binomial.hpp b/include/boost/math/distributions/negative_binomial.hpp index f520c94803..f12d966a9e 100644 --- a/include/boost/math/distributions/negative_binomial.hpp +++ b/include/boost/math/distributions/negative_binomial.hpp @@ -64,17 +64,18 @@ // in domain_error_imp in error_handling. #endif -namespace boost -{ - namespace math - { +#ifndef BOOST_MATH_HAS_NVRTC +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace negative_binomial_detail { // Common error checking routines for negative binomial distribution functions: template BOOST_MATH_GPU_ENABLED inline bool check_successes(const char* function, const RealType& r, RealType* result, const Policy& pol) { - if( !(boost::math::isfinite)(r) || (r <= 0) ) + if( !(BOOST_MATH_NAMESPACE::isfinite)(r) || (r <= 0) ) { *result = policies::raise_domain_error( function, @@ -86,7 +87,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& pol) { - if( !(boost::math::isfinite)(p) || (p < 0) || (p > 1) ) + if( !(BOOST_MATH_NAMESPACE::isfinite)(p) || (p < 0) || (p > 1) ) { *result = policies::raise_domain_error( function, @@ -108,7 +109,7 @@ namespace boost { return false; } - if( !(boost::math::isfinite)(k) || (k < 0) ) + if( !(BOOST_MATH_NAMESPACE::isfinite)(k) || (k < 0) ) { // Check k failures. *result = policies::raise_domain_error( function, @@ -129,7 +130,7 @@ namespace boost } // check_dist_and_prob } // namespace negative_binomial_detail - template > + BOOST_MATH_EXPORT template > class negative_binomial_distribution { public: @@ -251,29 +252,29 @@ namespace boost RealType m_p; // success_fraction }; // template class negative_binomial_distribution - typedef negative_binomial_distribution negative_binomial; // Reserved name of type double. + BOOST_MATH_EXPORT typedef negative_binomial_distribution negative_binomial; // Reserved name of type double. #ifdef __cpp_deduction_guides - template - negative_binomial_distribution(RealType,RealType)->negative_binomial_distribution::type>; + BOOST_MATH_EXPORT template + negative_binomial_distribution(RealType,RealType)->negative_binomial_distribution::type>; #endif - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const negative_binomial_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const negative_binomial_distribution& /* dist */) { // Range of permissible values for random variable k. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // max_integer? + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // max_integer? } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const negative_binomial_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const negative_binomial_distribution& /* dist */) { // Range of supported values for random variable k. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // max_integer? + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // max_integer? } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const negative_binomial_distribution& dist) { // Mean of Negative Binomial distribution = r(1-p)/p. return dist.successes() * (1 - dist.success_fraction() ) / dist.success_fraction(); @@ -286,14 +287,14 @@ namespace boost //} // median // Now implemented via quantile(half) in derived accessors. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const negative_binomial_distribution& dist) { // Mode of Negative Binomial distribution = floor[(r-1) * (1 - p)/p] BOOST_MATH_STD_USING // ADL of std functions. return floor((dist.successes() -1) * (1 - dist.success_fraction()) / dist.success_fraction()); } // mode - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const negative_binomial_distribution& dist) { // skewness of Negative Binomial distribution = 2-p / (sqrt(r(1-p)) BOOST_MATH_STD_USING // ADL of std functions. @@ -304,7 +305,7 @@ namespace boost sqrt(r * (1 - p)); } // skewness - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const negative_binomial_distribution& dist) { // kurtosis of Negative Binomial distribution // http://en.wikipedia.org/wiki/Negative_binomial is kurtosis_excess so add 3 @@ -313,7 +314,7 @@ namespace boost return 3 + (6 / r) + ((p * p) / (r * (1 - p))); } // kurtosis - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const negative_binomial_distribution& dist) { // kurtosis excess of Negative Binomial distribution // http://mathworld.wolfram.com/Kurtosis.html table of kurtosis_excess @@ -322,7 +323,7 @@ namespace boost return (6 - p * (6-p)) / (r * (1-p)); } // kurtosis_excess - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const negative_binomial_distribution& dist) { // Variance of Binomial distribution = r (1-p) / p^2. return dist.successes() * (1 - dist.success_fraction()) @@ -336,7 +337,7 @@ namespace boost // RealType chf(const negative_binomial_distribution& dist) // chf of Negative Binomial distribution provided by derived accessors. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const negative_binomial_distribution& dist, const RealType& k) { // Probability Density/Mass Function. BOOST_FPU_EXCEPTION_GUARD @@ -362,11 +363,11 @@ namespace boost return result; } // negative_binomial_pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const negative_binomial_distribution& dist, const RealType& k) { // Cumulative Distribution Function of Negative Binomial. constexpr auto function = "boost::math::cdf(const negative_binomial_distribution<%1%>&, %1%)"; - using boost::math::ibeta; // Regularized incomplete beta function. + using BOOST_MATH_NAMESPACE::ibeta; // Regularized incomplete beta function. // k argument may be integral, signed, or unsigned, or floating point. // If necessary, it has already been promoted from an integral type. RealType p = dist.success_fraction(); @@ -388,12 +389,12 @@ namespace boost return probability; } // cdf Cumulative Distribution Function Negative Binomial. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function Negative Binomial. constexpr auto function = "boost::math::cdf(const negative_binomial_distribution<%1%>&, %1%)"; - using boost::math::ibetac; // Regularized incomplete beta function complement. + using BOOST_MATH_NAMESPACE::ibetac; // Regularized incomplete beta function complement. // k argument may be integral, signed, or unsigned, or floating point. // If necessary, it has already been promoted from an integral type. RealType const& k = c.param; @@ -422,7 +423,36 @@ namespace boost return probability; } // cdf Cumulative Distribution Function Negative Binomial. - template + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline RealType logcdf(const negative_binomial_distribution& dist, const RealType& k) + { + constexpr auto function = "boost::math::logcdf(const negative_binomial_distribution<%1%>&, %1%)"; + RealType p = dist.success_fraction(); + RealType r = dist.successes(); + RealType result = 0; + if(false == negative_binomial_detail::check_dist_and_k(function, r, p, k, &result, Policy())) + { + return result; + } + return BOOST_MATH_NAMESPACE::libeta(r, static_cast(k + 1), p, Policy()); + } + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) + { + constexpr auto function = "boost::math::logcdf(const negative_binomial_distribution<%1%>&, %1%)"; + RealType const& k = c.param; + RealType p = c.dist.success_fraction(); + RealType r = c.dist.successes(); + RealType result = 0; + if(false == negative_binomial_detail::check_dist_and_k(function, r, p, k, &result, Policy())) + { + return result; + } + return BOOST_MATH_NAMESPACE::libetac(r, static_cast(k + 1), p, Policy()); + } + + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const negative_binomial_distribution& dist, const RealType& P) { // Quantile, percentile/100 or Percent Point Negative Binomial function. // Return the number of expected failures k for a given probability p. @@ -458,8 +488,8 @@ namespace boost { // No failures are expected if P = 0. return 0; // Total trials will be just dist.successes. } - if (P <= pow(dist.success_fraction(), dist.successes())) - { // p <= pdf(dist, 0) == cdf(dist, 0) + if (P <= cdf(dist, RealType(0))) + { // Compare with the cdf itself, not pow(p, r), so quantile(cdf(0)) round-trips. return 0; } if(p == 0) @@ -494,7 +524,7 @@ namespace boost // // Max iterations permitted: // - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); typedef typename Policy::discrete_quantile_type discrete_type; return detail::inverse_discrete_quantile( dist, @@ -507,7 +537,7 @@ namespace boost max_iter); } // RealType quantile(const negative_binomial_distribution dist, p) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { // Quantile or Percent Point Binomial function. // Return the number of expected failures k for a given @@ -548,8 +578,8 @@ namespace boost // usually means return +std::numeric_limits::infinity(); // unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR } - if (-Q <= boost::math::powm1(dist.success_fraction(), dist.successes(), Policy())) - { // q <= cdf(complement(dist, 0)) == pdf(dist, 0) + if (Q >= cdf(complement(dist, RealType(0)))) + { // Compare with the cdf itself, not powm1(p, r), so quantile(complement) round-trips. return 0; // } if(p == 0) @@ -581,7 +611,7 @@ namespace boost // // Max iterations permitted: // - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); typedef typename Policy::discrete_quantile_type discrete_type; return detail::inverse_discrete_quantile( dist, @@ -594,8 +624,88 @@ namespace boost max_iter); } // quantile complement - } // namespace math -} // namespace boost +#ifndef BOOST_MATH_HAS_NVRTC + // Not GPU enabled: the large-variance path uses Bernoulli numbers. + BOOST_MATH_EXPORT template + inline RealType entropy(const negative_binomial_distribution& dist) + { + BOOST_MATH_STD_USING + // No closed form: -sum p log(p) from the log ratios of the probabilities (detail::discrete_entropy_sum). + // For r (1 - p) below ~100 this is a direct sum of ~100 / p terms, and raises an evaluation_error + // past the policy's max_series_iterations (p below ~1e-4 by default). + constexpr auto function = "boost::math::entropy(const negative_binomial_distribution<%1%>&)"; + RealType r = dist.successes(); + RealType p = dist.success_fraction(); + RealType result = 0; + if (!negative_binomial_detail::check_dist(function, r, p, &result, Policy())) + return result; + if (p == 1) + return 0; + RealType q = 1 - p; + RealType mode = (r > 1) ? RealType(floor((r - 1) * q / p)) : RealType(0); + const RealType sigmas = detail::discrete_entropy_tail_sigmas(); + const RealType threshold = detail::entropy_series_threshold(); + RealType sigma = sqrt(r * q) / p; + RealType z2 = mode + 1; + if ((sigma >= 2 * sigmas) && (r >= 1) && (z2 >= sigmas * sigma + threshold + 2)) + { + // Trapezoidal rule on the continuation S(t) = t alpha + [lgamma(z1 + t) - lgamma(z1) - t log(z1)] + // - [lgamma(z2 + t) - lgamma(z2) - t log(z2)], z1 = z2 + r - 1, alpha = log(z1 q / z2), with + // z1 q - z2 = (r - 1) - z1 p. z1 = z1_hi + z1_lo exactly; z1_lo enters to first order. + RealType d = r - 1; + RealType z1_hi = z2 + d; + RealType z1_lo = detail::two_sum_error(z2, d, z1_hi); + RealType alpha = BOOST_MATH_NAMESPACE::log1p(RealType((fma(-z1_hi, p, d) - z1_lo * p) / z2), Policy()); + RealType h = sigma / detail::discrete_entropy_step_ratio(); + auto s_of = [&](RealType t) + { + return t * alpha + detail::entropy_lgamma_delta(z1_hi, t, Policy()) + z1_lo * BOOST_MATH_NAMESPACE::log1pmx(RealType(t / z1_hi), Policy()) + - detail::entropy_lgamma_delta(z2, t, Policy()); + }; + int j_right = 0; + int j_left = 0; + auto right = [&](RealType& s, RealType&) { s = s_of(RealType((++j_right) * h)); return true; }; + auto left = [&](RealType& s, RealType&) + { + RealType t = -(++j_left) * h; + if (z2 + t < threshold) + return false; + s = s_of(t); + return true; + }; + return detail::discrete_entropy_sum(right, left, h, RealType(0), function, Policy()); + } + // Direct sum from the mode, with p(k + 1) / p(k) = (k + r) q / (k + 1), whose numerator minus + // denominator is r q - 1 - k p. For r < 1 the ratio rises towards q in the tail: + RealType k_right = mode; + RealType k_left = mode; + detail::compensated_sum s_right; + detail::compensated_sum s_left; + auto log_ratio = [&](RealType k, RealType& ratio, bool left) + { + return detail::entropy_log_ratio(RealType((k + r) * q), RealType(k + 1), RealType(fma(r, q, -fma(k, p, RealType(1)))), ratio, left, Policy()); + }; + auto right = [&](RealType& s, RealType& ratio) + { + s_right.add(log_ratio(k_right, ratio, false)); + k_right += 1; + s = s_right.value(); + return true; + }; + auto left = [&](RealType& s, RealType& ratio) + { + if (k_left == 0) + return false; + k_left -= 1; + s_left.add(-log_ratio(k_left, ratio, true)); + s = s_left.value(); + return true; + }; + return detail::discrete_entropy_sum(right, left, RealType(1), q, function, Policy()); + } +#endif + + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/non_central_beta.hpp b/include/boost/math/distributions/non_central_beta.hpp index ea0c5a168e..61ba94576b 100644 --- a/include/boost/math/distributions/non_central_beta.hpp +++ b/include/boost/math/distributions/non_central_beta.hpp @@ -26,12 +26,9 @@ #include #include -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN - template + BOOST_MATH_EXPORT template class non_central_beta_distribution; namespace detail{ @@ -40,12 +37,12 @@ namespace boost BOOST_MATH_GPU_ENABLED T non_central_beta_p(T a, T b, T lam, T x, T y, const Policy& pol, T init_val = 0) { BOOST_MATH_STD_USING - using namespace boost::math; + using namespace BOOST_MATH_NAMESPACE; // // Variables come first: // - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); - T errtol = boost::math::policies::get_epsilon(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + T errtol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); T l2 = lam / 2; // // k is the starting point for iteration, and is the @@ -91,7 +88,7 @@ namespace boost // direction for recursion: // T last_term = 0; - boost::math::uintmax_t count = k; + BOOST_MATH_NAMESPACE::uintmax_t count = k; for(auto i = k; i >= 0; --i) { T term = beta * pois; @@ -129,7 +126,7 @@ namespace boost break; } last_term = term; - if(static_cast(count + i - k) > max_iter) + if(static_cast(count + i - k) > max_iter) { return policies::raise_evaluation_error("cdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE } @@ -141,12 +138,12 @@ namespace boost BOOST_MATH_GPU_ENABLED T non_central_beta_q(T a, T b, T lam, T x, T y, const Policy& pol, T init_val = 0) { BOOST_MATH_STD_USING - using namespace boost::math; + using namespace BOOST_MATH_NAMESPACE; // // Variables come first: // - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); - T errtol = boost::math::policies::get_epsilon(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + T errtol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); T l2 = lam / 2; // // k is the starting point for iteration, and is the @@ -194,7 +191,7 @@ namespace boost // of the bulk of the sum: // T last_term = 0; - boost::math::uintmax_t count = 0; + BOOST_MATH_NAMESPACE::uintmax_t count = 0; for(long long i = k + 1; ; ++i) { poisf *= l2 / i; @@ -208,7 +205,7 @@ namespace boost count = i - k; break; } - if(static_cast(i - k) > max_iter) + if(static_cast(i - k) > max_iter) { return policies::raise_evaluation_error("cdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE } @@ -222,7 +219,7 @@ namespace boost { break; } - if(static_cast(count + k - i) > max_iter) + if(static_cast(count + k - i) > max_iter) { return policies::raise_evaluation_error("cdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE } @@ -255,9 +252,20 @@ namespace boost return invert ? 0.0f : 1.0f; value_type result; value_type c = a + b + l / 2; - value_type cross = 1 - (b / c) * (1 + l / (2 * c * c)); + // 1 - (b / c) (1 + l / (2 c^2)), written without forming 1 - b/c, which rounds to 0 for huge b: + value_type cross = (a + l / 2) / c - (b / c) * (l / (2 * c * c)); if(l == 0) - result = cdf(boost::math::beta_distribution(a, b), x); + { + if(x < y) + { + return invert + ? cdf(complement(BOOST_MATH_NAMESPACE::beta_distribution(a, b), x)) + : cdf(BOOST_MATH_NAMESPACE::beta_distribution(a, b), x); + } + return invert + ? cdf(BOOST_MATH_NAMESPACE::beta_distribution(b, a), y) + : cdf(complement(BOOST_MATH_NAMESPACE::beta_distribution(b, a), y)); + } else if(x > cross) { // Complement is the smaller of the two: @@ -314,7 +322,7 @@ namespace boost // heuristics. // template - BOOST_MATH_GPU_ENABLED boost::math::pair bracket_and_solve_root_01(F f, const T& guess, T factor, bool rising, Tol tol, boost::math::uintmax_t& max_iter, const Policy& pol) + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::pair bracket_and_solve_root_01(F f, const T& guess, T factor, bool rising, Tol tol, BOOST_MATH_NAMESPACE::uintmax_t& max_iter, const Policy& pol) { BOOST_MATH_STD_USING constexpr auto function = "boost::math::tools::bracket_and_solve_root_01<%1%>"; @@ -328,7 +336,7 @@ namespace boost // // Set up invocation count: // - boost::math::uintmax_t count = max_iter - 1; + BOOST_MATH_NAMESPACE::uintmax_t count = max_iter - 1; if((fa < 0) == (guess < 0 ? !rising : rising)) { @@ -336,12 +344,12 @@ namespace boost // Zero is to the right of b, so walk upwards // until we find it: // - while((boost::math::sign)(fb) == (boost::math::sign)(fa)) + while((BOOST_MATH_NAMESPACE::sign)(fb) == (BOOST_MATH_NAMESPACE::sign)(fa)) { if(count == 0) { b = policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol); // LCOV_EXCL_LINE - return boost::math::make_pair(a, b); + return BOOST_MATH_NAMESPACE::make_pair(a, b); } // // Heuristic: every 20 iterations we double the growth factor in case the @@ -367,19 +375,19 @@ namespace boost // Zero is to the left of a, so walk downwards // until we find it: // - while((boost::math::sign)(fb) == (boost::math::sign)(fa)) + while((BOOST_MATH_NAMESPACE::sign)(fb) == (BOOST_MATH_NAMESPACE::sign)(fa)) { if(fabs(a) < tools::min_value()) { // Escape route just in case the answer is zero! max_iter -= count; max_iter += 1; - return a > 0 ? boost::math::make_pair(T(0), T(a)) : boost::math::make_pair(T(a), T(0)); + return a > 0 ? BOOST_MATH_NAMESPACE::make_pair(T(0), T(a)) : BOOST_MATH_NAMESPACE::make_pair(T(a), T(0)); } if(count == 0) { a = policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol); // LCOV_EXCL_LINE - return boost::math::make_pair(a, b); + return BOOST_MATH_NAMESPACE::make_pair(a, b); } // // Heuristic: every 20 iterations we double the growth factor in case the @@ -400,7 +408,7 @@ namespace boost } max_iter -= count; max_iter += 1; - boost::math::pair r = toms748_solve( + BOOST_MATH_NAMESPACE::pair r = toms748_solve( f, (a < 0 ? b : a), (a < 0 ? a : b), @@ -514,9 +522,9 @@ namespace boost detail::nc_beta_quantile_functor f(non_central_beta_distribution(a, b, l), p, comp); tools::eps_tolerance tol(policies::digits()); - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); - boost::math::pair ir + BOOST_MATH_NAMESPACE::pair ir = bracket_and_solve_root_01( f, guess, value_type(2.5), true, tol, max_iter, Policy()); @@ -550,8 +558,8 @@ namespace boost // // Variables come first: // - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); - T errtol = boost::math::policies::get_epsilon(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + T errtol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); T l2 = lam / 2; // // k is the starting point for iteration, and is the @@ -589,7 +597,7 @@ namespace boost // // Stable backwards recursion first: // - boost::math::uintmax_t count = k; + BOOST_MATH_NAMESPACE::uintmax_t count = k; T ratio = 0; T old_ratio = 0; for(auto i = k; i >= 0; --i) @@ -624,7 +632,7 @@ namespace boost break; } old_ratio = ratio; - if(static_cast(count + i - k) > max_iter) + if(static_cast(count + i - k) > max_iter) { return policies::raise_evaluation_error("pdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE } @@ -671,7 +679,7 @@ namespace boost return static_cast(r); if(l == 0) - return pdf(boost::math::beta_distribution(dist.alpha(), dist.beta()), x); + return pdf(BOOST_MATH_NAMESPACE::beta_distribution(dist.alpha(), dist.beta()), x); return policies::checked_narrowing_cast( non_central_beta_pdf(a, b, l, static_cast(x), value_type(1 - static_cast(x)), forwarding_policy()), "function"); @@ -706,9 +714,9 @@ namespace boost const char* function = "boost::math::detail::hypergeometric_2F2<%1%>(%1%,%1%,%1%,%1%,%1%)"; hypergeometric_2F2_sum s(a1, a2, b1, b2, z); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); - value_type result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); + value_type result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); policies::check_series_iterations(function, max_iter, pol); return policies::checked_narrowing_cast(result, function); @@ -716,7 +724,7 @@ namespace boost } // namespace detail - template > + BOOST_MATH_EXPORT template > class non_central_beta_distribution { public: @@ -759,31 +767,31 @@ namespace boost RealType ncp; // non-centrality parameter }; // template class non_central_beta_distribution - typedef non_central_beta_distribution non_central_beta; // Reserved name of type double. + BOOST_MATH_EXPORT typedef non_central_beta_distribution non_central_beta; // Reserved name of type double. #ifdef __cpp_deduction_guides - template - non_central_beta_distribution(RealType,RealType,RealType)->non_central_beta_distribution::type>; + BOOST_MATH_EXPORT template + non_central_beta_distribution(RealType,RealType,RealType)->non_central_beta_distribution::type>; #endif // Non-member functions to give properties of the distribution. - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const non_central_beta_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const non_central_beta_distribution& /* dist */) { // Range of permissible values for random variable k. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), static_cast(1)); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), static_cast(1)); } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const non_central_beta_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const non_central_beta_distribution& /* dist */) { // Range of supported values for random variable k. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), static_cast(1)); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), static_cast(1)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const non_central_beta_distribution& dist) { // mode. constexpr auto function = "mode(non_central_beta_distribution<%1%> const&)"; @@ -820,7 +828,7 @@ namespace boost // prototypes retained so we can fill in the blanks // later: // - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const non_central_beta_distribution& dist) { BOOST_MATH_STD_USING @@ -831,7 +839,7 @@ namespace boost return exp(-d / 2) * a * detail::hypergeometric_2F2(1 + a, apb, a, 1 + apb, d / 2, Policy()) / apb; } // mean - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const non_central_beta_distribution& dist) { // @@ -851,7 +859,7 @@ namespace boost // RealType standard_deviation(const non_central_beta_distribution& dist) // standard_deviation provided by derived accessors. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const non_central_beta_distribution& /*dist*/) { // skewness = sqrt(l). const char* function = "boost::math::non_central_beta_distribution<%1%>::skewness()"; @@ -859,10 +867,10 @@ namespace boost static_assert(assert_type::value == 0, "The Non Central Beta Distribution has no skewness."); return policies::raise_evaluation_error(function, "This function is not yet implemented, the only sensible result is %1%.", // LCOV_EXCL_LINE - boost::math::numeric_limits::quiet_NaN(), Policy()); // infinity? LCOV_EXCL_LINE + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); // infinity? LCOV_EXCL_LINE } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const non_central_beta_distribution& /*dist*/) { const char* function = "boost::math::non_central_beta_distribution<%1%>::kurtosis_excess()"; @@ -870,22 +878,22 @@ namespace boost static_assert(assert_type::value == 0, "The Non Central Beta Distribution has no kurtosis excess."); return policies::raise_evaluation_error(function, "This function is not yet implemented, the only sensible result is %1%.", // LCOV_EXCL_LINE - boost::math::numeric_limits::quiet_NaN(), Policy()); // infinity? LCOV_EXCL_LINE + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); // infinity? LCOV_EXCL_LINE } // kurtosis_excess - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const non_central_beta_distribution& dist) { return kurtosis_excess(dist) + 3; } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const non_central_beta_distribution& dist, const RealType& x) { // Probability Density/Mass Function. return detail::nc_beta_pdf(dist, x); } // pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType cdf(const non_central_beta_distribution& dist, const RealType& x) { const char* function = "boost::math::non_central_beta_distribution<%1%>::cdf(%1%)"; @@ -920,7 +928,7 @@ namespace boost return detail::non_central_beta_cdf(x, RealType(1 - x), a, b, l, false, Policy()); } // cdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function const char* function = "boost::math::non_central_beta_distribution<%1%>::cdf(%1%)"; @@ -957,20 +965,19 @@ namespace boost return detail::non_central_beta_cdf(x, RealType(1 - x), a, b, l, true, Policy()); } // ccdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const non_central_beta_distribution& dist, const RealType& p) { // Quantile (or Percent Point) function. return detail::nc_beta_quantile(dist, p, false); } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { // Quantile (or Percent Point) function. return detail::nc_beta_quantile(c.dist, c.param, true); } // quantile complement. - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/non_central_chi_squared.hpp b/include/boost/math/distributions/non_central_chi_squared.hpp index 5917b3732d..72dfd84f85 100644 --- a/include/boost/math/distributions/non_central_chi_squared.hpp +++ b/include/boost/math/distributions/non_central_chi_squared.hpp @@ -27,12 +27,9 @@ #include #include -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN - template + BOOST_MATH_EXPORT template class non_central_chi_squared_distribution; namespace detail{ @@ -67,8 +64,8 @@ namespace boost T lambda = theta / 2; T del = f / 2; T y = x / 2; - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); - T errtol = boost::math::policies::get_epsilon(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + T errtol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); T sum = init_sum; // // k is the starting location for iteration, we'll @@ -78,12 +75,12 @@ namespace boost // long long k = llround(lambda, pol); // Forwards and backwards Poisson weights: - T poisf = boost::math::gamma_p_derivative(static_cast(1 + k), lambda, pol); + T poisf = BOOST_MATH_NAMESPACE::gamma_p_derivative(static_cast(1 + k), lambda, pol); T poisb = poisf * k / lambda; // Initial forwards central chi squared term: - T gamf = boost::math::gamma_q(del + k, y, pol); + T gamf = BOOST_MATH_NAMESPACE::gamma_q(del + k, y, pol); // Forwards and backwards recursion terms on the central chi squared: - T xtermf = boost::math::gamma_p_derivative(del + 1 + k, y, pol); + T xtermf = BOOST_MATH_NAMESPACE::gamma_p_derivative(del + 1 + k, y, pol); T xtermb = xtermf * (del + k) / y; // Initial backwards central chi squared term: T gamb = gamf - xtermb; @@ -94,7 +91,7 @@ namespace boost // recurrences: // long long i; - for(i = k; static_cast(i-k) < max_iter; ++i) + for(i = k; static_cast(i-k) < max_iter; ++i) { T term = poisf * gamf; sum += term; @@ -105,7 +102,7 @@ namespace boost break; } //Error check: - if(static_cast(i-k) >= max_iter) + if(static_cast(i-k) >= max_iter) return policies::raise_evaluation_error("cdf(non_central_chi_squared_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE // // Now backwards iteration: the gamma @@ -152,7 +149,7 @@ namespace boost // Special case: if(x == 0) return 0; - T tk = boost::math::gamma_p_derivative(f/2 + 1, x/2, pol); + T tk = BOOST_MATH_NAMESPACE::gamma_p_derivative(f/2 + 1, x/2, pol); T lambda = theta / 2; T vk = exp(-lambda); T uk = vk; @@ -160,12 +157,12 @@ namespace boost if(sum == 0) return sum; - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); - T errtol = boost::math::policies::get_epsilon(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + T errtol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); int i; T lterm(0), term(0); - for(i = 1; static_cast(i) < max_iter; ++i) + for(i = 1; static_cast(i) < max_iter; ++i) { tk = tk * x / (f + 2 * i); uk = uk * lambda / i; @@ -177,7 +174,7 @@ namespace boost break; } //Error check: - if(static_cast(i) >= max_iter) + if(static_cast(i) >= max_iter) return policies::raise_evaluation_error("cdf(non_central_chi_squared_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE return sum; } @@ -203,8 +200,8 @@ namespace boost // Special case: if(y == 0) return 0; - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); - T errtol = boost::math::policies::get_epsilon(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + T errtol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); T errorf(0), errorb(0); T x = y / 2; @@ -219,7 +216,7 @@ namespace boost long long k = llround(del, pol); T a = n / 2 + k; // Central chi squared term for forward iteration: - T gamkf = boost::math::gamma_p(a, x, pol); + T gamkf = BOOST_MATH_NAMESPACE::gamma_p(a, x, pol); if(lambda == 0) return gamkf; @@ -230,7 +227,7 @@ namespace boost // Backwards Poisson weight: T poiskb = poiskf; // Forwards gamma function recursion term: - T xtermf = boost::math::gamma_p_derivative(a, x, pol); + T xtermf = BOOST_MATH_NAMESPACE::gamma_p_derivative(a, x, pol); // Backwards gamma function recursion term: T xtermb = xtermf * x / a; T sum = init_sum + poiskf * gamkf; @@ -271,10 +268,10 @@ namespace boost errorf = poiskf * gamkf; sum += errorf; ++i; - }while((fabs(errorf / sum) > errtol) && (static_cast(i) < max_iter)); + }while((fabs(errorf / sum) > errtol) && (static_cast(i) < max_iter)); //Error check: - if(static_cast(i) >= max_iter) + if(static_cast(i) >= max_iter) return policies::raise_evaluation_error("cdf(non_central_chi_squared_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE return sum; @@ -287,8 +284,8 @@ namespace boost // As above but for the PDF: // BOOST_MATH_STD_USING - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); - T errtol = boost::math::policies::get_epsilon(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + T errtol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); T x2 = x / 2; T n2 = n / 2; T l2 = lambda / 2; @@ -303,7 +300,7 @@ namespace boost sum += pois; if(pois / sum < errtol) break; - if(static_cast(i - k) >= max_iter) + if(static_cast(i - k) >= max_iter) return policies::raise_evaluation_error("pdf(non_central_chi_squared_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE pois *= l2 * x2 / ((i + 1) * (n2 + i)); } @@ -331,7 +328,7 @@ namespace boost BOOST_MATH_STD_USING value_type result; if(l == 0) - return invert == false ? cdf(boost::math::chi_squared_distribution(k), x) : cdf(complement(boost::math::chi_squared_distribution(k), x)); + return invert == false ? cdf(BOOST_MATH_NAMESPACE::chi_squared_distribution(k), x) : cdf(complement(BOOST_MATH_NAMESPACE::chi_squared_distribution(k), x)); else if(x > k + l) { // Complement is the smaller of the two: @@ -469,7 +466,7 @@ namespace boost { value_type pp = comp ? 1 - p : p; //guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k, 2 / k); - guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k * boost::math::tgamma(k / 2, forwarding_policy()), (2 / k)); + guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k * BOOST_MATH_NAMESPACE::tgamma(k / 2, forwarding_policy()), (2 / k)); if(guess == 0) guess = tools::min_value(); } @@ -519,7 +516,7 @@ namespace boost return static_cast(r); if(l == 0) - return pdf(boost::math::chi_squared_distribution(dist.degrees_of_freedom()), x); + return pdf(BOOST_MATH_NAMESPACE::chi_squared_distribution(dist.degrees_of_freedom()), x); // Special case: if(x == 0) @@ -539,7 +536,7 @@ namespace boost { r = exp(r); r = 0.5f * r - * boost::math::cyl_bessel_i(k/2 - 1, sqrt(l * x), forwarding_policy()); + * BOOST_MATH_NAMESPACE::cyl_bessel_i(k/2 - 1, sqrt(l * x), forwarding_policy()); } } return policies::checked_narrowing_cast( @@ -579,11 +576,11 @@ namespace boost // Can't a thing if one of p and q is zero: // return policies::raise_evaluation_error(function, "Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%", // LCOV_EXCL_LINE - RealType(boost::math::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE + RealType(BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE } degrees_of_freedom_finder f(lam, x, p < q ? p : q, p < q ? false : true); tools::eps_tolerance tol(policies::digits()); - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); // // Pick an initial guess that we know will give us a probability // right around 0.5. @@ -591,7 +588,7 @@ namespace boost RealType guess = x - lam; if(guess < 1) guess = 1; - boost::math::pair ir = tools::bracket_and_solve_root( + BOOST_MATH_NAMESPACE::pair ir = tools::bracket_and_solve_root( f, guess, RealType(2), false, tol, max_iter, pol); RealType result = ir.first + (ir.second - ir.first) / 2; if(max_iter >= policies::get_max_root_iterations()) @@ -634,11 +631,11 @@ namespace boost // Can't do a thing if one of p and q is zero: // return policies::raise_evaluation_error(function, "Can't find non centrality parameter when the probability is 0 or 1, only possible answer is %1%", // LCOV_EXCL_LINE - RealType(boost::math::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE + RealType(BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE } non_centrality_finder f(v, x, p < q ? p : q, p < q ? false : true); tools::eps_tolerance tol(policies::digits()); - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); // // Pick an initial guess that we know will give us a probability // right around 0.5. @@ -646,7 +643,7 @@ namespace boost RealType guess = x - v; if(guess < 1) guess = 1; - boost::math::pair ir = tools::bracket_and_solve_root( + BOOST_MATH_NAMESPACE::pair ir = tools::bracket_and_solve_root( f, guess, RealType(2), false, tol, max_iter, pol); RealType result = ir.first + (ir.second - ir.first) / 2; if(max_iter >= policies::get_max_root_iterations()) @@ -659,7 +656,7 @@ namespace boost } - template > + BOOST_MATH_EXPORT template > class non_central_chi_squared_distribution { public: @@ -776,31 +773,31 @@ namespace boost RealType ncp; // non-centrality parameter }; // template class non_central_chi_squared_distribution - typedef non_central_chi_squared_distribution non_central_chi_squared; // Reserved name of type double. + BOOST_MATH_EXPORT typedef non_central_chi_squared_distribution non_central_chi_squared; // Reserved name of type double. #ifdef __cpp_deduction_guides - template - non_central_chi_squared_distribution(RealType,RealType)->non_central_chi_squared_distribution::type>; + BOOST_MATH_EXPORT template + non_central_chi_squared_distribution(RealType,RealType)->non_central_chi_squared_distribution::type>; #endif // Non-member functions to give properties of the distribution. - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const non_central_chi_squared_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const non_central_chi_squared_distribution& /* dist */) { // Range of permissible values for random variable k. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // Max integer? + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // Max integer? } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const non_central_chi_squared_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const non_central_chi_squared_distribution& /* dist */) { // Range of supported values for random variable k. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const non_central_chi_squared_distribution& dist) { // Mean of poisson distribution = lambda. constexpr auto function = "boost::math::non_central_chi_squared_distribution<%1%>::mean()"; @@ -820,7 +817,7 @@ namespace boost return k + l; } // mean - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const non_central_chi_squared_distribution& dist) { // mode. constexpr auto function = "mode(non_central_chi_squared_distribution<%1%> const&)"; @@ -843,7 +840,7 @@ namespace boost return detail::generic_find_mode(dist, starting_point, function); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const non_central_chi_squared_distribution& dist) { // variance. constexpr auto function = "boost::math::non_central_chi_squared_distribution<%1%>::variance()"; @@ -866,7 +863,7 @@ namespace boost // RealType standard_deviation(const non_central_chi_squared_distribution& dist) // standard_deviation provided by derived accessors. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const non_central_chi_squared_distribution& dist) { // skewness = sqrt(l). constexpr auto function = "boost::math::non_central_chi_squared_distribution<%1%>::skewness()"; @@ -887,7 +884,7 @@ namespace boost return pow(2 / (k + 2 * l), RealType(3)/2) * (k + 3 * l); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const non_central_chi_squared_distribution& dist) { constexpr auto function = "boost::math::non_central_chi_squared_distribution<%1%>::kurtosis_excess()"; @@ -907,19 +904,19 @@ namespace boost return 12 * (k + 4 * l) / ((k + 2 * l) * (k + 2 * l)); } // kurtosis_excess - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const non_central_chi_squared_distribution& dist) { return kurtosis_excess(dist) + 3; } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const non_central_chi_squared_distribution& dist, const RealType& x) { // Probability Density/Mass Function. return detail::nccs_pdf(dist, x); } // pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType cdf(const non_central_chi_squared_distribution& dist, const RealType& x) { constexpr auto function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)"; @@ -946,7 +943,7 @@ namespace boost return detail::non_central_chi_squared_cdf(x, k, l, false, Policy()); } // cdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function constexpr auto function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)"; @@ -975,20 +972,19 @@ namespace boost return detail::non_central_chi_squared_cdf(x, k, l, true, Policy()); } // ccdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const non_central_chi_squared_distribution& dist, const RealType& p) { // Quantile (or Percent Point) function. return detail::nccs_quantile(dist, p, false); } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { // Quantile (or Percent Point) function. return detail::nccs_quantile(c.dist, c.param, true); } // quantile complement. - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/non_central_f.hpp b/include/boost/math/distributions/non_central_f.hpp index 9bae5c41ff..76f95b966a 100644 --- a/include/boost/math/distributions/non_central_f.hpp +++ b/include/boost/math/distributions/non_central_f.hpp @@ -15,15 +15,14 @@ #include #include #include +#include #include #include +#include #include #include // complements -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template @@ -51,7 +50,7 @@ namespace boost if ( p == 0 || q == 0) { return policies::raise_domain_error(function, "Can't find non centrality parameter when the probability is <=0 or >=1, only possible answer is %1%", // LCOV_EXCL_LINE - RealType(boost::math::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE + RealType(BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE } // Check if nc = 0 (which is just the F-distribution) @@ -69,10 +68,10 @@ namespace boost RealType guess = RealType(10); // Starting guess. RealType factor = RealType(2); // How big steps to take when searching. - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); tools::eps_tolerance tol(policies::digits()); - boost::math::pair result_bracket = tools::bracket_and_solve_root( + BOOST_MATH_NAMESPACE::pair result_bracket = tools::bracket_and_solve_root( f, guess, factor, false, tol, max_iter, pol); RealType result = result_bracket.first + (result_bracket.second - result_bracket.first)/2; @@ -118,6 +117,33 @@ namespace boost return comp ? pval - cdf(complement(d, x*v1)) : cdf(d, x*v1) - pval; } + template + RealType large_v1_approximation(RealType x, RealType v2, RealType p, RealType q) + { // For v1 -> inf, F -> v2 / X with X ~ chi-squared(v2), so cdf(x) -> Q_chi2(v2)(v2 / x). + bool comp = p < q ? false : true; + RealType pval = p < q ? p : q; + chi_squared_distribution d(v2); + return comp ? pval - cdf(d, v2 / x) : cdf(complement(d, v2 / x)) - pval; + } + + template + RealType small_v1_approximation(RealType p, RealType q, RealType nc) + { // For v1 -> 0, F collapses to a point mass at 0 with probability exp(-nc/2), so cdf(x) -> exp(-nc/2) for any x > 0. + BOOST_MATH_STD_USING + bool comp = p < q ? false : true; + RealType pval = p < q ? p : q; + // comp branch needs 1 - exp(-nc/2), computed via expm1 to avoid cancellation for small nc. + return comp ? pval + BOOST_MATH_NAMESPACE::expm1(RealType(-nc / 2)) : exp(RealType(-nc / 2)) - pval; + } + + template + RealType small_v2_approximation(RealType p, RealType q) + { // For v2 -> 0, F diverges to infinity a.s., so cdf(x) -> 0 for any finite x. + bool comp = p < q ? false : true; + RealType pval = p < q ? p : q; + return comp ? pval - 1 : -pval; + } + template inline RealType find_degrees_of_freedom_f( const RealType x, const RealType v, const RealType nc, const bool find_v1, const RealType p, const RealType q, const Policy& pol) @@ -145,20 +171,21 @@ namespace boost // small values of v have the same sign. If the sign is the same, then there // are an even number of roots. If the signs differ, there is only one root // and we can safely find the root. - RealType vLarge = sqrt(boost::math::tools::max_value()); - RealType vSmall = 1 / vLarge; - // As v2 -> infinity, noncentral f converges to chi-squared distribution. - // Rather than evaluating f(vLarge), we can use the more stable chi-squared approximation - RealType large_difference; - if (find_v1) - { - large_difference = large_v2_approximation(x, v, p, q, nc); - } - else - large_difference = f(vLarge); + // Rather than evaluating f at an enormous or minuscule degrees of freedom, use its + // limits. As v2 -> infinity, v1 F tends to the non-central chi-squared with v1 degrees + // of freedom; as v1 -> infinity, F tends to v2 / chi-squared(v2), central, whatever the + // non-centrality. As v1 -> 0, F collapses to a point mass at 0 with probability + // exp(-nc/2); as v2 -> 0, F diverges to infinity almost surely. + RealType large_difference = find_v1 + ? large_v1_approximation(x, v, p, q) + : large_v2_approximation(x, v, p, q, nc); - if ((large_difference < 0) == (f(vSmall) < 0)){ + RealType small_difference = find_v1 + ? small_v1_approximation(p, q, nc) + : small_v2_approximation(p, q); + + if ((large_difference < 0) == (small_difference < 0)){ return policies::raise_evaluation_error(function, "Can't find degrees of freedom because two degrees of freedom can be found using the given parameters", RealType(std::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE } @@ -181,7 +208,7 @@ namespace boost } } // namespace detail - template > + BOOST_MATH_EXPORT template > class non_central_f_distribution { public: @@ -287,7 +314,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED static RealType find_v1(const complemented4_type& c) { - constexpr auto function = "non_central_f_distribution<%1%>::find_non_centrality"; + constexpr auto function = "non_central_f_distribution<%1%>::find_v1"; typedef typename policies::evaluation::type eval_type; typedef typename policies::normalise< Policy, @@ -307,9 +334,9 @@ namespace boost result, function); } - BOOST_MATH_GPU_ENABLED static RealType find_v2(const RealType x, const RealType v2, const RealType nc, const RealType p) + BOOST_MATH_GPU_ENABLED static RealType find_v2(const RealType x, const RealType v2, const RealType nc, const RealType p) { - constexpr auto function = "non_central_f_distribution<%1%>::find_v1"; + constexpr auto function = "non_central_f_distribution<%1%>::find_v2"; typedef typename policies::evaluation::type eval_type; typedef typename policies::normalise< Policy, @@ -332,7 +359,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED static RealType find_v2(const complemented4_type& c) { - constexpr auto function = "non_central_f_distribution<%1%>::find_non_centrality"; + constexpr auto function = "non_central_f_distribution<%1%>::find_v2"; typedef typename policies::evaluation::type eval_type; typedef typename policies::normalise< Policy, @@ -359,31 +386,31 @@ namespace boost RealType ncp; // non-centrality parameter }; // template class non_central_f_distribution - typedef non_central_f_distribution non_central_f; // Reserved name of type double. + BOOST_MATH_EXPORT typedef non_central_f_distribution non_central_f; // Reserved name of type double. #ifdef __cpp_deduction_guides - template - non_central_f_distribution(RealType,RealType,RealType)->non_central_f_distribution::type>; + BOOST_MATH_EXPORT template + non_central_f_distribution(RealType,RealType,RealType)->non_central_f_distribution::type>; #endif // Non-member functions to give properties of the distribution. - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const non_central_f_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const non_central_f_distribution& /* dist */) { // Range of permissible values for random variable k. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const non_central_f_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const non_central_f_distribution& /* dist */) { // Range of supported values for random variable k. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const non_central_f_distribution& dist) { constexpr auto function = "mean(non_central_f_distribution<%1%> const&)"; @@ -413,7 +440,7 @@ namespace boost return v2 * (v1 + l) / (v1 * (v2 - 2)); } // mean - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const non_central_f_distribution& dist) { // mode. constexpr auto function = "mode(non_central_chi_squared_distribution<%1%> const&)"; @@ -443,7 +470,7 @@ namespace boost function); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const non_central_f_distribution& dist) { // variance. constexpr auto function = "variance(non_central_f_distribution<%1%> const&)"; @@ -479,7 +506,7 @@ namespace boost // RealType standard_deviation(const non_central_f_distribution& dist) // standard_deviation provided by derived accessors. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const non_central_f_distribution& dist) { // skewness = sqrt(l). constexpr auto function = "skewness(non_central_f_distribution<%1%> const&)"; @@ -516,7 +543,7 @@ namespace boost return result; } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const non_central_f_distribution& dist) { constexpr auto function = "kurtosis_excess(non_central_f_distribution<%1%> const&)"; @@ -558,18 +585,18 @@ namespace boost + 4 * (10 + m) * (-2 + m + n) * l3 + (10 + m) * l4)) / - ((-8 + m) * (-6 + m) * boost::math::pow<2>(n * (-2 + m + n) + ((-8 + m) * (-6 + m) * BOOST_MATH_NAMESPACE::pow<2>(n * (-2 + m + n) + 2 * (-2 + m + n) * l + l2)); return result; } // kurtosis_excess - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const non_central_f_distribution& dist) { return kurtosis_excess(dist) + 3; } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const non_central_f_distribution& dist, const RealType& x) { // Probability Density/Mass Function. typedef typename policies::evaluation::type value_type; @@ -583,13 +610,13 @@ namespace boost value_type alpha = dist.degrees_of_freedom1() / 2; value_type beta = dist.degrees_of_freedom2() / 2; value_type y = x * alpha / beta; - value_type r = pdf(boost::math::non_central_beta_distribution(alpha, beta, dist.non_centrality()), y / (1 + y)); + value_type r = pdf(BOOST_MATH_NAMESPACE::non_central_beta_distribution(alpha, beta, dist.non_centrality()), y / (1 + y)); return policies::checked_narrowing_cast( r * (dist.degrees_of_freedom1() / dist.degrees_of_freedom2()) / ((1 + y) * (1 + y)), "pdf(non_central_f_distribution<%1%>, %1%)"); } // pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType cdf(const non_central_f_distribution& dist, const RealType& x) { constexpr auto function = "cdf(const non_central_f_distribution<%1%>&, %1%)"; @@ -609,7 +636,7 @@ namespace boost Policy())) return r; - if((x < 0) || !(boost::math::isfinite)(x)) + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) { return policies::raise_domain_error( function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy()); @@ -630,7 +657,7 @@ namespace boost return r; } // cdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function constexpr auto function = "cdf(complement(const non_central_f_distribution<%1%>&, %1%))"; @@ -650,7 +677,7 @@ namespace boost Policy())) return r; - if((c.param < 0) || !(boost::math::isfinite)(c.param)) + if((c.param < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(c.param)) { return policies::raise_domain_error( function, "Random Variable parameter was %1%, but must be > 0 !", c.param, Policy()); @@ -671,12 +698,12 @@ namespace boost return r; } // ccdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const non_central_f_distribution& dist, const RealType& p) { // Quantile (or Percent Point) function. RealType alpha = dist.degrees_of_freedom1() / 2; RealType beta = dist.degrees_of_freedom2() / 2; - RealType x = quantile(boost::math::non_central_beta_distribution(alpha, beta, dist.non_centrality()), p); + RealType x = quantile(BOOST_MATH_NAMESPACE::non_central_beta_distribution(alpha, beta, dist.non_centrality()), p); if(x == 1) return policies::raise_overflow_error( "quantile(const non_central_f_distribution<%1%>&, %1%)", @@ -685,12 +712,12 @@ namespace boost return (x / (1 - x)) * (dist.degrees_of_freedom2() / dist.degrees_of_freedom1()); } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { // Quantile (or Percent Point) function. RealType alpha = c.dist.degrees_of_freedom1() / 2; RealType beta = c.dist.degrees_of_freedom2() / 2; - RealType x = quantile(complement(boost::math::non_central_beta_distribution(alpha, beta, c.dist.non_centrality()), c.param)); + RealType x = quantile(complement(BOOST_MATH_NAMESPACE::non_central_beta_distribution(alpha, beta, c.dist.non_centrality()), c.param)); if(x == 1) return policies::raise_overflow_error( "quantile(complement(const non_central_f_distribution<%1%>&, %1%))", @@ -698,8 +725,7 @@ namespace boost Policy()); return (x / (1 - x)) * (c.dist.degrees_of_freedom2() / c.dist.degrees_of_freedom1()); } // quantile complement. - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/non_central_t.hpp b/include/boost/math/distributions/non_central_t.hpp index 9bc1cf8ccc..02e51614fc 100644 --- a/include/boost/math/distributions/non_central_t.hpp +++ b/include/boost/math/distributions/non_central_t.hpp @@ -18,13 +18,14 @@ #include #include #include +#include +#include +#include +#include -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN - template + BOOST_MATH_EXPORT template class non_central_t_distribution; namespace detail{ @@ -131,7 +132,7 @@ namespace boost // Variables come first: // std::uintmax_t max_iter = policies::get_max_series_iterations(); - T errtol = boost::math::policies::get_epsilon(); + T errtol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); T d2 = delta * delta / 2; // // k is the starting point for iteration, and is the @@ -152,7 +153,7 @@ namespace boost // pois = exp(-d2); pois *= pow(d2, static_cast(k)); - pois /= boost::math::tgamma(T(k + 1 + 0.5), pol); + pois /= BOOST_MATH_NAMESPACE::tgamma(T(k + 1 + 0.5), pol); pois *= delta / constants::root_two(); } else @@ -220,11 +221,79 @@ namespace boost return sum; } + template + T non_central_t_left_tail_integral(T v, T delta, T t, const Policy& pol) + { + BOOST_MATH_STD_USING + // + // Computes P(T <= -t) for t > 0 and delta > 0, which is the upper tail Q(t) of the + // distribution with non-centrality -delta. The series used for the cdf sum terms of both + // signs here, which cancel when this tail is small (they sum to the much larger tail on the + // other side), so integrate the tail directly instead: + // + // P(T <= -t) = E[Phi(-(t s + delta))], s = sqrt(chi^2_v / v), + // + // where the integrand is positive. The chi density is 2 (v/2)^(v/2) e^(-v/2) / Gamma(v/2) + // times s^(v-1) exp(-v (s^2 - 1) / 2). + // + T half_v = v / 2; + T t2 = t * t; + T eps = policies::get_epsilon(); + auto integrand = [&](T s) -> T + { + // (v - 1) log(s) - v (s^2 - 1) / 2, avoiding cancellation for s close to 1: + T e; + if (fabs(s - 1) < 0.5f) + { + T d = s - 1; + e = v * (BOOST_MATH_NAMESPACE::log1pmx(d, pol) - d * d / 2) - BOOST_MATH_NAMESPACE::log1p(d, pol); + } + else + e = (v - 1) * log(s) - half_v * (s * s - 1); + return exp(e) * BOOST_MATH_NAMESPACE::erfc((t * s + delta) / constants::root_two(), pol) / 2; + }; + // + // The integrand is only significant in a narrow window, for large v much narrower than the + // interval (0, inf), so first locate it. The upper limit is where the tail of + // exp(-t delta s - (v + t^2) s^2 / 2), the factors that decay for large s, has fallen to epsilon: + // + T hi = (sqrt(t2 * delta * delta - 2 * (v + t2) * log(eps)) - t * delta) / (v + t2); + T result; + if (v < 2) + { + // + // The integrand is singular at zero (for v < 1) or has a singular derivative there, + // and is otherwise wide, so tanh-sinh quadrature is the right tool: + // + result = quadrature::tanh_sinh().integrate(integrand, T(0), hi); + return result * 2 * half_v * gamma_p_derivative(half_v, half_v, pol); + } + // + // Otherwise estimate the mode m and the width of the window around it from the Gaussian + // approximation to Phi(-a), and integrate each side of the mode separately: + // + T disc = t2 * delta * delta + 4 * (v + t2) * (v - 1); + T m = (sqrt(disc) - t * delta) / (2 * (v + t2)); + T w = 2 * sqrt(-2 * log(eps) / (v + t2 + (v - 1) / (m * m))); + using integrator = quadrature::gauss_kronrod; + if (m + w > hi) + hi = m + w; + // The default tolerance of sqrt(epsilon) leaves errors of 1e-12 or so, which is more than the series: + T tol = pow(eps, T(2) / 3); + result = integrator::integrate(integrand, m, hi, 15, tol); + if (m > w) + result += integrator::integrate(integrand, m - w, m, 15, tol); + else + result += integrator::integrate(integrand, T(0), m, 15, tol); + // The normalisation constant is 2 (v/2)^(v/2) e^(-v/2) / Gamma(v/2): + return result * 2 * half_v * gamma_p_derivative(half_v, half_v, pol); + } + template T non_central_t_cdf(T v, T delta, T t, bool invert, const Policy& pol) { BOOST_MATH_STD_USING - if ((boost::math::isinf)(v)) + if ((BOOST_MATH_NAMESPACE::isinf)(v)) { // Infinite degrees of freedom, so use normal distribution located at delta. normal_distribution n(delta, 1); return cdf(n, t); @@ -249,8 +318,7 @@ namespace boost // t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31. // "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and // N. Balkrishnan. 1995. John Wiley and Sons New York. - T result = cdf(students_t_distribution(v), t - delta); - return invert ? 1 - result : result; + return invert ? cdf(complement(students_t_distribution(v), t - delta)) : cdf(students_t_distribution(v), t - delta); } // // x and y are the corresponding random @@ -274,21 +342,41 @@ namespace boost // // Calculate p: // + T beta_p = 0; if(x != 0) { - result = non_central_beta_p(a, b, d2, x, y, pol); - result = non_central_t2_p(v, delta, x, y, pol, result); + beta_p = non_central_beta_p(a, b, d2, x, y, pol); + result = non_central_t2_p(v, delta, x, y, pol, beta_p); result /= 2; } else result = 0; if (invert) { - result = cdf(complement(boost::math::normal_distribution(), -delta)) - result; + T upper = cdf(complement(BOOST_MATH_NAMESPACE::normal_distribution(), -delta)); + result = upper - result; + if ((delta < 0) && (x != 0) && (result < (std::max)(beta_p, upper) / 8)) + { + // Most of the digits have cancelled, compute the tail directly: + return non_central_t_left_tail_integral(v, T(-delta), t, pol); + } + if ((x != 0) && (fabs(result / (beta_p * tools::epsilon())) < 1000)) + { + // We've cancelled out most of the digits in the result, try A&S 26.7.9, + // this is only accurate to a couple of digits at best, but it's better + // than nothing when all else fails, see https://github.com/boostorg/math/issues/1430 + t = -t; + delta = -delta; + + T z = (t * (1 - 1 / (4 * v)) - delta) / sqrt(1 + t * t / (2 * v)); + + return cdf(BOOST_MATH_NAMESPACE::normal_distribution(), z); + + } invert = false; } else - result += cdf(boost::math::normal_distribution(), -delta); + result += cdf(BOOST_MATH_NAMESPACE::normal_distribution(), -delta); } else { @@ -299,11 +387,18 @@ namespace boost if(x != 0) { result = non_central_beta_q(a, b, d2, x, y, pol); + T positive = result; result = non_central_t2_q(v, delta, x, y, pol, result); + if (!invert && (delta < 0) && (result < positive / 8)) + { + // The terms with delta < 0 have cancelled most of the digits of the + // (small) upper tail, compute it directly: + return non_central_t_left_tail_integral(v, T(-delta), t, pol); + } result /= 2; } else // x == 0 - result = cdf(complement(boost::math::normal_distribution(), -delta)); + result = cdf(complement(BOOST_MATH_NAMESPACE::normal_distribution(), -delta)); } if(invert) result = 1 - result; @@ -344,7 +439,7 @@ namespace boost value_type guess = 0; - if ( ((boost::math::isinf)(v)) || (v > 1 / boost::math::tools::epsilon()) ) + if ( ((BOOST_MATH_NAMESPACE::isinf)(v)) || (v > 1 / BOOST_MATH_NAMESPACE::tools::epsilon()) ) { // Infinite or very large degrees of freedom, so use normal distribution located at delta. normal_distribution n(delta, 1); if (p < q) @@ -377,10 +472,10 @@ namespace boost forwarding_policy()); int s; if(p < q) - s = boost::math::sign(p - pzero); + s = BOOST_MATH_NAMESPACE::sign(p - pzero); else - s = boost::math::sign(pzero - q); - if(s != boost::math::sign(guess)) + s = BOOST_MATH_NAMESPACE::sign(pzero - q); + if(s != BOOST_MATH_NAMESPACE::sign(guess)) { guess = static_cast(s); } @@ -400,7 +495,7 @@ namespace boost T non_central_t_pdf_integral(T x, T v, T mu, const Policy& pol) { BOOST_MATH_STD_USING - boost::math::quadrature::exp_sinh integrator; + BOOST_MATH_NAMESPACE::quadrature::exp_sinh integrator; T integral = pow(v, v / 2) * exp(-v * mu * mu / (2 * (x * x + v))); if (integral != 0) { @@ -408,13 +503,13 @@ namespace boost { T p; if (v * log(y) < tools::log_max_value()) - p = pow(y, v) * exp(boost::math::pow<2>((y - mu * x / sqrt(x * x + v))) / -2); + p = pow(y, v) * exp(BOOST_MATH_NAMESPACE::pow<2>((y - mu * x / sqrt(x * x + v))) / -2); else - p = exp(log(y) * v + boost::math::pow<2>((y - mu * x / sqrt(x * x + v))) / -2); + p = exp(log(y) * v + BOOST_MATH_NAMESPACE::pow<2>((y - mu * x / sqrt(x * x + v))) / -2); return p; }); } - integral /= boost::math::constants::root_pi() * boost::math::tgamma(v / 2, pol) * pow(T(2), (v - 1) / 2) * pow(x * x + v, (v + 1) / 2); + integral /= BOOST_MATH_NAMESPACE::constants::root_pi() * BOOST_MATH_NAMESPACE::tgamma(v / 2, pol) * pow(T(2), (v - 1) / 2) * pow(x * x + v, (v + 1) / 2); return integral; } @@ -428,13 +523,13 @@ namespace boost // We only call this routine when we know that the series form of 1F1 is cheap to evaluate, // so no need to call the whole 1F1 function, just the series will do: // - T Av = hypergeometric_1F1_generic_series(static_cast((v + 1) / 2), boost::math::constants::half(), static_cast(mu * mu * x * x / (2 * (x * x + v))), pol, scale, function); + T Av = hypergeometric_1F1_generic_series(static_cast((v + 1) / 2), BOOST_MATH_NAMESPACE::constants::half(), static_cast(mu * mu * x * x / (2 * (x * x + v))), pol, scale, function); Av = ldexp(Av, static_cast(scale)); scale = 0; T Bv = hypergeometric_1F1_generic_series(static_cast(v / 2 + T(1)), static_cast(T(3) / 2), static_cast(mu * mu * x * x / (2 * (x * x + v))), pol, scale, function); Bv = ldexp(Bv, static_cast(scale)); - Bv *= boost::math::tgamma_delta_ratio(v / 2 + T(1), -constants::half(), pol); - Bv *= boost::math::constants::root_two() * mu * x / sqrt(x * x + v); + Bv *= BOOST_MATH_NAMESPACE::tgamma_delta_ratio(v / 2 + T(1), -constants::half(), pol); + Bv *= BOOST_MATH_NAMESPACE::constants::root_two() * mu * x / sqrt(x * x + v); T tolerance = tools::root_epsilon() * Av * 4; Av += Bv; @@ -445,8 +540,8 @@ namespace boost return non_central_t_pdf_integral(x, v, mu, pol); } - Av *= exp(-mu * mu / 2) * pow(1 + x * x / v, -(v + 1) / 2) * boost::math::tgamma_delta_ratio(v / 2 + constants::half(), -constants::half(), pol); - Av /= sqrt(v) * boost::math::constants::root_pi(); + Av *= exp(-mu * mu / 2) * pow(1 + x * x / v, -(v + 1) / 2) * BOOST_MATH_NAMESPACE::tgamma_delta_ratio(v / 2 + constants::half(), -constants::half(), pol); + Av /= sqrt(v) * BOOST_MATH_NAMESPACE::constants::root_pi(); return Av; } @@ -458,7 +553,7 @@ namespace boost // Variables come first: // std::uintmax_t max_iter = policies::get_max_series_iterations(); - T errtol = boost::math::policies::get_epsilon(); + T errtol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); T d2 = delta * delta / 2; // // k is the starting point for iteration, and is the @@ -547,7 +642,7 @@ namespace boost T non_central_t_pdf(T n, T delta, T t, const Policy& pol) { BOOST_MATH_STD_USING - if ((boost::math::isinf)(n)) + if ((BOOST_MATH_NAMESPACE::isinf)(n)) { // Infinite degrees of freedom, so use normal distribution located at delta. normal_distribution norm(delta, 1); return pdf(norm, t); @@ -638,12 +733,12 @@ namespace boost template T mean(T v, T delta, const Policy& pol) { - if ((boost::math::isinf)(v)) + if ((BOOST_MATH_NAMESPACE::isinf)(v)) { return delta; } BOOST_MATH_STD_USING - if (v > 1 / boost::math::tools::epsilon() ) + if (v > 1 / BOOST_MATH_NAMESPACE::tools::epsilon() ) { //normal_distribution n(delta, 1); //return boost::math::mean(n); @@ -659,7 +754,7 @@ namespace boost template T variance(T v, T delta, const Policy& pol) { - if ((boost::math::isinf)(v)) + if ((BOOST_MATH_NAMESPACE::isinf)(v)) { return 1; } @@ -677,7 +772,7 @@ namespace boost T skewness(T v, T delta, const Policy& pol) { BOOST_MATH_STD_USING - if ((boost::math::isinf)(v)) + if ((BOOST_MATH_NAMESPACE::isinf)(v)) { return 0; } @@ -685,7 +780,7 @@ namespace boost { // == Student's t return 0; } - T mean = boost::math::detail::mean(v, delta, pol); + T mean = BOOST_MATH_NAMESPACE::detail::mean(v, delta, pol); T l2 = delta * delta; T var = ((l2 + 1) * v) / (v - 2) - mean * mean; T result = -2 * var; @@ -699,7 +794,7 @@ namespace boost T kurtosis_excess(T v, T delta, const Policy& pol) { BOOST_MATH_STD_USING - if ((boost::math::isinf)(v)) + if ((BOOST_MATH_NAMESPACE::isinf)(v)) { return 1; } @@ -707,7 +802,7 @@ namespace boost { // == Student's t return 1; } - T mean = boost::math::detail::mean(v, delta, pol); + T mean = BOOST_MATH_NAMESPACE::detail::mean(v, delta, pol); T l2 = delta * delta; T var = ((l2 + 1) * v) / (v - 2) - mean * mean; T result = -3 * var; @@ -759,6 +854,29 @@ namespace boost return policies::raise_evaluation_error(function, "Can't find degrees of freedom when the abscissa value is very close to zero as all degrees of freedom generate the same CDF at x=0: try again further out in the tails!!", RealType(std::numeric_limits::quiet_NaN()), Policy()); // LCOV_EXCL_LINE } + + // The limiting CDF values are + // + // v -> 0: Phi(-delta) + // v -> inf: Phi(x - delta) + // + // Outside the interval between these limits, a monotone CDF(v) + // has no inverse, and a non-monotone one may have several, so we + // cannot select a unique degree of freedom. This only screens + // out-of-range p: it does not detect multiple roots inside the + // interval. See https://github.com/boostorg/math/issues/1410 + normal_distribution normal; + RealType p0 = cdf(normal, -delta); + RealType pinf = cdf(normal, x - delta); + RealType lower = p0 < pinf ? p0 : pinf; + RealType upper = p0 < pinf ? pinf : p0; + if((p < lower) || (p > upper)) + { + return policies::raise_evaluation_error(function, + "Probability lies outside the interval between the limiting CDF values; the inverse is absent or non-unique: result was %1%", + RealType(std::numeric_limits::quiet_NaN()), Policy()); + } + t_degrees_of_freedom_finder f(delta, x, p < q ? p : q, p < q ? false : true); tools::eps_tolerance tol(policies::digits()); std::uintmax_t max_iter = policies::get_max_root_iterations(); @@ -835,7 +953,7 @@ namespace boost } } // namespace detail ====================================================================== - template > + BOOST_MATH_EXPORT template > class non_central_t_distribution { public: @@ -953,31 +1071,31 @@ namespace boost RealType ncp; // non-centrality parameter }; // template class non_central_t_distribution - typedef non_central_t_distribution non_central_t; // Reserved name of type double. + BOOST_MATH_EXPORT typedef non_central_t_distribution non_central_t; // Reserved name of type double. #ifdef __cpp_deduction_guides - template - non_central_t_distribution(RealType,RealType)->non_central_t_distribution::type>; + BOOST_MATH_EXPORT template + non_central_t_distribution(RealType,RealType)->non_central_t_distribution::type>; #endif // Non-member functions to give properties of the distribution. - template + BOOST_MATH_EXPORT template inline const std::pair range(const non_central_t_distribution& /* dist */) { // Range of permissible values for random variable k. - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; return std::pair(-max_value(), max_value()); } - template + BOOST_MATH_EXPORT template inline const std::pair support(const non_central_t_distribution& /* dist */) { // Range of supported values for random variable k. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; return std::pair(-max_value(), max_value()); } - template + BOOST_MATH_EXPORT template inline RealType mode(const non_central_t_distribution& dist) { // mode. static const char* function = "mode(non_central_t_distribution<%1%> const&)"; @@ -1007,7 +1125,7 @@ namespace boost sqrt(var)); } - template + BOOST_MATH_EXPORT template inline RealType mean(const non_central_t_distribution& dist) { BOOST_MATH_STD_USING @@ -1042,7 +1160,7 @@ namespace boost } // mean - template + BOOST_MATH_EXPORT template inline RealType variance(const non_central_t_distribution& dist) { // variance. const char* function = "variance(const non_central_t_distribution<%1%>&)"; @@ -1078,7 +1196,7 @@ namespace boost // RealType standard_deviation(const non_central_t_distribution& dist) // standard_deviation provided by derived accessors. - template + BOOST_MATH_EXPORT template inline RealType skewness(const non_central_t_distribution& dist) { // skewness = sqrt(l). const char* function = "skewness(const non_central_t_distribution<%1%>&)"; @@ -1110,7 +1228,7 @@ namespace boost detail::skewness(static_cast(v), static_cast(l), forwarding_policy()), function); } - template + BOOST_MATH_EXPORT template inline RealType kurtosis_excess(const non_central_t_distribution& dist) { const char* function = "kurtosis_excess(const non_central_t_distribution<%1%>&)"; @@ -1142,13 +1260,13 @@ namespace boost detail::kurtosis_excess(static_cast(v), static_cast(l), forwarding_policy()), function); } // kurtosis_excess - template + BOOST_MATH_EXPORT template inline RealType kurtosis(const non_central_t_distribution& dist) { return kurtosis_excess(dist) + 3; } - template + BOOST_MATH_EXPORT template inline RealType pdf(const non_central_t_distribution& dist, const RealType& t) { // Probability Density/Mass Function. const char* function = "pdf(non_central_t_distribution<%1%>, %1%)"; @@ -1187,7 +1305,7 @@ namespace boost function); } // pdf - template + BOOST_MATH_EXPORT template RealType cdf(const non_central_t_distribution& dist, const RealType& x) { const char* function = "boost::math::cdf(non_central_t_distribution<%1%>&, %1%)"; @@ -1219,7 +1337,7 @@ namespace boost &r, Policy())) return static_cast(r); - if ((boost::math::isinf)(v)) + if ((BOOST_MATH_NAMESPACE::isinf)(v)) { // Infinite degrees of freedom, so use normal distribution located at delta. normal_distribution n(l, 1); cdf(n, x); @@ -1239,7 +1357,7 @@ namespace boost function); } // cdf - template + BOOST_MATH_EXPORT template RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function // was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)"; @@ -1274,7 +1392,7 @@ namespace boost Policy())) return static_cast(r); - if ((boost::math::isinf)(v)) + if ((BOOST_MATH_NAMESPACE::isinf)(v)) { // Infinite degrees of freedom, so use normal distribution located at delta. normal_distribution n(l, 1); return cdf(complement(n, x)); @@ -1292,7 +1410,7 @@ namespace boost function); } // ccdf - template + BOOST_MATH_EXPORT template inline RealType quantile(const non_central_t_distribution& dist, const RealType& p) { // Quantile (or Percent Point) function. static const char* function = "quantile(const non_central_t_distribution<%1%>, %1%)"; @@ -1301,7 +1419,7 @@ namespace boost return detail::non_central_t_quantile(function, v, l, p, RealType(1-p), Policy()); } // quantile - template + BOOST_MATH_EXPORT template inline RealType quantile(const complemented2_type, RealType>& c) { // Quantile (or Percent Point) function. static const char* function = "quantile(const complement(non_central_t_distribution<%1%>, %1%))"; @@ -1312,8 +1430,7 @@ namespace boost return detail::non_central_t_quantile(function, v, l, RealType(1-q), q, Policy()); } // quantile complement. - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/normal.hpp b/include/boost/math/distributions/normal.hpp index aa27c8feb1..f04eae5925 100644 --- a/include/boost/math/distributions/normal.hpp +++ b/include/boost/math/distributions/normal.hpp @@ -26,9 +26,9 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template > +BOOST_MATH_EXPORT template > class normal_distribution { public: @@ -73,7 +73,7 @@ class normal_distribution RealType m_sd; // distribution standard deviation or scale. }; // class normal_distribution -using normal = normal_distribution; +BOOST_MATH_EXPORT using normal = normal_distribution; // // Deduction guides, note we don't check the @@ -82,10 +82,10 @@ using normal = normal_distribution; // #ifdef __cpp_deduction_guides -template -normal_distribution(RealType, RealType)->normal_distribution::type>; -template -normal_distribution(RealType)->normal_distribution::type>; +BOOST_MATH_EXPORT template +normal_distribution(RealType, RealType)->normal_distribution::type>; +BOOST_MATH_EXPORT template +normal_distribution(RealType)->normal_distribution::type>; #endif @@ -94,31 +94,31 @@ normal_distribution(RealType)->normal_distribution -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const normal_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const normal_distribution& /*dist*/) { // Range of permissible values for random variable x. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + max value. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + max value. } } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const normal_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const normal_distribution& /*dist*/) { // This is range values for random variable x where cdf rises from 0 to 1, and outside it, the pdf is zero. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + max value. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + max value. } } @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline boost::math::pair support(cons #pragma warning(pop) #endif -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const normal_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -145,7 +145,7 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const normal_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logpdf(const normal_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -174,7 +174,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const normal_distribution::infinity(); + RealType result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); if(false == detail::check_scale(function, sd, &result, Policy())) { return result; @@ -183,7 +183,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const normal_distribution(); - const RealType half = boost::math::constants::half(); + const RealType pi = BOOST_MATH_NAMESPACE::constants::pi(); + const RealType half = BOOST_MATH_NAMESPACE::constants::half(); result = -log(sd) - half*log(2*pi) - (x-mean)*(x-mean)/(2*sd*sd); return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const normal_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -217,7 +217,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const normal_distribution()); - result = boost::math::erfc(-diff, Policy()) / 2; + result = BOOST_MATH_NAMESPACE::erfc(-diff, Policy()) / 2; return result; } // cdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const normal_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions @@ -248,14 +248,14 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const normal_distribution(); result += mean; return result; } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -270,7 +270,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type()); - result = boost::math::erfc(diff, Policy()) / 2; + result = BOOST_MATH_NAMESPACE::erfc(diff, Policy()) / 2; return result; } // cdf complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -299,55 +299,55 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type(); result += mean; return result; } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const normal_distribution& dist) { return dist.mean(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const normal_distribution& dist) { return dist.standard_deviation(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const normal_distribution& dist) { return dist.mean(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const normal_distribution& dist) { return dist.mean(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const normal_distribution& /*dist*/) { return 0; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const normal_distribution& /*dist*/) { return 3; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const normal_distribution& /*dist*/) { return 0; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const normal_distribution & dist) { BOOST_MATH_STD_USING @@ -355,8 +355,7 @@ BOOST_MATH_GPU_ENABLED inline RealType entropy(const normal_distribution #include -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // Parameter checking. template @@ -38,7 +35,7 @@ namespace boost RealType scale, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(scale)) + if((BOOST_MATH_NAMESPACE::isfinite)(scale)) { // any > 0 finite value is OK. if (scale > 0) { @@ -67,7 +64,7 @@ namespace boost RealType shape, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(shape)) + if((BOOST_MATH_NAMESPACE::isfinite)(shape)) { // Any finite value > 0 is OK. if (shape > 0) { @@ -96,7 +93,7 @@ namespace boost RealType const& x, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(x)) + if((BOOST_MATH_NAMESPACE::isfinite)(x)) { // if (x > 0) { @@ -132,7 +129,7 @@ namespace boost } // namespace detail - template > + BOOST_MATH_EXPORT template > class pareto_distribution { public: @@ -161,32 +158,32 @@ namespace boost RealType m_shape; // distribution shape (k) or alpha }; - typedef pareto_distribution pareto; // Convenience to allow pareto(2., 3.); + BOOST_MATH_EXPORT typedef pareto_distribution pareto; // Convenience to allow pareto(2., 3.); #ifdef __cpp_deduction_guides - template - pareto_distribution(RealType)->pareto_distribution::type>; - template - pareto_distribution(RealType,RealType)->pareto_distribution::type>; + BOOST_MATH_EXPORT template + pareto_distribution(RealType)->pareto_distribution::type>; + BOOST_MATH_EXPORT template + pareto_distribution(RealType,RealType)->pareto_distribution::type>; #endif - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const pareto_distribution& /*dist*/) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const pareto_distribution& /*dist*/) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // scale zero to + infinity. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // scale zero to + infinity. } // range - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const pareto_distribution& dist) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const pareto_distribution& dist) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(dist.scale(), max_value() ); // scale to + infinity. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(dist.scale(), max_value() ); // scale to + infinity. } // support - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const pareto_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std function pow. @@ -205,7 +202,7 @@ namespace boost return result; } // pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const pareto_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std function pow. @@ -224,11 +221,11 @@ namespace boost } // result = RealType(1) - pow((scale / x), shape); - result = -boost::math::powm1(scale/x, shape, Policy()); // should be more accurate. + result = -BOOST_MATH_NAMESPACE::powm1(scale/x, shape, Policy()); // should be more accurate. return result; } // cdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const pareto_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std function pow. @@ -243,14 +240,14 @@ namespace boost if (x <= scale) { // regardless of shape, cdf is zero. - return -boost::math::numeric_limits::infinity(); + return -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } result = log1p(-pow(scale/x, shape), Policy()); return result; } // logcdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const pareto_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std function pow. @@ -277,7 +274,7 @@ namespace boost return result; } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std function pow. @@ -299,7 +296,7 @@ namespace boost return result; } // cdf complement - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std function pow. @@ -321,7 +318,7 @@ namespace boost return result; } // logcdf complement - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std function pow. @@ -348,7 +345,7 @@ namespace boost return result; } // quantile complement - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const pareto_distribution& dist) { RealType result = 0; @@ -363,18 +360,18 @@ namespace boost } else { - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; return max_value(); // +infinity. } } // mean - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const pareto_distribution& dist) { return dist.scale(); } // mode - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const pareto_distribution& dist) { RealType result = 0; @@ -387,7 +384,7 @@ namespace boost return dist.scale() * pow(RealType(2), (1/dist.shape())); } // median - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const pareto_distribution& dist) { RealType result = 0; @@ -412,7 +409,7 @@ namespace boost return result; } // variance - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const pareto_distribution& dist) { BOOST_MATH_STD_USING @@ -438,7 +435,7 @@ namespace boost return result; } // skewness - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const pareto_distribution& dist) { RealType result = 0; @@ -462,7 +459,7 @@ namespace boost return result; } // kurtosis - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const pareto_distribution& dist) { RealType result = 0; @@ -486,7 +483,7 @@ namespace boost return result; } // kurtosis_excess - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const pareto_distribution& dist) { BOOST_MATH_STD_USING @@ -495,8 +492,7 @@ namespace boost return log(xm/alpha) + 1 + 1/alpha; } - } // namespace math - } // namespace boost + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/poisson.hpp b/include/boost/math/distributions/poisson.hpp index c2fad66be0..b20d48ccea 100644 --- a/include/boost/math/distributions/poisson.hpp +++ b/include/boost/math/distributions/poisson.hpp @@ -50,11 +50,15 @@ #include // factorials. #include // for root finding. #include +#include +#include +#include -namespace boost -{ - namespace math - { +#ifndef BOOST_MATH_HAS_NVRTC +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace poisson_detail { // Common error checking routines for Poisson distribution functions. @@ -64,7 +68,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_mean(const char* function, const RealType& mean, RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(mean) || (mean < 0)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(mean) || (mean < 0)) { *result = policies::raise_domain_error( function, @@ -77,7 +81,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_mean_NZ(const char* function, const RealType& mean, RealType* result, const Policy& pol) { // mean == 0 is considered an error. - if( !(boost::math::isfinite)(mean) || (mean <= 0)) + if( !(BOOST_MATH_NAMESPACE::isfinite)(mean) || (mean <= 0)) { *result = policies::raise_domain_error( function, @@ -96,7 +100,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_k(const char* function, const RealType& k, RealType* result, const Policy& pol) { - if((k < 0) || !(boost::math::isfinite)(k)) + if((k < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(k)) { *result = policies::raise_domain_error( function, @@ -120,7 +124,7 @@ namespace boost template BOOST_MATH_GPU_ENABLED inline bool check_prob(const char* function, const RealType& p, RealType* result, const Policy& pol) { // Check 0 <= p <= 1 - if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(p) || (p < 0) || (p > 1)) { *result = policies::raise_domain_error( function, @@ -141,9 +145,10 @@ namespace boost return true; } // bool check_dist_and_prob + } // namespace poisson_detail - template > + BOOST_MATH_EXPORT template > class poisson_distribution { public: @@ -168,37 +173,37 @@ namespace boost RealType m_l; // mean number of occurrences. }; // template class poisson_distribution - using poisson = poisson_distribution; // Reserved name of type double. + BOOST_MATH_EXPORT using poisson = poisson_distribution; // Reserved name of type double. #ifdef __cpp_deduction_guides - template - poisson_distribution(RealType)->poisson_distribution::type>; + BOOST_MATH_EXPORT template + poisson_distribution(RealType)->poisson_distribution::type>; #endif // Non-member functions to give properties of the distribution. - template - BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const poisson_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const poisson_distribution& /* dist */) { // Range of permissible values for random variable k. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); // Max integer? + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); // Max integer? } - template - BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const poisson_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const poisson_distribution& /* dist */) { // Range of supported values for random variable k. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const poisson_distribution& dist) { // Mean of poisson distribution = lambda. return dist.mean(); } // mean - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const poisson_distribution& dist) { // mode. BOOST_MATH_STD_USING // ADL of std functions. @@ -207,7 +212,7 @@ namespace boost // Median now implemented via quantile(half) in derived accessors. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const poisson_distribution& dist) { // variance. return dist.mean(); @@ -215,14 +220,14 @@ namespace boost // standard_deviation provided by derived accessors. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const poisson_distribution& dist) { // skewness = sqrt(l). BOOST_MATH_STD_USING // ADL of std functions. return 1 / sqrt(dist.mean()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const poisson_distribution& dist) { // skewness = sqrt(l). return 1 / dist.mean(); // kurtosis_excess 1/mean from Wiki & MathWorld eq 31. @@ -231,7 +236,7 @@ namespace boost // whereas the true kurtosis is 3. } // RealType kurtosis_excess - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const poisson_distribution& dist) { // kurtosis is 4th moment about the mean = u4 / sd ^ 4 // http://en.wikipedia.org/wiki/Kurtosis @@ -243,7 +248,7 @@ namespace boost // whereas the true kurtosis is 3. } // RealType kurtosis - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType pdf(const poisson_distribution& dist, const RealType& k) { // Probability Density/Mass Function. // Probability that there are EXACTLY k occurrences (or arrivals). @@ -272,20 +277,20 @@ namespace boost { // mean ^ k = 1, and k! = 1, so can simplify. return exp(-mean); } - return boost::math::gamma_p_derivative(k+1, mean, Policy()); + return BOOST_MATH_NAMESPACE::gamma_p_derivative(k+1, mean, Policy()); } // pdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType logpdf(const poisson_distribution& dist, const RealType& k) { BOOST_FPU_EXCEPTION_GUARD BOOST_MATH_STD_USING // for ADL of std functions. - using boost::math::lgamma; + using BOOST_MATH_NAMESPACE::lgamma; RealType mean = dist.mean(); // Error check: - RealType result = -boost::math::numeric_limits::infinity(); + RealType result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); if(false == poisson_detail::check_dist_and_k( "boost::math::pdf(const poisson_distribution<%1%>&, %1%)", mean, @@ -298,20 +303,34 @@ namespace boost // Special case of mean zero, regardless of the number of events k. if (mean == 0) { // Probability for any k is zero. - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } // Special case where k and lambda are both positive if(k > 0 && mean > 0) { +#ifdef BOOST_MATH_HAS_GPU_SUPPORT return -lgamma(k+1) + k*log(mean) - mean; +#else + // For small k the direct formula has little cancellation, while Stirling's form would cancel + // its ln(2 pi k)/2 terms as k -> 0. Just above minimum_argument_for_bernoulli_recursion the + // Bernoulli series can still fail to converge (at k = 6.05 for double), so leave a margin. + if (k <= 2 * BOOST_MATH_NAMESPACE::detail::minimum_argument_for_bernoulli_recursion()) + { + // Below 1/2, ln(k!) = log1p(tgamma1pm1(k)) avoids rounding 1 + k. + const RealType log_k_factorial = k < RealType(0.5) ? RealType(log1p(tgamma1pm1(k, Policy()), Policy())) : RealType(lgamma(k+1, Policy())); + return -log_k_factorial + k*log(mean) - mean; + } + // Loader's (2000) saddle-point form, which avoids the cancellation of the direct formula when k is near mean. + return -BOOST_MATH_NAMESPACE::detail::stirlerr_series(k, Policy()) - BOOST_MATH_NAMESPACE::detail::bd0(mean, k, Policy()) - log(BOOST_MATH_NAMESPACE::constants::two_pi() * k) / 2; +#endif } result = log(pdf(dist, k)); return result; } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType cdf(const poisson_distribution& dist, const RealType& k) { // Cumulative Distribution Function Poisson. // The random variate k is the number of occurrences(or arrivals) @@ -362,7 +381,7 @@ namespace boost return gamma_q(k+1, mean, Policy()); } // binomial cdf - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType cdf(const complemented2_type, RealType>& c) { // Complemented Cumulative Distribution Function Poisson // The random variate k is the number of events, occurrences or arrivals. @@ -403,7 +422,7 @@ namespace boost } if (k == 0) { // Avoid repeated checks on k and mean in gamma_p. - return -boost::math::expm1(-mean, Policy()); + return -BOOST_MATH_NAMESPACE::expm1(-mean, Policy()); } // Unlike un-complemented cdf (sum from 0 to k), // can't use finite sum from k+1 to infinity for small integral k, @@ -412,7 +431,52 @@ namespace boost // CCDF = gamma_p(k+1, lambda) } // poisson ccdf - template + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline RealType logcdf(const poisson_distribution& dist, const RealType& k) + { + BOOST_MATH_STD_USING + RealType mean = dist.mean(); + RealType result = 0; + if(false == poisson_detail::check_dist_and_k( + "boost::math::logcdf(const poisson_distribution<%1%>&, %1%)", mean, k, &result, Policy())) + { + return result; + } + if (mean == 0) + { + return log(RealType(0)); + } + if (k == 0) + { + return -mean; + } + return BOOST_MATH_NAMESPACE::lgamma_q(k + 1, mean, Policy()); + } + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) + { + BOOST_MATH_STD_USING + RealType const& k = c.param; + RealType mean = c.dist.mean(); + RealType result = 0; + if(false == poisson_detail::check_dist_and_k( + "boost::math::logcdf(const poisson_distribution<%1%>&, %1%)", mean, k, &result, Policy())) + { + return result; + } + if (mean == 0) + { + return 0; + } + if (k == 0) + { + return log(-BOOST_MATH_NAMESPACE::expm1(-mean, Policy())); + } + return BOOST_MATH_NAMESPACE::lgamma_p(k + 1, mean, Policy()); + } + + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const poisson_distribution& dist, const RealType& p) { // Quantile (or Percent Point) Poisson function. // Return the number of expected events k for a given probability p. @@ -445,14 +509,14 @@ namespace boost return policies::raise_overflow_error(function, 0, Policy()); } using discrete_type = typename Policy::discrete_quantile_type; - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); RealType guess; RealType factor = 8; RealType z = dist.mean(); if(z < 1) guess = z; else - guess = boost::math::detail::inverse_poisson_cornish_fisher(z, p, RealType(1-p), Policy()); + guess = BOOST_MATH_NAMESPACE::detail::inverse_poisson_cornish_fisher(z, p, RealType(1-p), Policy()); if(z > 5) { if(z > 1000) @@ -478,7 +542,7 @@ namespace boost max_iter); } // quantile - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { // Quantile (or Percent Point) of Poisson function. // Return the number of expected events k for a given @@ -516,14 +580,14 @@ namespace boost return 0; // Exact result regardless of discrete-quantile Policy } using discrete_type = typename Policy::discrete_quantile_type; - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); RealType guess; RealType factor = 8; RealType z = dist.mean(); if(z < 1) guess = z; else - guess = boost::math::detail::inverse_poisson_cornish_fisher(z, RealType(1-q), q, Policy()); + guess = BOOST_MATH_NAMESPACE::detail::inverse_poisson_cornish_fisher(z, RealType(1-q), q, Policy()); if(z > 5) { if(z > 1000) @@ -549,8 +613,66 @@ namespace boost max_iter); } // quantile complement. - } // namespace math -} // namespace boost +#ifndef BOOST_MATH_HAS_NVRTC + // Not GPU enabled: the large-mean path uses Bernoulli numbers. + BOOST_MATH_EXPORT template + inline RealType entropy(const poisson_distribution& dist) + { + BOOST_MATH_STD_USING + // No closed form: -sum p log(p) from the log ratios of the probabilities (detail::discrete_entropy_sum). + constexpr auto function = "boost::math::entropy(const poisson_distribution<%1%>&)"; + RealType lambda = dist.mean(); + RealType result = 0; + if (!poisson_detail::check_dist(function, lambda, &result, Policy())) + return result; + const RealType sigmas = detail::discrete_entropy_tail_sigmas(); + const RealType threshold = detail::entropy_series_threshold(); + RealType sigma = sqrt(lambda); + if (sigma >= 2 * sigmas) + { + // Trapezoidal rule on the continuation S(t) = log(lambda^t Gamma(lambda) / Gamma(lambda + t)), + // centred on x = lambda - 1: + RealType h = sigma / detail::discrete_entropy_step_ratio(); + int j_right = 0; + int j_left = 0; + auto right = [&](RealType& s, RealType&) { s = -detail::entropy_lgamma_delta(lambda, RealType(++j_right * h), Policy()); return true; }; + auto left = [&](RealType& s, RealType&) + { + RealType t = -(++j_left) * h; + if (lambda + t < threshold) + return false; + s = -detail::entropy_lgamma_delta(lambda, t, Policy()); + return true; + }; + return detail::discrete_entropy_sum(right, left, h, RealType(0), function, Policy()); + } + // Direct sum from the mode, with p(k + 1) / p(k) = lambda / (k + 1): + RealType mode = floor(lambda); + RealType k_right = mode; + RealType k_left = mode; + detail::compensated_sum s_right; + detail::compensated_sum s_left; + auto right = [&](RealType& s, RealType& ratio) + { + s_right.add(detail::entropy_log_ratio(lambda, RealType(k_right + 1), RealType(lambda - (k_right + 1)), ratio, false, Policy())); + k_right += 1; + s = s_right.value(); + return true; + }; + auto left = [&](RealType& s, RealType& ratio) + { + if (k_left == 0) + return false; + s_left.add(-detail::entropy_log_ratio(lambda, k_left, RealType(lambda - k_left), ratio, true, Policy())); + k_left -= 1; + s = s_left.value(); + return true; + }; + return detail::discrete_entropy_sum(right, left, RealType(1), RealType(0), function, Policy()); + } +#endif + + BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/rayleigh.hpp b/include/boost/math/distributions/rayleigh.hpp index 155525b539..e537e96537 100644 --- a/include/boost/math/distributions/rayleigh.hpp +++ b/include/boost/math/distributions/rayleigh.hpp @@ -23,14 +23,14 @@ # pragma warning(disable: 4702) // unreachable code (return after domain_error throw). #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // Error checks: template BOOST_MATH_GPU_ENABLED inline bool verify_sigma(const char* function, RealType sigma, RealType* presult, const Policy& pol) { - if((sigma <= 0) || (!(boost::math::isfinite)(sigma))) + if((sigma <= 0) || (!(BOOST_MATH_NAMESPACE::isfinite)(sigma))) { *presult = policies::raise_domain_error( function, @@ -43,7 +43,7 @@ namespace detail template BOOST_MATH_GPU_ENABLED inline bool verify_rayleigh_x(const char* function, RealType x, RealType* presult, const Policy& pol) { - if((x < 0) || (boost::math::isnan)(x)) + if((x < 0) || (BOOST_MATH_NAMESPACE::isnan)(x)) { *presult = policies::raise_domain_error( function, @@ -54,7 +54,7 @@ namespace detail } // bool verify_rayleigh_x } // namespace detail -template > +BOOST_MATH_EXPORT template > class rayleigh_distribution { public: @@ -77,29 +77,29 @@ class rayleigh_distribution RealType m_sigma; }; // class rayleigh_distribution -using rayleigh = rayleigh_distribution; +BOOST_MATH_EXPORT using rayleigh = rayleigh_distribution; #ifdef __cpp_deduction_guides -template -rayleigh_distribution(RealType)->rayleigh_distribution::type>; +BOOST_MATH_EXPORT template +rayleigh_distribution(RealType)->rayleigh_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const rayleigh_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const rayleigh_distribution& /*dist*/) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : max_value()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const rayleigh_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const rayleigh_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const rayleigh_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std function exp. @@ -115,7 +115,7 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const rayleigh_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logpdf(const rayleigh_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std function exp. const RealType sigma = dist.sigma(); - RealType result = -boost::math::numeric_limits::infinity(); + RealType result = -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); constexpr auto function = "boost::math::logpdf(const rayleigh_distribution<%1%>&, %1%)"; if(false == detail::verify_sigma(function, sigma, &result, Policy())) @@ -141,7 +141,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const rayleigh_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const rayleigh_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -166,11 +166,11 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const rayleigh_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const rayleigh_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -180,17 +180,17 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const rayleigh_distribution::infinity(); + return -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } if(false == detail::verify_rayleigh_x(function, x, &result, Policy())) { - return -boost::math::numeric_limits::infinity(); + return -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } result = log1p(-exp(-x * x / ( 2 * sigma * sigma)), Policy()); return result; } // logcdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const rayleigh_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions @@ -211,11 +211,11 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const rayleigh_distribution(function, 0, Policy()); } - result = sqrt(-2 * sigma * sigma * boost::math::log1p(-p, Policy())); + result = sqrt(-2 * sigma * sigma * BOOST_MATH_NAMESPACE::log1p(-p, Policy())); return result; } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -240,7 +240,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -250,12 +250,12 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type::infinity(); + return -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } RealType x = c.param; if(false == detail::verify_rayleigh_x(function, x, &result, Policy())) { - return -boost::math::numeric_limits::infinity(); + return -BOOST_MATH_NAMESPACE::numeric_limits::infinity(); } RealType ea = x * x / (2 * sigma * sigma); // Fix for VC11/12 x64 bug in exp(float): @@ -265,7 +265,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions, log & sqrt. @@ -294,7 +294,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const rayleigh_distribution& dist) { RealType result = 0; @@ -304,11 +304,11 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const rayleigh_distribution(); } // mean -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const rayleigh_distribution& dist) { RealType result = 0; @@ -318,24 +318,24 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const rayleigh_distribution() * sigma * sigma / 2; } // variance -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const rayleigh_distribution& dist) { return dist.sigma(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const rayleigh_distribution& dist) { - using boost::math::constants::root_ln_four; + using BOOST_MATH_NAMESPACE::constants::root_ln_four; return root_ln_four() * dist.sigma(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const rayleigh_distribution& /*dist*/) { return static_cast(0.63111065781893713819189935154422777984404221106391L); @@ -343,7 +343,7 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const rayleigh_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const rayleigh_distribution& /*dist*/) { return static_cast(3.2450893006876380628486604106197544154170667057995L); @@ -351,7 +351,7 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const rayleigh_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const rayleigh_distribution& /*dist*/) { return static_cast(0.2450893006876380628486604106197544154170667057995L); @@ -359,15 +359,14 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const rayleigh_distributi // -(6*pi*pi - 24*pi + 16) / pow(4-pi,2) } // kurtosis_excess -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const rayleigh_distribution& dist) { BOOST_MATH_STD_USING return 1 + log(dist.sigma()*constants::one_div_root_two()) + constants::euler()/2; } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER # pragma warning(pop) diff --git a/include/boost/math/distributions/saspoint5.hpp b/include/boost/math/distributions/saspoint5.hpp index 7846b99560..d97f009da9 100644 --- a/include/boost/math/distributions/saspoint5.hpp +++ b/include/boost/math/distributions/saspoint5.hpp @@ -28,17 +28,19 @@ #ifndef BOOST_MATH_HAS_NVRTC #include +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif -namespace boost { namespace math { -template +BOOST_MATH_NAMESPACE_BEGIN +BOOST_MATH_EXPORT template class saspoint5_distribution; namespace detail { template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -343,7 +345,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_plus_imp_prec(const RealTyp template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -855,14 +857,14 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_plus_imp_prec(const RealTyp template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_imp_prec(const RealType& x, const boost::math::integral_constant &tag) { +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant &tag) { BOOST_MATH_STD_USING // for ADL of std functions return saspoint5_pdf_plus_imp_prec(abs(x), tag); } template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_imp_prec(const RealType& x, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant& tag) { BOOST_MATH_STD_USING // for ADL of std functions return saspoint5_pdf_plus_imp_prec(abs(x), tag); @@ -895,7 +897,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_pdf_imp(const saspoint5_distrib typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1169,7 +1171,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_plus_imp_prec(const RealTyp template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_plus_imp_prec(const RealType& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_plus_imp_prec(const RealType& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -1648,7 +1650,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_plus_imp_prec(const RealTyp } template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_imp_prec(const RealType& x, bool complement, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_imp_prec(const RealType& x, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return complement ? saspoint5_cdf_plus_imp_prec(x, tag) : 1 - saspoint5_cdf_plus_imp_prec(x, tag); } @@ -1656,12 +1658,12 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_imp_prec(const RealType& x, return complement ? 1 - saspoint5_cdf_plus_imp_prec(-x, tag) : saspoint5_cdf_plus_imp_prec(-x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_imp_prec(const RealType& x, bool complement, const boost::math::integral_constant& tag) { +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_imp_prec(const RealType& x, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (x >= 0) { return complement ? saspoint5_cdf_plus_imp_prec(x, tag) : 1 - saspoint5_cdf_plus_imp_prec(x, tag); } @@ -1669,7 +1671,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_imp_prec(const RealType& x, return complement ? 1 - saspoint5_cdf_plus_imp_prec(-x, tag) : saspoint5_cdf_plus_imp_prec(-x, tag); } else { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } } @@ -1700,7 +1702,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_cdf_imp(const saspoint5_distrib typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_upper_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_upper_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -2000,7 +2002,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_upper_imp_prec(const R template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_upper_imp_prec(const RealType& p, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_upper_imp_prec(const RealType& p, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING RealType result; @@ -2499,7 +2501,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_upper_imp_prec(const R } template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_imp_prec(const RealType& p, bool complement, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_imp_prec(const RealType& p, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (p > 0.5) { return !complement ? saspoint5_quantile_upper_imp_prec(1 - p, tag) : -saspoint5_quantile_upper_imp_prec(1 - p, tag); @@ -2509,7 +2511,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_imp_prec(const RealTyp } template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_imp_prec(const RealType& p, bool complement, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_imp_prec(const RealType& p, bool complement, const BOOST_MATH_NAMESPACE::integral_constant& tag) { if (p > 0.5) { return !complement ? saspoint5_quantile_upper_imp_prec(1 - p, tag) : -saspoint5_quantile_upper_imp_prec(1 - p, tag); @@ -2546,7 +2548,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_quantile_imp(const saspoint5_di typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_entropy_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_entropy_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return static_cast(3.63992444568030649573); } template -BOOST_MATH_GPU_ENABLED inline RealType saspoint5_entropy_imp_prec(const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline RealType saspoint5_entropy_imp_prec(const BOOST_MATH_NAMESPACE::integral_constant&) { return BOOST_MATH_BIG_CONSTANT(RealType, 113, 3.6399244456803064957308496039071853510); } @@ -2589,7 +2591,7 @@ BOOST_MATH_GPU_ENABLED inline RealType saspoint5_entropy_imp(const saspoint5_dis typedef typename tools::promote_args::type result_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant > +BOOST_MATH_EXPORT template > class saspoint5_distribution { public: @@ -2634,76 +2636,76 @@ class saspoint5_distribution RealType c; // The scale parameter. }; -typedef saspoint5_distribution saspoint5; +BOOST_MATH_EXPORT typedef saspoint5_distribution saspoint5; #ifdef __cpp_deduction_guides -template -saspoint5_distribution(RealType) -> saspoint5_distribution::type>; -template -saspoint5_distribution(RealType, RealType) -> saspoint5_distribution::type>; +BOOST_MATH_EXPORT template +saspoint5_distribution(RealType) -> saspoint5_distribution::type>; +BOOST_MATH_EXPORT template +saspoint5_distribution(RealType, RealType) -> saspoint5_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const saspoint5_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const saspoint5_distribution&) { // Range of permissible values for random variable x. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + max. } } -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const saspoint5_distribution&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const saspoint5_distribution&) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - return boost::math::pair(-boost::math::numeric_limits::infinity(), boost::math::numeric_limits::infinity()); // - to + infinity. + return BOOST_MATH_NAMESPACE::pair(-BOOST_MATH_NAMESPACE::numeric_limits::infinity(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); // - to + infinity. } else { // Can only use max_value. - using boost::math::tools::max_value; - return boost::math::pair(-tools::max_value(), max_value()); // - to + max. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-tools::max_value(), max_value()); // - to + max. } } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const saspoint5_distribution& dist, const RealType& x) { return detail::saspoint5_pdf_imp(dist, x); } // pdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const saspoint5_distribution& dist, const RealType& x) { return detail::saspoint5_cdf_imp(dist, x, false); } // cdf -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const saspoint5_distribution& dist, const RealType& p) { return detail::saspoint5_quantile_imp(dist, p, false); } // quantile -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { return detail::saspoint5_cdf_imp(c.dist, c.param, true); } // cdf complement -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { return detail::saspoint5_quantile_imp(c.dist, c.param, true); } // quantile complement -template -BOOST_MATH_GPU_ENABLED inline RealType mean(const saspoint5_distribution &dist) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType mean(const saspoint5_distribution &/*dist*/) { // There is no mean: typedef typename Policy::assert_undefined_type assert_type; @@ -2713,10 +2715,10 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const saspoint5_distribution&)", "The SaS point5 distribution does not have a mean: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const saspoint5_distribution& /*dist*/) { // There is no variance: @@ -2727,22 +2729,22 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const saspoint5_distribution&)", "The SaS point5 distribution does not have a variance: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const saspoint5_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const saspoint5_distribution& dist) { return dist.location(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const saspoint5_distribution& /*dist*/) { // There is no skewness: @@ -2753,10 +2755,10 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const saspoint5_distribution&)", "The SaS point5 distribution does not have a skewness: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); // infinity? + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); // infinity? } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const saspoint5_distribution& /*dist*/) { // There is no kurtosis: @@ -2767,10 +2769,10 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const saspoint5_distribution&)", "The SaS point5 distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const saspoint5_distribution& /*dist*/) { // There is no kurtosis excess: @@ -2781,16 +2783,16 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const saspoint5_distribut "boost::math::kurtosis_excess(saspoint5<%1%>&)", "The SaS point5 distribution does not have a kurtosis: " "the only possible return value is %1%.", - boost::math::numeric_limits::quiet_NaN(), Policy()); + BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const saspoint5_distribution& dist) { return detail::saspoint5_entropy_imp(dist); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_STATS_SASPOINT5_HPP diff --git a/include/boost/math/distributions/skew_normal.hpp b/include/boost/math/distributions/skew_normal.hpp index 28595a9ee8..0a3ecd65a7 100644 --- a/include/boost/math/distributions/skew_normal.hpp +++ b/include/boost/math/distributions/skew_normal.hpp @@ -17,6 +17,7 @@ #include // Owen's T function #include #include +#include #include #include #include @@ -24,14 +25,20 @@ #include #include // pdf max finder. +#ifndef BOOST_MATH_BUILD_MODULE #include #include // std::lower_bound, std::distance +#endif #ifdef BOOST_MATH_INSTRUMENT_SKEW_NORMAL_ITERATIONS extern std::uintmax_t global_iter_count; #endif -namespace boost{ namespace math{ +#ifndef BOOST_MATH_HAS_NVRTC +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -42,7 +49,7 @@ namespace boost{ namespace math{ RealType* result, const Policy& pol) { - if(!(boost::math::isfinite)(shape)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(shape)) { *result = policies::raise_domain_error(function, @@ -53,9 +60,25 @@ namespace boost{ namespace math{ return true; } +#ifndef BOOST_MATH_HAS_NVRTC + template + inline RealType skew_normal_tail_integral(RealType x, RealType shape, bool upper) + { + normal_distribution std_normal; + quadrature::exp_sinh integrator; + const RealType direction = upper ? static_cast(1) : static_cast(-1); + const auto integrand = [&](RealType t)->RealType + { + const RealType z = x + direction * t; + return static_cast(2) * pdf(std_normal, z) * cdf(std_normal, shape * z); + }; + return integrator.integrate(integrand, policies::get_epsilon() * 8); + } +#endif + } // namespace detail - template > + BOOST_MATH_EXPORT template > class skew_normal_distribution { public: @@ -98,36 +121,36 @@ namespace boost{ namespace math{ RealType shape_; // distribution shape. }; // class skew_normal_distribution - typedef skew_normal_distribution skew_normal; + BOOST_MATH_EXPORT typedef skew_normal_distribution skew_normal; #ifdef __cpp_deduction_guides - template - skew_normal_distribution(RealType)->skew_normal_distribution::type>; - template - skew_normal_distribution(RealType,RealType)->skew_normal_distribution::type>; - template - skew_normal_distribution(RealType,RealType,RealType)->skew_normal_distribution::type>; + BOOST_MATH_EXPORT template + skew_normal_distribution(RealType)->skew_normal_distribution::type>; + BOOST_MATH_EXPORT template + skew_normal_distribution(RealType,RealType)->skew_normal_distribution::type>; + BOOST_MATH_EXPORT template + skew_normal_distribution(RealType,RealType,RealType)->skew_normal_distribution::type>; #endif - template + BOOST_MATH_EXPORT template inline const std::pair range(const skew_normal_distribution& /*dist*/) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; return std::pair( std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -max_value(), std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : max_value()); // - to + max value. } - template + BOOST_MATH_EXPORT template inline const std::pair support(const skew_normal_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; return std::pair(-max_value(), max_value()); // - to + max value. } - template + BOOST_MATH_EXPORT template inline RealType pdf(const skew_normal_distribution& dist, const RealType& x) { const RealType scale = dist.scale(); @@ -149,7 +172,7 @@ namespace boost{ namespace math{ { return result; } - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) { return 0; // pdf + and - infinity is zero. } @@ -172,7 +195,7 @@ namespace boost{ namespace math{ return result; } // pdf - template + BOOST_MATH_EXPORT template inline RealType cdf(const skew_normal_distribution& dist, const RealType& x) { const RealType scale = dist.scale(); @@ -193,7 +216,7 @@ namespace boost{ namespace math{ { return result; } - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) { if(x < 0) return 0; // -infinity return 1; // + infinity @@ -216,12 +239,24 @@ namespace boost{ namespace math{ normal_distribution std_normal; - result = cdf(std_normal, transformed_x) - owens_t(transformed_x, shape)*static_cast(2); + const RealType normal_cdf = cdf(std_normal, transformed_x); + result = normal_cdf - owens_t(transformed_x, shape)*static_cast(2); + +#ifndef BOOST_MATH_HAS_NVRTC + // Subtraction magnifies the error in the normal CDF and Owen's T. + // Switch after losing three bits, rather than waiting until half the + // precision is lost: even moderate cancellation can spoil quantiles. + if((shape > 0) && (transformed_x < 0) + && (result < normal_cdf / static_cast(8))) + { + result = detail::skew_normal_tail_integral(transformed_x, shape, false); + } +#endif return result; } // cdf - template + BOOST_MATH_EXPORT template inline RealType cdf(const complemented2_type, RealType>& c) { const RealType scale = c.dist.scale(); @@ -231,7 +266,7 @@ namespace boost{ namespace math{ static const char* function = "boost::math::cdf(const complement(skew_normal_distribution<%1%>&), %1%)"; - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) { if(x < 0) return 1; // cdf complement -infinity is unity. return 0; // cdf complement +infinity is zero @@ -259,7 +294,17 @@ namespace boost{ namespace math{ normal_distribution std_normal; - result = cdf(complement(std_normal, transformed_x)) + owens_t(transformed_x, shape)*static_cast(2); + const RealType normal_cdf = cdf(complement(std_normal, transformed_x)); + result = normal_cdf + owens_t(transformed_x, shape)*static_cast(2); + +#ifndef BOOST_MATH_HAS_NVRTC + // The reflected tail has the same cancellation as the lower CDF. + if((shape < 0) && (transformed_x > 0) + && (result < normal_cdf / static_cast(8))) + { + result = detail::skew_normal_tail_integral(transformed_x, shape, true); + } +#endif return result; } // cdf complement @@ -281,12 +326,12 @@ namespace boost{ namespace math{ return dist.shape(); } - template + BOOST_MATH_EXPORT template inline RealType mean(const skew_normal_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; //const RealType delta = dist.shape() / sqrt(static_cast(1)+dist.shape()*dist.shape()); @@ -295,10 +340,10 @@ namespace boost{ namespace math{ return dist.location() + dist.scale() * dist.shape() / sqrt(pi()+pi()*dist.shape()*dist.shape()) * root_two(); } - template + BOOST_MATH_EXPORT template inline RealType variance(const skew_normal_distribution& dist) { - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; const RealType delta2 = dist.shape() != 0 ? static_cast(1) / (static_cast(1)+static_cast(1)/(dist.shape()*dist.shape())) : static_cast(0); //const RealType inv_delta2 = static_cast(1)+static_cast(1)/(dist.shape()*dist.shape()); @@ -435,12 +480,12 @@ namespace boost{ namespace math{ template struct skew_normal_mode_functor { - skew_normal_mode_functor(const boost::math::skew_normal_distribution dist) + skew_normal_mode_functor(const BOOST_MATH_NAMESPACE::skew_normal_distribution dist) : distribution(dist) { } - boost::math::tuple operator()(RealType const& x) + BOOST_MATH_NAMESPACE::tuple operator()(RealType const& x) { normal_distribution std_normal; const RealType shape = distribution.shape(); @@ -450,15 +495,15 @@ namespace boost{ namespace math{ RealType fx = static_cast(2)*shape*normpdf_ax*normpdf_x - x*pdf_x; RealType dx = static_cast(2)*shape*x*normpdf_x*normpdf_ax*(static_cast(1) + shape*shape) + pdf_x + x*fx; // return both function evaluation difference f(x) and 1st derivative f'(x). - return boost::math::make_tuple(fx, -dx); + return BOOST_MATH_NAMESPACE::make_tuple(fx, -dx); } private: - const boost::math::skew_normal_distribution distribution; + const BOOST_MATH_NAMESPACE::skew_normal_distribution distribution; }; } // namespace detail - template + BOOST_MATH_EXPORT template inline RealType mode(const skew_normal_distribution& dist) { const RealType scale = dist.scale(); @@ -584,11 +629,11 @@ namespace boost{ namespace math{ - template + BOOST_MATH_EXPORT template inline RealType skewness(const skew_normal_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; static const RealType factor = four_minus_pi()/static_cast(2); const RealType delta = dist.shape() / sqrt(static_cast(1)+dist.shape()*dist.shape()); @@ -597,16 +642,16 @@ namespace boost{ namespace math{ pow(static_cast(1)-two_div_pi()*delta*delta, static_cast(1.5))); } - template + BOOST_MATH_EXPORT template inline RealType kurtosis(const skew_normal_distribution& dist) { return kurtosis_excess(dist)+static_cast(3); } - template + BOOST_MATH_EXPORT template inline RealType kurtosis_excess(const skew_normal_distribution& dist) { - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; static const RealType factor = pi_minus_three()*static_cast(2); @@ -618,7 +663,7 @@ namespace boost{ namespace math{ return factor * y*y / (x*x); } - template + BOOST_MATH_EXPORT template inline RealType quantile(const skew_normal_distribution& dist, const RealType& p) { const RealType scale = dist.scale(); @@ -638,7 +683,7 @@ namespace boost{ namespace math{ return result; // Compute initial guess via Cornish-Fisher expansion. - RealType x = -boost::math::erfc_inv(2 * p, Policy()) * constants::root_two(); + RealType x = -BOOST_MATH_NAMESPACE::erfc_inv(2 * p, Policy()) * constants::root_two(); // Avoid unnecessary computations if there is no skew. if(shape != 0) @@ -651,11 +696,16 @@ namespace boost{ namespace math{ - x*(static_cast(2)*x*x-static_cast(5))*skew*skew/static_cast(36); } // if(shape != 0) - result = standard_deviation(dist)*x+mean(dist); - // handle special case of non-skew normal distribution. if(shape == 0) - return result; + return standard_deviation(dist)*x+mean(dist); + + // Search in standardized coordinates. bracket_and_solve_root expands + // multiplicatively about zero, so searching in the user's location/scale + // can turn a good initial estimate into a very wide bracket. + skew_normal_distribution standard_dist( + static_cast(0), static_cast(1), shape); + result = standard_deviation(standard_dist)*x+mean(standard_dist); // refine the result by numerically searching the root of (p-cdf) @@ -665,12 +715,12 @@ namespace boost{ namespace math{ if (result == 0) result = tools::min_value(); // we need to be one side of zero or the other for the root finder to work. - auto fun = [&, dist, p](const RealType& x)->RealType { return cdf(dist, x) - p; }; + auto fun = [&, standard_dist, p](const RealType& z)->RealType { return cdf(standard_dist, z) - p; }; RealType f_result = fun(result); if (f_result == 0) - return result; + return location + scale * result; if (f_result * result > 0) { @@ -702,7 +752,7 @@ namespace boost{ namespace math{ // // Try one last Newton step, just to close up the interval: // - RealType step = fun(result) / pdf(dist, result); + RealType step = fun(result) / pdf(standard_dist, result); if (result - step <= p_result.first) result = p_result.first; @@ -711,6 +761,8 @@ namespace boost{ namespace math{ else result -= step; + result = location + scale * result; + if (max_iter >= policies::get_max_root_iterations()) { return policies::raise_evaluation_error(function, "Unable to locate solution in a reasonable time: either there is no answer to quantile" // LCOV_EXCL_LINE @@ -720,7 +772,7 @@ namespace boost{ namespace math{ return result; } // quantile - template + BOOST_MATH_EXPORT template inline RealType quantile(const complemented2_type, RealType>& c) { const RealType scale = c.dist.scale(); @@ -747,8 +799,45 @@ namespace boost{ namespace math{ } // quantile -} // namespace math -} // namespace boost +#ifndef BOOST_MATH_HAS_NVRTC +// Not GPU enabled: uses quadrature. +BOOST_MATH_EXPORT template +inline RealType entropy(const skew_normal_distribution& dist) +{ + BOOST_MATH_STD_USING + // H = log(omega) + log(2 pi e)/2 - E[log(2 Phi(alpha Z))], Z the standard skew normal. Folding the + // integral onto x >= 0 turns Phi log(Phi) + (1 - Phi) log(1 - Phi) into the binary entropy h: + // H = log(omega) + log(2 pi e)/2 - log(2) + 2 int_0^inf phi(x) h(Phi(|alpha| x)) dx, + // which has no closed form but a smooth, positive, Gaussian-decaying integrand. + RealType alpha = fabs(dist.shape()); + auto h = [](RealType y) -> RealType + { + // Binary entropy of Phi(y) for y >= 0, with q = Phi(-y): + RealType q = BOOST_MATH_NAMESPACE::erfc(y * constants::one_div_root_two(), Policy()) / 2; + if (q == 0) + return RealType(0); + return -q * log(q) - (1 - q) * BOOST_MATH_NAMESPACE::log1p(-q, Policy()); + }; + RealType integral; + quadrature::exp_sinh integrator; + const RealType tol = policies::get_epsilon() * 8; + if (alpha <= 1) + { + auto f = [&](RealType x) -> RealType { return 2 * exp(-x * x / 2) * h(alpha * x); }; + integral = integrator.integrate(f, tol); + } + else + { + // y = alpha x keeps the integrand's width ~1 as alpha grows: + auto f = [&](RealType y) -> RealType { RealType x = y / alpha; return 2 * exp(-x * x / 2) * h(y); }; + integral = integrator.integrate(f, tol) / alpha; + } + return log(dist.scale()) + constants::half() - constants::ln_two() + integral * constants::one_div_root_two_pi() + + constants::log_root_two_pi(); +} +#endif + +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/students_t.hpp b/include/boost/math/distributions/students_t.hpp index 859118768e..466e949cbd 100644 --- a/include/boost/math/distributions/students_t.hpp +++ b/include/boost/math/distributions/students_t.hpp @@ -31,9 +31,9 @@ # pragma warning(disable: 4702) // unreachable code (return after domain_error throw). #endif -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template > +BOOST_MATH_EXPORT template > class students_t_distribution { public: @@ -69,33 +69,33 @@ class students_t_distribution RealType df_; // degrees of freedom is a real number > 0 or +infinity. }; -typedef students_t_distribution students_t; // Convenience typedef for double version. +BOOST_MATH_EXPORT typedef students_t_distribution students_t; // Convenience typedef for double version. #ifdef __cpp_deduction_guides -template -students_t_distribution(RealType)->students_t_distribution::type>; +BOOST_MATH_EXPORT template +students_t_distribution(RealType)->students_t_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const students_t_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const students_t_distribution& /*dist*/) { // Range of permissible values for random variable x. // Now including infinity. - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; //return boost::math::pair(-max_value(), max_value()); - return boost::math::pair(((::boost::math::numeric_limits::is_specialized & ::boost::math::numeric_limits::has_infinity) ? -boost::math::numeric_limits::infinity() : -max_value()), ((::boost::math::numeric_limits::is_specialized & ::boost::math::numeric_limits::has_infinity) ? +boost::math::numeric_limits::infinity() : +max_value())); + return BOOST_MATH_NAMESPACE::pair(((::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized & ::BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) ? -BOOST_MATH_NAMESPACE::numeric_limits::infinity() : -max_value()), ((::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized & ::BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) ? +BOOST_MATH_NAMESPACE::numeric_limits::infinity() : +max_value())); } -template -BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const students_t_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const students_t_distribution& /*dist*/) { // Range of supported values for random variable x. // Now including infinity. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::max_value; //return boost::math::pair(-max_value(), max_value()); - return boost::math::pair(((::boost::math::numeric_limits::is_specialized & ::boost::math::numeric_limits::has_infinity) ? -boost::math::numeric_limits::infinity() : -max_value()), ((::boost::math::numeric_limits::is_specialized & ::boost::math::numeric_limits::has_infinity) ? +boost::math::numeric_limits::infinity() : +max_value())); + return BOOST_MATH_NAMESPACE::pair(((::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized & ::BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) ? -BOOST_MATH_NAMESPACE::numeric_limits::infinity() : -max_value()), ((::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized & ::BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) ? +BOOST_MATH_NAMESPACE::numeric_limits::infinity() : +max_value())); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const students_t_distribution& dist, const RealType& x) { BOOST_FPU_EXCEPTION_GUARD @@ -111,7 +111,7 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const students_t_distribution(0); return result; @@ -137,18 +137,18 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const students_t_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const students_t_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -171,7 +171,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const students_t_distribution(0.5); } - if ((boost::math::isinf)(x)) + if ((BOOST_MATH_NAMESPACE::isinf)(x)) { // x == - or + infinity, regardless of df. return ((x < 0) ? static_cast(0) : static_cast(1)); } @@ -229,7 +229,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const students_t_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const students_t_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions @@ -280,16 +280,77 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const students_t_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { return cdf(c.dist, -c.param); } -template +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const students_t_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING + RealType error_result; + RealType df = dist.degrees_of_freedom(); + if (false == detail::check_df_gt0_to_inf( + "boost::math::logcdf(const students_t_distribution<%1%>&, %1%)", df, &error_result, Policy())) + { + return error_result; + } + if(false == detail::check_x_not_NaN( + "boost::math::logcdf(const students_t_distribution<%1%>&, %1%)", x, &error_result, Policy())) + { + return error_result; + } + if (x == 0) + { + return -constants::ln_two(); + } + if ((BOOST_MATH_NAMESPACE::isinf)(x)) + { + return (x < 0) ? log(RealType(0)) : RealType(0); + } + if ((BOOST_MATH_NAMESPACE::isinf)(df)) + { + // The normal limit. (Unlike cdf, finite df stays with the incomplete beta functions below: their logs + // reach the normal limit as df grows, where the normal cdf itself underflows.) + return logcdf(normal_distribution(0, 1), x); + } + // log of the lower tail, at -|x|, from the same two incomplete beta forms as cdf. Neither underflows, + // even where the tail itself does (huge df, or large |x|): + RealType ax = fabs(x); + RealType log_tail; + if (ax > sqrt(tools::max_value())) + { + // x^2 would overflow; df / (df + x^2) is then z = (df / |x|) / |x|. Where z is below epsilon (it may + // underflow), log I_z(a, 1/2) = a log(z) - log(a) - lbeta(a, 1/2) + O(z), with log(z) taken from the logs: + RealType z = (df / ax) / ax; + RealType a = df / 2; + log_tail = z < tools::epsilon() + ? RealType(a * (log(df) - 2 * log(ax)) - log(a) - BOOST_MATH_NAMESPACE::lbeta(a, static_cast(0.5), Policy())) + : RealType(BOOST_MATH_NAMESPACE::libeta(a, static_cast(0.5), z, Policy())); + } + else + { + RealType x2 = x * x; + log_tail = df > 2 * x2 + ? BOOST_MATH_NAMESPACE::libetac(static_cast(0.5), df / 2, RealType(x2 / (df + x2)), Policy()) + : BOOST_MATH_NAMESPACE::libeta(df / 2, static_cast(0.5), RealType(df / (df + x2)), Policy()); + } + log_tail -= constants::ln_two(); + return (x < 0) ? log_tail : RealType(BOOST_MATH_NAMESPACE::log1p(-exp(log_tail), Policy())); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) +{ + return logcdf(c.dist, -c.param); +} + +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { return -quantile(c.dist, c.param); @@ -309,7 +370,7 @@ BOOST_MATH_GPU_ENABLED inline bool analytical_df_if_cdf_matches(const Distributi // Minimum degrees-of-freedom used as the warm-start fallback when the // Edgeworth approximation yields no valid positive root or is inaccurate -constexpr double df_hint_fallback = 0.01; +BOOST_MATH_INLINE_CONSTEXPR double df_hint_fallback = 0.01; // // Functors for finding degrees of freedom: @@ -390,8 +451,8 @@ BOOST_MATH_GPU_ENABLED RealType solve_for_degrees_of_freedom( Policy const&) { tools::eps_tolerance tol(policies::digits()); - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); - boost::math::pair r = tools::bracket_and_solve_root( + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::pair r = tools::bracket_and_solve_root( f, hint, RealType(2), rising, tol, max_iter, Policy()); RealType result = r.first + (r.second - r.first) / 2; if (max_iter >= policies::get_max_root_iterations()) @@ -466,7 +527,7 @@ BOOST_MATH_GPU_ENABLED RealType calculate_hill_df_guess( RealType za = quantile(complement(n, alpha)); RealType zb = quantile(complement(n, beta)); - RealType v_norm = pow((za + zb) * sd / difference_from_mean, 2) - 1; + RealType v_norm = static_cast(pow((za + zb) * sd / difference_from_mean, 2) - 1); RealType hint = v_norm + (za * za - za * zb + zb * zb + 1) / 2; return (hint <= 0) ? RealType(1) : hint; @@ -525,11 +586,11 @@ BOOST_MATH_GPU_ENABLED RealType students_t_distribution::find_ } // Analytical cases: df = infinity (normal), df = 1 (cauchy) - boost::math::normal_distribution norm(0, 1); + BOOST_MATH_NAMESPACE::normal_distribution norm(0, 1); if (detail::analytical_df_if_cdf_matches(norm, t, p)) return policies::raise_overflow_error(function, nullptr, Policy()); - boost::math::cauchy_distribution cauchy(0, 1); - if (detail::analytical_df_if_cdf_matches(cauchy, t, p)) + BOOST_MATH_NAMESPACE::cauchy_distribution cauchy_dist(0, 1); + if (detail::analytical_df_if_cdf_matches(cauchy_dist, t, p)) return RealType(1); // Edgeworth warm start: compute a df estimate; fall back to df_hint_fallback if it fails @@ -553,14 +614,14 @@ BOOST_MATH_GPU_ENABLED RealType students_t_distribution::find_ return detail::solve_for_degrees_of_freedom(f, hint, t > 0, function, Policy()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const students_t_distribution& /*dist*/) { // Assume no checks on degrees of freedom are useful (unlike mean). return 0; // Always zero by definition. } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const students_t_distribution& /*dist*/) { // Assume no checks on degrees of freedom are useful (unlike mean). @@ -569,34 +630,34 @@ BOOST_MATH_GPU_ENABLED inline RealType median(const students_t_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const students_t_distribution& dist) { // Revised for https://svn.boost.org/trac/boost/ticket/7177 RealType df = dist.degrees_of_freedom(); - if(((boost::math::isnan)(df)) || (df <= 1) ) + if(((BOOST_MATH_NAMESPACE::isnan)(df)) || (df <= 1) ) { // mean is undefined for moment <= 1! return policies::raise_domain_error( "boost::math::mean(students_t_distribution<%1%> const&, %1%)", "Mean is undefined for degrees of freedom < 1 but got %1%.", df, Policy()); - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } return 0; } // mean -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const students_t_distribution& dist) { // http://en.wikipedia.org/wiki/Student%27s_t-distribution // Revised for https://svn.boost.org/trac/boost/ticket/7177 RealType df = dist.degrees_of_freedom(); - if ((boost::math::isnan)(df) || (df <= 2)) + if ((BOOST_MATH_NAMESPACE::isnan)(df) || (df <= 2)) { // NaN or undefined for <= 2. return policies::raise_domain_error( "boost::math::variance(students_t_distribution<%1%> const&, %1%)", "variance is undefined for degrees of freedom <= 2, but got %1%.", df, Policy()); - return boost::math::numeric_limits::quiet_NaN(); // Undefined. + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // Undefined. } - if ((boost::math::isinf)(df)) + if ((BOOST_MATH_NAMESPACE::isinf)(df)) { // +infinity. return 1; } @@ -615,34 +676,34 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const students_t_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const students_t_distribution& dist) { RealType df = dist.degrees_of_freedom(); - if( ((boost::math::isnan)(df)) || (dist.degrees_of_freedom() <= 3)) + if( ((BOOST_MATH_NAMESPACE::isnan)(df)) || (dist.degrees_of_freedom() <= 3)) { // Undefined for moment k = 3. return policies::raise_domain_error( "boost::math::skewness(students_t_distribution<%1%> const&, %1%)", "Skewness is undefined for degrees of freedom <= 3, but got %1%.", dist.degrees_of_freedom(), Policy()); - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } return 0; // For all valid df, including infinity. } // skewness -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const students_t_distribution& dist) { RealType df = dist.degrees_of_freedom(); - if(((boost::math::isnan)(df)) || (df <= 4)) + if(((BOOST_MATH_NAMESPACE::isnan)(df)) || (df <= 4)) { // Undefined or infinity for moment k = 4. return policies::raise_domain_error( "boost::math::kurtosis(students_t_distribution<%1%> const&, %1%)", "Kurtosis is undefined for degrees of freedom <= 4, but got %1%.", df, Policy()); - return boost::math::numeric_limits::quiet_NaN(); // Undefined. + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // Undefined. } - if ((boost::math::isinf)(df)) + if ((BOOST_MATH_NAMESPACE::isinf)(df)) { // +infinity. return 3; } @@ -662,21 +723,21 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const students_t_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const students_t_distribution& dist) { // see http://mathworld.wolfram.com/Kurtosis.html RealType df = dist.degrees_of_freedom(); - if(((boost::math::isnan)(df)) || (df <= 4)) + if(((BOOST_MATH_NAMESPACE::isnan)(df)) || (df <= 4)) { // Undefined or infinity for moment k = 4. return policies::raise_domain_error( "boost::math::kurtosis_excess(students_t_distribution<%1%> const&, %1%)", "Kurtosis_excess is undefined for degrees of freedom <= 4, but got %1%.", df, Policy()); - return boost::math::numeric_limits::quiet_NaN(); // Undefined. + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // Undefined. } - if ((boost::math::isinf)(df)) + if ((BOOST_MATH_NAMESPACE::isinf)(df)) { // +infinity. return 0; } @@ -695,7 +756,7 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const students_t_distribu } } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const students_t_distribution& dist) { BOOST_MATH_STD_USING @@ -706,8 +767,7 @@ BOOST_MATH_GPU_ENABLED inline RealType entropy(const students_t_distribution #include -namespace boost{ namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template @@ -35,7 +34,7 @@ namespace boost{ namespace math RealType lower, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(lower)) + if((BOOST_MATH_NAMESPACE::isfinite)(lower)) { // Any finite value is OK. return true; } @@ -54,7 +53,7 @@ namespace boost{ namespace math RealType mode, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(mode)) + if((BOOST_MATH_NAMESPACE::isfinite)(mode)) { // any finite value is OK. return true; } @@ -73,7 +72,7 @@ namespace boost{ namespace math RealType upper, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(upper)) + if((BOOST_MATH_NAMESPACE::isfinite)(upper)) { // any finite value is OK. return true; } @@ -92,7 +91,7 @@ namespace boost{ namespace math RealType const& x, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(x)) + if((BOOST_MATH_NAMESPACE::isfinite)(x)) { // Any finite value is OK return true; } @@ -147,7 +146,7 @@ namespace boost{ namespace math } // bool check_triangular } // namespace detail - template > + BOOST_MATH_EXPORT template > class triangular_distribution { public: @@ -183,32 +182,32 @@ namespace boost{ namespace math RealType m_upper; // distribution upper aka b }; // class triangular_distribution - typedef triangular_distribution triangular; + BOOST_MATH_EXPORT typedef triangular_distribution triangular; #ifdef __cpp_deduction_guides - template - triangular_distribution(RealType)->triangular_distribution::type>; - template - triangular_distribution(RealType,RealType)->triangular_distribution::type>; - template - triangular_distribution(RealType,RealType,RealType)->triangular_distribution::type>; + BOOST_MATH_EXPORT template + triangular_distribution(RealType)->triangular_distribution::type>; + BOOST_MATH_EXPORT template + triangular_distribution(RealType,RealType)->triangular_distribution::type>; + BOOST_MATH_EXPORT template + triangular_distribution(RealType,RealType,RealType)->triangular_distribution::type>; #endif - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const triangular_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const triangular_distribution& /* dist */) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const triangular_distribution& dist) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const triangular_distribution& dist) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - return boost::math::pair(dist.lower(), dist.upper()); + return BOOST_MATH_NAMESPACE::pair(dist.lower(), dist.upper()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType pdf(const triangular_distribution& dist, const RealType& x) { constexpr auto function = "boost::math::pdf(const triangular_distribution<%1%>&, %1%)"; @@ -246,7 +245,7 @@ namespace boost{ namespace math } } // RealType pdf(const triangular_distribution& dist, const RealType& x) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const triangular_distribution& dist, const RealType& x) { constexpr auto function = "boost::math::cdf(const triangular_distribution<%1%>&, %1%)"; @@ -281,7 +280,7 @@ namespace boost{ namespace math } } // RealType cdf(const triangular_distribution& dist, const RealType& x) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType quantile(const triangular_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions (sqrt). @@ -324,7 +323,7 @@ namespace boost{ namespace math } // RealType quantile(const triangular_distribution& dist, const RealType& q) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType cdf(const complemented2_type, RealType>& c) { constexpr auto function = "boost::math::cdf(const triangular_distribution<%1%>&, %1%)"; @@ -359,7 +358,7 @@ namespace boost{ namespace math } } // RealType cdf(const complemented2_type, RealType>& c) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // Aid ADL for sqrt. @@ -393,8 +392,6 @@ namespace boost{ namespace math RealType p0 = (mode - lower) / (upper - lower); if(p < p0) { - RealType s = (upper - lower) * (mode - lower); - s *= p; result = sqrt((upper - lower) * (mode - lower) * p) + lower; } else if (p == p0) @@ -408,7 +405,7 @@ namespace boost{ namespace math return result; } // RealType quantile(const complemented2_type, RealType>& c) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const triangular_distribution& dist) { constexpr auto function = "boost::math::mean(const triangular_distribution<%1%>&)"; @@ -424,7 +421,7 @@ namespace boost{ namespace math } // RealType mean(const triangular_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const triangular_distribution& dist) { constexpr auto function = "boost::math::mean(const triangular_distribution<%1%>&)"; @@ -439,7 +436,7 @@ namespace boost{ namespace math return (lower * lower + upper * upper + mode * mode - lower * upper - lower * mode - upper * mode) / 18; } // RealType variance(const triangular_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const triangular_distribution& dist) { constexpr auto function = "boost::math::mode(const triangular_distribution<%1%>&)"; @@ -452,7 +449,7 @@ namespace boost{ namespace math return mode; } // RealType mode - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const triangular_distribution& dist) { BOOST_MATH_STD_USING // ADL of std functions. @@ -475,18 +472,18 @@ namespace boost{ namespace math } } // RealType mode - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const triangular_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions - using namespace boost::math::constants; // for root_two + using namespace BOOST_MATH_NAMESPACE::constants; // for root_two constexpr auto function = "boost::math::skewness(const triangular_distribution<%1%>&)"; RealType lower = dist.lower(); RealType mode = dist.mode(); RealType upper = dist.upper(); RealType result = 0; // of checks. - if(false == boost::math::detail::check_triangular(function,lower, mode, upper, &result, Policy())) + if(false == BOOST_MATH_NAMESPACE::detail::check_triangular(function,lower, mode, upper, &result, Policy())) { return result; } @@ -496,7 +493,7 @@ namespace boost{ namespace math // #11768: Skewness formula for triangular distribution is incorrect - corrected 29 Oct 2015 for release 1.61. } // RealType skewness(const triangular_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const triangular_distribution& dist) { // These checks may be belt and braces as should have been checked on construction? constexpr auto function = "boost::math::kurtosis(const triangular_distribution<%1%>&)"; @@ -511,7 +508,7 @@ namespace boost{ namespace math return static_cast(12)/5; // 12/5 = 2.4; } // RealType kurtosis_excess(const triangular_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const triangular_distribution& dist) { // These checks may be belt and braces as should have been checked on construction? constexpr auto function = "boost::math::kurtosis_excess(const triangular_distribution<%1%>&)"; @@ -527,15 +524,14 @@ namespace boost{ namespace math // Assuming mathworld really means kurtosis excess? Wikipedia now corrected to match this. } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const triangular_distribution& dist) { BOOST_MATH_STD_USING return constants::half() + log((dist.upper() - dist.lower())/2); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/uniform.hpp b/include/boost/math/distributions/uniform.hpp index 08472f95e1..55e5f4f2ab 100644 --- a/include/boost/math/distributions/uniform.hpp +++ b/include/boost/math/distributions/uniform.hpp @@ -23,8 +23,7 @@ #include #include -namespace boost{ namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template @@ -33,7 +32,7 @@ namespace boost{ namespace math RealType lower, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(lower)) + if((BOOST_MATH_NAMESPACE::isfinite)(lower)) { // any finite value is OK. return true; } @@ -52,7 +51,7 @@ namespace boost{ namespace math RealType upper, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(upper)) + if((BOOST_MATH_NAMESPACE::isfinite)(upper)) { // Any finite value is OK. return true; } @@ -71,7 +70,7 @@ namespace boost{ namespace math RealType const& x, RealType* result, const Policy& pol) { - if((boost::math::isfinite)(x)) + if((BOOST_MATH_NAMESPACE::isfinite)(x)) { // Any finite value is OK return true; } @@ -111,7 +110,7 @@ namespace boost{ namespace math } // namespace detail - template > + BOOST_MATH_EXPORT template > class uniform_distribution { public: @@ -140,32 +139,32 @@ namespace boost{ namespace math RealType m_upper; // distribution upper aka b. }; // class uniform_distribution - typedef uniform_distribution uniform; + BOOST_MATH_EXPORT typedef uniform_distribution uniform; #ifdef __cpp_deduction_guides - template - uniform_distribution(RealType)->uniform_distribution::type>; - template - uniform_distribution(RealType,RealType)->uniform_distribution::type>; + BOOST_MATH_EXPORT template + uniform_distribution(RealType)->uniform_distribution::type>; + BOOST_MATH_EXPORT template + uniform_distribution(RealType,RealType)->uniform_distribution::type>; #endif - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair range(const uniform_distribution& /* dist */) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair range(const uniform_distribution& /* dist */) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(-max_value(), max_value()); // - to + 'infinity'. + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(-max_value(), max_value()); // - to + 'infinity'. // Note RealType infinity is NOT permitted, only max_value. } - template - BOOST_MATH_GPU_ENABLED inline const boost::math::pair support(const uniform_distribution& dist) + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED inline const BOOST_MATH_NAMESPACE::pair support(const uniform_distribution& dist) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - return boost::math::pair(dist.lower(), dist.upper()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(dist.lower(), dist.upper()); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const uniform_distribution& dist, const RealType& x) { RealType lower = dist.lower(); @@ -190,7 +189,7 @@ namespace boost{ namespace math } } // RealType pdf(const uniform_distribution& dist, const RealType& x) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const uniform_distribution& dist, const RealType& x) { RealType lower = dist.lower(); @@ -215,7 +214,7 @@ namespace boost{ namespace math return (x - lower) / (upper - lower); // lower <= x <= upper } // RealType cdf(const uniform_distribution& dist, const RealType& x) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const uniform_distribution& dist, const RealType& p) { RealType lower = dist.lower(); @@ -240,7 +239,7 @@ namespace boost{ namespace math return p * (upper - lower) + lower; } // RealType quantile(const uniform_distribution& dist, const RealType& p) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { RealType lower = c.dist.lower(); @@ -266,7 +265,7 @@ namespace boost{ namespace math return (upper - x) / (upper - lower); } // RealType cdf(const complemented2_type, RealType>& c) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { RealType lower = c.dist.lower(); @@ -292,7 +291,7 @@ namespace boost{ namespace math return -q * (upper - lower) + upper; } // RealType quantile(const complemented2_type, RealType>& c) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const uniform_distribution& dist) { RealType lower = dist.lower(); @@ -305,7 +304,7 @@ namespace boost{ namespace math return (lower + upper ) / 2; } // RealType mean(const uniform_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const uniform_distribution& dist) { RealType lower = dist.lower(); @@ -319,7 +318,7 @@ namespace boost{ namespace math // for standard uniform = 0.833333333333333333333333333333333333333333; } // RealType variance(const uniform_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const uniform_distribution& dist) { RealType lower = dist.lower(); @@ -333,7 +332,7 @@ namespace boost{ namespace math return result; } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const uniform_distribution& dist) { RealType lower = dist.lower(); @@ -345,7 +344,7 @@ namespace boost{ namespace math } return (lower + upper) / 2; // } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const uniform_distribution& dist) { RealType lower = dist.lower(); @@ -358,7 +357,7 @@ namespace boost{ namespace math return 0; } // RealType skewness(const uniform_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const uniform_distribution& dist) { RealType lower = dist.lower(); @@ -371,21 +370,20 @@ namespace boost{ namespace math return static_cast(-6)/5; // -6/5 = -1.2; } // RealType kurtosis_excess(const uniform_distribution& dist) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const uniform_distribution& dist) { return kurtosis_excess(dist) + 3; } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const uniform_distribution& dist) { BOOST_MATH_STD_USING return log(dist.upper() - dist.lower()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/distributions/von_mises.hpp b/include/boost/math/distributions/von_mises.hpp new file mode 100644 index 0000000000..0a5de5160a --- /dev/null +++ b/include/boost/math/distributions/von_mises.hpp @@ -0,0 +1,524 @@ +// Copyright John Maddock 2006, 2007. +// Copyright Paul A. Bristow 2006, 2007. +// Copyright Philipp C. J. Muenster, 2020. +// Copyright Matt Borland, 2022. +// +// 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) + +#ifndef BOOST_MATH_DISTRIBUTIONS_VON_MISES_HPP +#define BOOST_MATH_DISTRIBUTIONS_VON_MISES_HPP + +// https://en.wikipedia.org/wiki/Von_Mises_distribution +// From MathWorld--A Wolfram Web Resource. +// http://mathworld.wolfram.com/VonMisesDistribution.html + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN + +namespace detail { + +template +inline bool check_von_mises_concentration(const char* function, RealType concentration, RealType* result, const Policy& pol) +{ + if (!(BOOST_MATH_NAMESPACE::isfinite)(concentration) || (concentration < 0)) + { + *result = policies::raise_domain_error( + function, "Concentration parameter is %1%, but must be finite and >= 0!", concentration, pol); + return false; + } + return true; +} + +template +inline bool check_von_mises(const char* function, RealType mean, RealType concentration, RealType* result, const Policy& pol) +{ + return check_location(function, mean, result, pol) + && check_von_mises_concentration(function, concentration, result, pol); +} + +} // namespace detail + +BOOST_MATH_EXPORT template > +class von_mises_distribution +{ +public: + using value_type = RealType; + using policy_type = Policy; + + explicit von_mises_distribution(RealType l_mean = 0, RealType concentration = 1) + : m_mean {l_mean}, m_concentration {concentration} + { // Default is a 'standard' von Mises distribution vM01. + RealType result; + detail::check_von_mises("boost::math::von_mises_distribution<%1%>::von_mises_distribution", + l_mean, concentration, &result, Policy()); + } + + RealType mean() const + { // alias for location. + return m_mean; + } + + RealType concentration() const + { // alias for scale. + return m_concentration; + } + + // Synonyms, provided to allow generic use of find_location and find_scale. + RealType location() const + { + return m_mean; + } + RealType scale() const + { + return m_concentration; + } + +private: + RealType m_mean; + RealType m_concentration; +}; // class von_mises_distribution + +BOOST_MATH_EXPORT using von_mises = von_mises_distribution; + +#ifdef __cpp_deduction_guides +BOOST_MATH_EXPORT template +von_mises_distribution(RealType)->von_mises_distribution>; +BOOST_MATH_EXPORT template +von_mises_distribution(RealType,RealType)->von_mises_distribution>; +#endif + +BOOST_MATH_EXPORT template +inline std::pair range(const von_mises_distribution& /*dist*/) +{ // Range of permissible values for random variable x. + using BOOST_MATH_NAMESPACE::tools::max_value; + return std::pair(-max_value(), max_value()); +} + +BOOST_MATH_EXPORT template +inline std::pair support(const von_mises_distribution& dist) +{ // Range of x where the pdf is non-zero: one full turn centred on the mean. + const RealType pi = BOOST_MATH_NAMESPACE::constants::pi(); + return std::pair(dist.mean() - pi, dist.mean() + pi); +} + +namespace detail { + +// e^-k I0(k), which stays finite for all k. +template +RealType von_mises_scaled_i0(RealType k, const Policy& pol) +{ + BOOST_MATH_STD_USING + if (k < tools::log_max_value()) + { + return cyl_bessel_i(0, k, pol) * exp(-k); + } + // Here k is far beyond the precision, so the asymptotic series converges before its terms grow. + RealType term = 1; + RealType sum = 1; + for (unsigned j = 1; term > tools::epsilon() * sum; ++j) + { + term *= RealType((2 * j - 1) * (2 * j - 1)) / (8 * j * k); + sum += term; + } + return sum / sqrt(constants::two_pi() * k); +} + +// The circular variance 1 - I1(k)/I0(k) and ln(2 pi e^-k I0(k)), both without underflow and +// without the cancellation of forming I0 - I1: every sum below has positive terms. +template +void von_mises_moments(RealType k, RealType* circular_variance, RealType* log_two_pi_scaled_i0, const Policy&) +{ + BOOST_MATH_STD_USING + const RealType eps = tools::epsilon(); + // Beyond this the smallest term of the asymptotic series, about e^(-2k), is below eps. + const RealType asymptotic_limit = tools::digits() * constants::ln_two(); + if (k >= asymptotic_limit) + { + // e^-k I_nu(k) ~ (2 pi k)^(-1/2) sum_j (-1)^j a_j(nu) k^-j; every term of the I0 - I1 series is positive. + RealType t0 = 1; + RealType t1 = 1; + RealType sum0 = 1; + RealType sumd = 0; + for (unsigned j = 1; ; ++j) + { + t0 *= RealType((2 * j - 1) * (2 * j - 1)) / (8 * j * k); + t1 *= (RealType(2 * j) - 3) * (2 * j + 1) / (8 * j * k); + sum0 += t0; + sumd += t0 - t1; + if (t0 - t1 <= eps * sumd) + { + break; + } + } + *circular_variance = sumd / sum0; + *log_two_pi_scaled_i0 = log(sum0 * sqrt(constants::two_pi() / k)); + return; + } + // (1/pi) int_0^pi e^(-k(1 - cos t)) {1, 1 - cos t} dt by the trapezoidal rule, which for these + // periodic integrands at least squares the error with each halving of the step. + const RealType tol = sqrt(eps); + RealType f_end = exp(-2 * k); + RealType sum0 = (1 + f_end) / 2; + RealType sumd = f_end; + unsigned n = 1; + for (unsigned level = 0; level < 30; ++level) + { + RealType mid0 = 0; + RealType midd = 0; + for (unsigned j = 1; j < 2 * n; j += 2) + { + RealType s = sin(constants::pi() * j / (4 * n)); + RealType g = 2 * s * s; + RealType f = exp(-k * g); + mid0 += f; + midd += f * g; + } + // Compare the midpoint rule with the trapezoidal rule of the previous level. + const bool converged = (level > 1) && (fabs(mid0 - sum0) <= tol * sum0) && (fabs(midd - sumd) <= tol * sumd); + sum0 += mid0; + sumd += midd; + n *= 2; + if (converged) + { + break; + } + } + *circular_variance = sumd / sum0; + *log_two_pi_scaled_i0 = log(constants::two_pi() * sum0 / n); +} + +// int_0^width f(s) ds for the positive, smooth integrands below, which fall by at most the cutoff's +// number of e-folds over the interval. That interval is not a full period, so the trapezoidal rule +// would converge only as h^2: use Gauss-Legendre up to double precision, and tanh-sinh beyond. +template +RealType von_mises_integrate(F f, RealType width, const Policy&) +{ + BOOST_MATH_IF_CONSTEXPR (std::numeric_limits::is_specialized && (std::numeric_limits::digits <= 53)) + { + return quadrature::gauss::integrate(f, RealType(0), width); + } + else + { + static const quadrature::tanh_sinh integrator; + return integrator.integrate(f, RealType(0), width, policies::get_epsilon()); + } +} + +// Beyond this many e-folds the integrands are negligible: the part cut off is at most about +// e^-L sqrt(2L) of what is kept. +template +RealType von_mises_cutoff() +{ + BOOST_MATH_STD_USING + const RealType l0 = 1 - log(policies::get_epsilon()); + return l0 + log(l0); +} + +// The cdf of the standard distribution at -a, 0 <= a <= pi, which is at most 1/2: +// F(-a) = (1/(2 pi e^-k I0(k))) int_a^pi e^(-k(1 - cos t)) dt. +// The integrand is positive, so the left tail keeps its relative accuracy. +// It falls off like e^(-k(cos a - cos t)), so the range is cut where it drops below eps. +template +RealType von_mises_cdf_left(RealType k, RealType a, RealType s0, const Policy& pol) +{ + BOOST_MATH_STD_USING + const RealType pi = constants::pi(); + if (a >= pi) + { + return 0; + } + if (k == 0) + { + return (pi - a) / constants::two_pi(); + } + const RealType sin_half_a = sin(a / 2); + const RealType s2 = sin_half_a * sin_half_a + von_mises_cutoff() / (2 * k); + const RealType width = (s2 >= 1 ? pi : RealType(2 * asin(sqrt(s2)))) - a; + // In terms of the offset s = t - a, so that rounding t does not perturb the steep exponent: + // cos a - cos t = 2 sin(a + s/2) sin(s/2). + auto integrand = [&](RealType s) -> RealType + { + return exp(-2 * k * sin(a + s / 2) * sin(s / 2)); + }; + return exp(-2 * k * sin_half_a * sin_half_a) * von_mises_integrate(integrand, width, pol) / (constants::two_pi() * s0); +} + +// The probability between the mean and a, 0 <= a <= pi, with relative accuracy even as a -> 0: +// F(a) - 1/2 = (1/(2 pi e^-k I0(k))) int_0^a e^(-k(1 - cos t)) dt. +template +RealType von_mises_cdf_centre(RealType k, RealType a, RealType s0, const Policy& pol) +{ + BOOST_MATH_STD_USING + RealType width = a; + if (k > 0) + { + const RealType s2 = von_mises_cutoff() / (2 * k); + if (s2 < 1) + { + width = (std::min)(a, RealType(2 * asin(sqrt(s2)))); + } + } + auto integrand = [&](RealType t) -> RealType + { + RealType s = sin(t / 2); + return exp(-2 * k * s * s); + }; + return von_mises_integrate(integrand, width, pol) / (constants::two_pi() * s0); +} + +template +RealType von_mises_pdf_imp(RealType k, RealType u, RealType s0) +{ + BOOST_MATH_STD_USING + RealType s = sin(u / 2); + return exp(-2 * k * s * s) / (constants::two_pi() * s0); +} + +// Solves F(u) = p for u in [-pi, 0], where p <= 1/2. +template +RealType von_mises_quantile_left(RealType k, RealType p, const Policy& pol) +{ + BOOST_MATH_STD_USING + static const char* function = "boost::math::quantile(const von_mises_distribution<%1%>&, %1%)"; + const RealType pi = constants::pi(); + if (p <= 0) + { + return -pi; + } + const RealType s0 = von_mises_scaled_i0(k, pol); + std::uintmax_t max_iter = policies::get_max_root_iterations(); + const int digits = policies::digits(); + RealType result; + if (p >= 0.25f) + { + // Near the median solve for the distance a below it, so that the root is not + // lost against the 1/2 it sits beside: q = 1/2 - p is exact here. + const RealType q = 0.5f - p; + if (q == 0) + { + return 0; + } + RealType guess; + if (k < 1) + { + guess = constants::two_pi() * q; + } + else + { + // Wrapped normal with variance 1/k: 2 sqrt(k) sin(u/2) is close to standard normal. + RealType z = constants::root_two() * erf_inv(2 * q, pol) / (2 * sqrt(k)); + guess = z >= 1 ? RealType(pi / 2) : RealType(2 * asin(z)); + } + auto f = [&](RealType a) -> std::pair + { + return std::make_pair(von_mises_cdf_centre(k, a, s0, pol) - q, von_mises_pdf_imp(k, a, s0)); + }; + result = -tools::newton_raphson_iterate(f, guess, RealType(0), pi, digits, max_iter); + } + else + { + RealType guess; + if (k < 1) + { + guess = (2 * p - 1) * pi; + } + else + { + RealType z = -constants::root_two() * erfc_inv(2 * p, pol) / (2 * sqrt(k)); + guess = z <= -1 ? RealType(-pi / 2) : RealType(2 * asin(z)); + } + auto f = [&](RealType u) -> std::pair + { + return std::make_pair(von_mises_cdf_left(k, -u, s0, pol) - p, von_mises_pdf_imp(k, u, s0)); + }; + result = tools::newton_raphson_iterate(f, guess, -pi, RealType(0), digits, max_iter); + } + if (max_iter >= policies::get_max_root_iterations()) + { + return policies::raise_evaluation_error(function, + "Unable to locate solution in a reasonable time: either there is no answer to quantile or the answer is infinite. Current best guess is %1%", result, pol); + } + return result; +} + +} // namespace detail + +BOOST_MATH_EXPORT template +inline RealType pdf(const von_mises_distribution& dist, const RealType& x) +{ + BOOST_MATH_STD_USING + static const char* function = "boost::math::pdf(const von_mises_distribution<%1%>&, %1%)"; + const RealType k = dist.concentration(); + const RealType mean = dist.mean(); + RealType result = 0; + if (!detail::check_von_mises(function, mean, k, &result, Policy()) + || !detail::check_x(function, x, &result, Policy())) + { + return result; + } + const RealType u = x - mean; + if (fabs(u) > constants::pi()) + { + return 0; + } + return detail::von_mises_pdf_imp(k, u, detail::von_mises_scaled_i0(k, Policy())); +} + +BOOST_MATH_EXPORT template +inline RealType cdf(const von_mises_distribution& dist, const RealType& x) +{ + static const char* function = "boost::math::cdf(const von_mises_distribution<%1%>&, %1%)"; + const RealType k = dist.concentration(); + const RealType mean = dist.mean(); + RealType result = 0; + if (!detail::check_von_mises(function, mean, k, &result, Policy()) + || !detail::check_x(function, x, &result, Policy())) + { + return result; + } + const RealType u = x - mean; + const RealType s0 = detail::von_mises_scaled_i0(k, Policy()); + return u <= 0 ? detail::von_mises_cdf_left(k, -u, s0, Policy()) + : 1 - detail::von_mises_cdf_left(k, u, s0, Policy()); +} + +BOOST_MATH_EXPORT template +inline RealType cdf(const complemented2_type, RealType>& c) +{ + static const char* function = "boost::math::cdf(const complement(von_mises_distribution<%1%>&), %1%)"; + const RealType k = c.dist.concentration(); + const RealType mean = c.dist.mean(); + const RealType x = c.param; + RealType result = 0; + if (!detail::check_von_mises(function, mean, k, &result, Policy()) + || !detail::check_x(function, x, &result, Policy())) + { + return result; + } + const RealType u = x - mean; + const RealType s0 = detail::von_mises_scaled_i0(k, Policy()); + return u >= 0 ? detail::von_mises_cdf_left(k, u, s0, Policy()) + : 1 - detail::von_mises_cdf_left(k, -u, s0, Policy()); +} + +BOOST_MATH_EXPORT template +inline RealType quantile(const von_mises_distribution& dist, const RealType& p) +{ + static const char* function = "boost::math::quantile(const von_mises_distribution<%1%>&, %1%)"; + const RealType k = dist.concentration(); + const RealType mean = dist.mean(); + RealType result = 0; + if (!detail::check_von_mises(function, mean, k, &result, Policy()) + || !detail::check_probability(function, p, &result, Policy())) + { + return result; + } + // By symmetry F(-u) = 1 - F(u). + return p <= 0.5f ? mean + detail::von_mises_quantile_left(k, p, Policy()) + : mean - detail::von_mises_quantile_left(k, RealType(1 - p), Policy()); +} + +BOOST_MATH_EXPORT template +inline RealType quantile(const complemented2_type, RealType>& c) +{ + static const char* function = "boost::math::quantile(const complement(von_mises_distribution<%1%>&), %1%)"; + const RealType k = c.dist.concentration(); + const RealType mean = c.dist.mean(); + const RealType q = c.param; + RealType result = 0; + if (!detail::check_von_mises(function, mean, k, &result, Policy()) + || !detail::check_probability(function, q, &result, Policy())) + { + return result; + } + return q <= 0.5f ? mean - detail::von_mises_quantile_left(k, q, Policy()) + : mean + detail::von_mises_quantile_left(k, RealType(1 - q), Policy()); +} + +BOOST_MATH_EXPORT template +inline RealType mean(const von_mises_distribution& dist) +{ + return dist.mean(); +} + +BOOST_MATH_EXPORT template +inline RealType mode(const von_mises_distribution& dist) +{ + return dist.mean(); +} + +BOOST_MATH_EXPORT template +inline RealType median(const von_mises_distribution& dist) +{ + return dist.mean(); +} + +// Circular variance, 1 - I1(k)/I0(k). +BOOST_MATH_EXPORT template +inline RealType variance(const von_mises_distribution& dist) +{ + RealType v, log_two_pi_s0; + detail::von_mises_moments(dist.concentration(), &v, &log_two_pi_s0, Policy()); + return v; +} + +// Circular standard deviation, sqrt(-2 ln(I1(k)/I0(k))). +BOOST_MATH_EXPORT template +inline RealType standard_deviation(const von_mises_distribution& dist) +{ + BOOST_MATH_STD_USING + if (dist.concentration() == 0) + { + return policies::raise_overflow_error("boost::math::standard_deviation(const von_mises_distribution<%1%>&)", + "The circular standard deviation is infinite when the concentration is zero.", Policy()); + } + RealType v, log_two_pi_s0; + detail::von_mises_moments(dist.concentration(), &v, &log_two_pi_s0, Policy()); + return sqrt(-2 * log1p(-v, Policy())); +} + +BOOST_MATH_EXPORT template +inline RealType skewness(const von_mises_distribution& /*dist*/) +{ + return 0; +} + +BOOST_MATH_EXPORT template +inline RealType entropy(const von_mises_distribution& dist) +{ + BOOST_MATH_STD_USING + // ln(2 pi I0(k)) - k I1(k)/I0(k), with the e^k factors cancelled. + const RealType k = dist.concentration(); + RealType v, log_two_pi_s0; + detail::von_mises_moments(k, &v, &log_two_pi_s0, Policy()); + return log_two_pi_s0 + k * v; +} + +BOOST_MATH_NAMESPACE_END + +// This include must be at the end, *after* the accessors +// for this distribution have been defined, in order to +// keep compilers that support two-phase lookup happy. +#include + +#endif // BOOST_MATH_DISTRIBUTIONS_VON_MISES_HPP diff --git a/include/boost/math/distributions/weibull.hpp b/include/boost/math/distributions/weibull.hpp index eb4de106c8..0b44488eed 100644 --- a/include/boost/math/distributions/weibull.hpp +++ b/include/boost/math/distributions/weibull.hpp @@ -21,8 +21,7 @@ #include #include -namespace boost{ namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template @@ -31,7 +30,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_weibull_shape( RealType shape, RealType* result, const Policy& pol) { - if((shape <= 0) || !(boost::math::isfinite)(shape)) + if((shape <= 0) || !(BOOST_MATH_NAMESPACE::isfinite)(shape)) { *result = policies::raise_domain_error( function, @@ -47,7 +46,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_weibull_x( RealType const& x, RealType* result, const Policy& pol) { - if((x < 0) || !(boost::math::isfinite)(x)) + if((x < 0) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) { *result = policies::raise_domain_error( function, @@ -69,7 +68,7 @@ BOOST_MATH_GPU_ENABLED inline bool check_weibull( } // namespace detail -template > +BOOST_MATH_EXPORT template > class weibull_distribution { public: @@ -100,33 +99,33 @@ class weibull_distribution RealType m_scale; // distribution scale }; -using weibull = weibull_distribution; +BOOST_MATH_EXPORT using weibull = weibull_distribution; #ifdef __cpp_deduction_guides -template -weibull_distribution(RealType)->weibull_distribution::type>; -template -weibull_distribution(RealType,RealType)->weibull_distribution::type>; +BOOST_MATH_EXPORT template +weibull_distribution(RealType)->weibull_distribution::type>; +BOOST_MATH_EXPORT template +weibull_distribution(RealType,RealType)->weibull_distribution::type>; #endif -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const weibull_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair range(const weibull_distribution& /*dist*/) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + return BOOST_MATH_NAMESPACE::pair(static_cast(0), max_value()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const weibull_distribution& /*dist*/) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair support(const weibull_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - using boost::math::tools::min_value; - return boost::math::pair(min_value(), max_value()); + using BOOST_MATH_NAMESPACE::tools::max_value; + using BOOST_MATH_NAMESPACE::tools::min_value; + return BOOST_MATH_NAMESPACE::pair(min_value(), max_value()); // A discontinuity at x == 0, so only support down to min_value. } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType pdf(const weibull_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -160,7 +159,7 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const weibull_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logpdf(const weibull_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -182,9 +181,10 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const weibull_distribution 1) { - return 0; + return -policies::raise_overflow_error(function, nullptr, Policy()); } return policies::raise_overflow_error(function, 0, Policy()); } @@ -194,7 +194,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logpdf(const weibull_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const weibull_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -210,12 +210,12 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const weibull_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const weibull_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions @@ -236,7 +236,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const weibull_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const weibull_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions @@ -255,12 +255,12 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const weibull_distribution(function, 0, Policy()); - result = scale * pow(-boost::math::log1p(-p, Policy()), 1 / shape); + result = scale * pow(-BOOST_MATH_NAMESPACE::log1p(-p, Policy()), 1 / shape); return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -281,7 +281,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -302,7 +302,7 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions @@ -327,7 +327,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mean(const weibull_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -341,11 +341,11 @@ BOOST_MATH_GPU_ENABLED inline RealType mean(const weibull_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType variance(const weibull_distribution& dist) { RealType shape = dist.shape(); @@ -358,14 +358,14 @@ BOOST_MATH_GPU_ENABLED inline RealType variance(const weibull_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType mode(const weibull_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std function pow. @@ -386,7 +386,7 @@ BOOST_MATH_GPU_ENABLED inline RealType mode(const weibull_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType median(const weibull_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std function pow. @@ -401,12 +401,12 @@ BOOST_MATH_GPU_ENABLED inline RealType median(const weibull_distribution(), 1 / shape); return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType skewness(const weibull_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -422,16 +422,16 @@ BOOST_MATH_GPU_ENABLED inline RealType skewness(const weibull_distribution +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const weibull_distribution& dist) { BOOST_MATH_STD_USING // for ADL of std functions @@ -445,10 +445,10 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const weibull_distributio if(false == detail::check_weibull(function, scale, shape, &result, Policy())) return result; - RealType g1 = boost::math::tgamma(1 + 1 / shape, Policy()); - RealType g2 = boost::math::tgamma(1 + 2 / shape, Policy()); - RealType g3 = boost::math::tgamma(1 + 3 / shape, Policy()); - RealType g4 = boost::math::tgamma(1 + 4 / shape, Policy()); + RealType g1 = BOOST_MATH_NAMESPACE::tgamma(1 + 1 / shape, Policy()); + RealType g2 = BOOST_MATH_NAMESPACE::tgamma(1 + 2 / shape, Policy()); + RealType g3 = BOOST_MATH_NAMESPACE::tgamma(1 + 3 / shape, Policy()); + RealType g4 = BOOST_MATH_NAMESPACE::tgamma(1 + 4 / shape, Policy()); RealType g1_2 = g1 * g1; RealType g1_4 = g1_2 * g1_2; RealType d = g2 - g1_2; @@ -459,13 +459,13 @@ BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const weibull_distributio return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const weibull_distribution& dist) { return kurtosis_excess(dist) + 3; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline RealType entropy(const weibull_distribution& dist) { BOOST_MATH_STD_USING @@ -474,8 +474,7 @@ BOOST_MATH_GPU_ENABLED inline RealType entropy(const weibull_distribution()*(1-1/k) + log(lambda/k) + 1; } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END // This include must be at the end, *after* the accessors // for this distribution have been defined, in order to diff --git a/include/boost/math/filters/daubechies.hpp b/include/boost/math/filters/daubechies.hpp index 0655be3793..1c10e71500 100644 --- a/include/boost/math/filters/daubechies.hpp +++ b/include/boost/math/filters/daubechies.hpp @@ -6,8 +6,10 @@ */ #ifndef BOOST_MATH_FILTERS_DAUBECHIES_HPP #define BOOST_MATH_FILTERS_DAUBECHIES_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include @@ -18,7 +20,7 @@ #endif #endif -namespace boost::math::filters { +BOOST_MATH_NAMESPACE_BEGIN namespace filters { template constexpr std::array daubechies_scaling_filter() @@ -95,5 +97,5 @@ std::array daubechies_wavelet_filter() { return g; } -} // namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/barycentric_rational.hpp b/include/boost/math/interpolators/barycentric_rational.hpp index c18e38dd74..2e9be0e3d0 100644 --- a/include/boost/math/interpolators/barycentric_rational.hpp +++ b/include/boost/math/interpolators/barycentric_rational.hpp @@ -26,12 +26,14 @@ #ifndef BOOST_MATH_INTERPOLATORS_BARYCENTRIC_RATIONAL_HPP #define BOOST_MATH_INTERPOLATORS_BARYCENTRIC_RATIONAL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include -namespace boost{ namespace math{ namespace interpolators{ +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators{ -template +BOOST_MATH_EXPORT template class barycentric_rational { public: @@ -95,5 +97,5 @@ Real barycentric_rational::prime(Real x) const } -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/bezier_polynomial.hpp b/include/boost/math/interpolators/bezier_polynomial.hpp index 022d205c09..d7e8fc9a19 100644 --- a/include/boost/math/interpolators/bezier_polynomial.hpp +++ b/include/boost/math/interpolators/bezier_polynomial.hpp @@ -5,16 +5,20 @@ // or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_INTERPOLATORS_BEZIER_POLYNOMIAL_HPP #define BOOST_MATH_INTERPOLATORS_BEZIER_POLYNOMIAL_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #ifdef BOOST_MATH_NO_THREAD_LOCAL_WITH_NON_TRIVIAL_TYPES #warning "Thread local storage support is necessary for the Bezier polynomial class to work." #endif -namespace boost::math::interpolators { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template class bezier_polynomial { public: @@ -56,5 +60,5 @@ class bezier_polynomial std::shared_ptr> m_imp; }; -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/bilinear_uniform.hpp b/include/boost/math/interpolators/bilinear_uniform.hpp index 555204a875..28d0c51310 100644 --- a/include/boost/math/interpolators/bilinear_uniform.hpp +++ b/include/boost/math/interpolators/bilinear_uniform.hpp @@ -17,13 +17,17 @@ #ifndef BOOST_MATH_INTERPOLATORS_BILINEAR_UNIFORM_HPP #define BOOST_MATH_INTERPOLATORS_BILINEAR_UNIFORM_HPP +#include + +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include -namespace boost::math::interpolators { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template class bilinear_uniform { public: @@ -50,5 +54,5 @@ class bilinear_uniform std::shared_ptr> m_imp; }; -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/cardinal_cubic_b_spline.hpp b/include/boost/math/interpolators/cardinal_cubic_b_spline.hpp index 1a38caebae..26fb2952db 100644 --- a/include/boost/math/interpolators/cardinal_cubic_b_spline.hpp +++ b/include/boost/math/interpolators/cardinal_cubic_b_spline.hpp @@ -24,9 +24,9 @@ #include -namespace boost{ namespace math{ namespace interpolators { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template class cardinal_cubic_b_spline { public: @@ -83,5 +83,5 @@ Real cardinal_cubic_b_spline::double_prime(Real x) const } -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/cardinal_quadratic_b_spline.hpp b/include/boost/math/interpolators/cardinal_quadratic_b_spline.hpp index a5b150f2f1..58dfb0c3b1 100644 --- a/include/boost/math/interpolators/cardinal_quadratic_b_spline.hpp +++ b/include/boost/math/interpolators/cardinal_quadratic_b_spline.hpp @@ -6,13 +6,17 @@ #ifndef BOOST_MATH_INTERPOLATORS_CARDINAL_QUADRATIC_B_SPLINE_HPP #define BOOST_MATH_INTERPOLATORS_CARDINAL_QUADRATIC_B_SPLINE_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include -namespace boost{ namespace math{ namespace interpolators { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template class cardinal_quadratic_b_spline { public: @@ -53,5 +57,5 @@ class cardinal_quadratic_b_spline std::shared_ptr> impl_; }; -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/cardinal_quintic_b_spline.hpp b/include/boost/math/interpolators/cardinal_quintic_b_spline.hpp index 3d72865d93..540b530f2d 100644 --- a/include/boost/math/interpolators/cardinal_quintic_b_spline.hpp +++ b/include/boost/math/interpolators/cardinal_quintic_b_spline.hpp @@ -6,14 +6,16 @@ #ifndef BOOST_MATH_INTERPOLATORS_CARDINAL_QUINTIC_B_SPLINE_HPP #define BOOST_MATH_INTERPOLATORS_CARDINAL_QUINTIC_B_SPLINE_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include -namespace boost{ namespace math{ namespace interpolators { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template class cardinal_quintic_b_spline { public: @@ -58,5 +60,5 @@ class cardinal_quintic_b_spline std::shared_ptr> impl_; }; -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/cardinal_trigonometric.hpp b/include/boost/math/interpolators/cardinal_trigonometric.hpp index 28a58c8b28..62f4cac4a4 100644 --- a/include/boost/math/interpolators/cardinal_trigonometric.hpp +++ b/include/boost/math/interpolators/cardinal_trigonometric.hpp @@ -5,19 +5,21 @@ #ifndef BOOST_MATH_INTERPOLATORS_CARDINAL_TRIGONOMETRIC_HPP #define BOOST_MATH_INTERPOLATORS_CARDINAL_TRIGONOMETRIC_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include -namespace boost { namespace math { namespace interpolators { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template class cardinal_trigonometric { public: using Real = typename RandomAccessContainer::value_type; cardinal_trigonometric(RandomAccessContainer const & v, Real t0, Real h) { - m_impl = std::make_shared>(v.data(), v.size(), t0, h); + m_impl = std::make_shared>(v, t0, h); } Real operator()(Real t) const @@ -54,5 +56,5 @@ class cardinal_trigonometric std::shared_ptr> m_impl; }; -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/catmull_rom.hpp b/include/boost/math/interpolators/catmull_rom.hpp index cf8e3cb3b8..a16e826ffd 100644 --- a/include/boost/math/interpolators/catmull_rom.hpp +++ b/include/boost/math/interpolators/catmull_rom.hpp @@ -9,12 +9,16 @@ #ifndef BOOST_MATH_INTERPOLATORS_CATMULL_ROM #define BOOST_MATH_INTERPOLATORS_CATMULL_ROM +#include + +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include +#endif namespace std_workaround { @@ -34,7 +38,7 @@ namespace std_workaround { #endif } -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -53,7 +57,7 @@ namespace boost{ namespace math{ } } -template > +BOOST_MATH_EXPORT template > class catmull_rom { typedef typename Point::value_type value_type; @@ -306,5 +310,5 @@ Point catmull_rom::prime(const typename Point::val } -}} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/cubic_b_spline.hpp b/include/boost/math/interpolators/cubic_b_spline.hpp index a634f5168f..6538b9339c 100644 --- a/include/boost/math/interpolators/cubic_b_spline.hpp +++ b/include/boost/math/interpolators/cubic_b_spline.hpp @@ -27,7 +27,7 @@ BOOST_MATH_HEADER_DEPRECATED(""); -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN template class cubic_b_spline @@ -86,5 +86,5 @@ Real cubic_b_spline::double_prime(Real x) const } -}} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/cubic_hermite.hpp b/include/boost/math/interpolators/cubic_hermite.hpp index 04d1fa787f..7b853de845 100644 --- a/include/boost/math/interpolators/cubic_hermite.hpp +++ b/include/boost/math/interpolators/cubic_hermite.hpp @@ -6,21 +6,27 @@ #ifndef BOOST_MATH_INTERPOLATORS_CUBIC_HERMITE_HPP #define BOOST_MATH_INTERPOLATORS_CUBIC_HERMITE_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif +#include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template> class cubic_hermite { public: using Real = typename RandomAccessContainer::value_type; cubic_hermite(RandomAccessContainer && x, RandomAccessContainer && y, RandomAccessContainer && dydx) - : impl_(std::make_shared>(std::move(x), std::move(y), std::move(dydx))) + : impl_(std::make_shared>(std::move(x), std::move(y), std::move(dydx))) {} inline Real operator()(Real x) const { @@ -44,6 +50,7 @@ class cubic_hermite { std::int64_t bytes() const { + if ( ! valid()) return 0; return impl_->bytes() + sizeof(impl_); } @@ -52,17 +59,25 @@ class cubic_hermite { return impl_->domain(); } + bool valid() const { + return impl_->valid(); + } + + std::string const& error_msg() const { + return impl_->error_msg(); + } + private: - std::shared_ptr> impl_; + std::shared_ptr> impl_; }; -template +BOOST_MATH_EXPORT template> class cardinal_cubic_hermite { public: using Real = typename RandomAccessContainer::value_type; cardinal_cubic_hermite(RandomAccessContainer && y, RandomAccessContainer && dydx, Real x0, Real dx) - : impl_(std::make_shared>(std::move(y), std::move(dydx), x0, dx)) + : impl_(std::make_shared>(std::move(y), std::move(dydx), x0, dx)) {} inline Real operator()(Real x) const @@ -83,6 +98,7 @@ class cardinal_cubic_hermite { std::int64_t bytes() const { + if ( ! valid()) return 0; return impl_->bytes() + sizeof(impl_); } @@ -91,19 +107,27 @@ class cardinal_cubic_hermite { return impl_->domain(); } + bool valid() const { + return impl_->valid(); + } + + std::string const& error_msg() const { + return impl_->error_msg(); + } + private: - std::shared_ptr> impl_; + std::shared_ptr> impl_; }; -template +BOOST_MATH_EXPORT template> class cardinal_cubic_hermite_aos { public: using Point = typename RandomAccessContainer::value_type; using Real = typename Point::value_type; cardinal_cubic_hermite_aos(RandomAccessContainer && data, Real x0, Real dx) - : impl_(std::make_shared>(std::move(data), x0, dx)) + : impl_(std::make_shared>(std::move(data), x0, dx)) {} inline Real operator()(Real x) const @@ -124,6 +148,7 @@ class cardinal_cubic_hermite_aos { std::int64_t bytes() const { + if ( ! valid()) return 0; return impl_->bytes() + sizeof(impl_); } @@ -132,11 +157,18 @@ class cardinal_cubic_hermite_aos { return impl_->domain(); } + bool valid() const { + return impl_->valid(); + } + + std::string const& error_msg() const { + return impl_->error_msg(); + } + private: - std::shared_ptr> impl_; + std::shared_ptr> impl_; }; } -} -} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/barycentric_rational_detail.hpp b/include/boost/math/interpolators/detail/barycentric_rational_detail.hpp index 004bf3f9b5..0de42fb293 100644 --- a/include/boost/math/interpolators/detail/barycentric_rational_detail.hpp +++ b/include/boost/math/interpolators/detail/barycentric_rational_detail.hpp @@ -8,15 +8,17 @@ #ifndef BOOST_MATH_INTERPOLATORS_BARYCENTRIC_RATIONAL_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_BARYCENTRIC_RATIONAL_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include // for std::move #include // for std::is_sorted #include #include +#endif #include #include -namespace boost{ namespace math{ namespace interpolators { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { namespace detail{ template class barycentric_rational_imp @@ -70,13 +72,13 @@ barycentric_rational_imp::barycentric_rational_imp(InputIterator1 start_x, for(unsigned i = 0; start_x != end_x; ++start_x, ++start_y, ++i) { // But if we're going to do a memcpy, we can do some error checking which is inexpensive relative to the copy: - if(boost::math::isnan(*start_x)) + if(BOOST_MATH_NAMESPACE::isnan(*start_x)) { std::string msg = std::string("x[") + std::to_string(i) + "] is a NAN"; throw std::domain_error(msg); } - if(boost::math::isnan(*start_y)) + if(BOOST_MATH_NAMESPACE::isnan(*start_y)) { std::string msg = std::string("y[") + std::to_string(i) + "] is a NAN"; throw std::domain_error(msg); @@ -211,5 +213,5 @@ Real barycentric_rational_imp::prime(Real x) const return numerator/denominator; } -}}}} +}} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/bezier_polynomial_detail.hpp b/include/boost/math/interpolators/detail/bezier_polynomial_detail.hpp index 60fe5ab5d8..0571127134 100644 --- a/include/boost/math/interpolators/detail/bezier_polynomial_detail.hpp +++ b/include/boost/math/interpolators/detail/bezier_polynomial_detail.hpp @@ -7,18 +7,26 @@ #ifndef BOOST_MATH_INTERPOLATORS_BEZIER_POLYNOMIAL_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_BEZIER_POLYNOMIAL_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif + +#include -namespace boost::math::interpolators::detail { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators::detail { +// Each thread has its own scratch space, allocated on first use. template -static inline RandomAccessContainer& get_bezier_storage() +inline RandomAccessContainer& get_bezier_storage(typename RandomAccessContainer::size_type size) { static thread_local RandomAccessContainer the_storage; + if (the_storage.size() < size) { + the_storage.resize(size); + } return the_storage; } @@ -48,10 +56,6 @@ class bezier_polynomial_imp } } control_points_ = std::move(control_points); - auto & storage = get_bezier_storage(); - if (storage.size() < control_points_.size() -1) { - storage.resize(control_points_.size() -1); - } } inline Point operator()(Real t) const @@ -66,7 +70,7 @@ class bezier_polynomial_imp return p; } - auto & scratch_space = get_bezier_storage(); + auto & scratch_space = get_bezier_storage(control_points_.size() - 1); for (Z i = 0; i < control_points_.size() - 1; ++i) { for (Z j = 0; j < control_points_[0].size(); ++j) { scratch_space[i][j] = (1-t)*control_points_[i][j] + t*control_points_[i+1][j]; @@ -78,7 +82,7 @@ class bezier_polynomial_imp } Point prime(Real t) { - auto & scratch_space = get_bezier_storage(); + auto & scratch_space = get_bezier_storage(control_points_.size() - 1); for (Z i = 0; i < control_points_.size() - 1; ++i) { for (Z j = 0; j < control_points_[0].size(); ++j) { scratch_space[i][j] = control_points_[i+1][j] - control_points_[i][j]; @@ -163,5 +167,5 @@ class bezier_polynomial_imp }; -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/bilinear_uniform_detail.hpp b/include/boost/math/interpolators/detail/bilinear_uniform_detail.hpp index 590e961f7f..7e358b55c1 100644 --- a/include/boost/math/interpolators/detail/bilinear_uniform_detail.hpp +++ b/include/boost/math/interpolators/detail/bilinear_uniform_detail.hpp @@ -7,14 +7,18 @@ #ifndef BOOST_MATH_INTERPOLATORS_BILINEAR_UNIFORM_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_BILINEAR_UNIFORM_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include +#endif + +#include -namespace boost::math::interpolators::detail { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators::detail { template class bilinear_uniform_imp @@ -133,5 +137,5 @@ class bilinear_uniform_imp }; -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp b/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp index 2064caa515..38ee967f5a 100644 --- a/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp +++ b/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp @@ -7,15 +7,17 @@ #ifndef BOOST_MATH_INTERPOLATORS_CARDINAL_CUBIC_B_SPLINE_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_CARDINAL_CUBIC_B_SPLINE_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #include #include #include -namespace boost{ namespace math{ namespace interpolators{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators{ namespace detail{ template @@ -53,12 +55,12 @@ Real b3_spline(Real x) { Real y = 2 - absx; Real z = 1 - absx; - return boost::math::constants::sixth()*(y*y*y - 4*z*z*z); + return BOOST_MATH_NAMESPACE::constants::sixth()*(y*y*y - 4*z*z*z); } if (absx < 2) { Real y = 2 - absx; - return boost::math::constants::sixth()*y*y*y; + return BOOST_MATH_NAMESPACE::constants::sixth()*y*y*y; } return static_cast(0); } @@ -73,11 +75,11 @@ Real b3_spline_prime(Real x) if (x < 1) { - return x*(3*boost::math::constants::half()*x - 2); + return x*(3*BOOST_MATH_NAMESPACE::constants::half()*x - 2); } if (x < 2) { - return -boost::math::constants::half()*(2 - x)*(2 - x); + return -BOOST_MATH_NAMESPACE::constants::half()*(2 - x)*(2 - x); } return static_cast(0); } @@ -107,13 +109,13 @@ template cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, BidiIterator end_p, Real left_endpoint, Real step_size, Real left_endpoint_derivative, Real right_endpoint_derivative) : m_a(left_endpoint), m_avg(0) { - using boost::math::constants::third; + using BOOST_MATH_NAMESPACE::constants::third; std::size_t length = end_p - f; if (length < 5) { - if (boost::math::isnan(left_endpoint_derivative) || boost::math::isnan(right_endpoint_derivative)) + if (BOOST_MATH_NAMESPACE::isnan(left_endpoint_derivative) || BOOST_MATH_NAMESPACE::isnan(right_endpoint_derivative)) { throw std::logic_error("Interpolation using a cubic b spline with derivatives estimated at the endpoints requires at least 5 points.\n"); } @@ -123,7 +125,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B } } - if (boost::math::isnan(left_endpoint)) + if (BOOST_MATH_NAMESPACE::isnan(left_endpoint)) { throw std::logic_error("Left endpoint is NAN; this is disallowed.\n"); } @@ -145,7 +147,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B // to construct high-order estimates for one-sided derivatives: // https://en.wikipedia.org/wiki/Finite_difference_coefficient#Forward_and_backward_finite_difference // Here, we estimate then to O(h^4), as that is the maximum accuracy we could obtain from this method. - if (boost::math::isnan(a1)) + if (BOOST_MATH_NAMESPACE::isnan(a1)) { // For simple functions (linear, quadratic, so on) // almost all the error comes from derivative estimation. @@ -156,7 +158,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B } Real b1 = right_endpoint_derivative; - if (boost::math::isnan(b1)) + if (BOOST_MATH_NAMESPACE::isnan(b1)) { size_t n = length - 1; Real t0 = -4*(f[n - 1] + third()*f[n - 3]); @@ -178,7 +180,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B Real t = 1; for (size_t i = 0; i < length; ++i) { - if (boost::math::isnan(f[i])) + if (BOOST_MATH_NAMESPACE::isnan(f[i])) { std::string err = "This function you are trying to interpolate is a nan at index " + std::to_string(i) + "\n"; throw std::logic_error(err); @@ -274,8 +276,8 @@ Real cardinal_cubic_b_spline_imp::operator()(Real x) const using std::ceil; using std::floor; - size_t k_min = static_cast((max)(static_cast(0), boost::math::ltrunc(ceil(t - 2)))); - size_t k_max = static_cast((max)((min)(static_cast(m_beta.size() - 1), boost::math::ltrunc(floor(t + 2))), 0l)); + size_t k_min = static_cast((max)(static_cast(0), BOOST_MATH_NAMESPACE::ltrunc(ceil(t - 2)))); + size_t k_max = static_cast((max)((min)(static_cast(m_beta.size() - 1), BOOST_MATH_NAMESPACE::ltrunc(floor(t + 2))), 0l)); for (size_t k = k_min; k <= k_max; ++k) { @@ -296,8 +298,8 @@ Real cardinal_cubic_b_spline_imp::prime(Real x) const using std::ceil; using std::floor; - size_t k_min = static_cast((max)(static_cast(0), boost::math::ltrunc(ceil(t - 2)))); - size_t k_max = static_cast((min)(static_cast(m_beta.size() - 1), boost::math::ltrunc(floor(t + 2)))); + size_t k_min = static_cast((max)(static_cast(0), BOOST_MATH_NAMESPACE::ltrunc(ceil(t - 2)))); + size_t k_max = static_cast((min)(static_cast(m_beta.size() - 1), BOOST_MATH_NAMESPACE::ltrunc(floor(t + 2)))); for (size_t k = k_min; k <= k_max; ++k) { @@ -317,8 +319,8 @@ Real cardinal_cubic_b_spline_imp::double_prime(Real x) const using std::ceil; using std::floor; - size_t k_min = static_cast((max)(static_cast(0), boost::math::ltrunc(ceil(t - 2)))); - size_t k_max = static_cast((min)(static_cast(m_beta.size() - 1), boost::math::ltrunc(floor(t + 2)))); + size_t k_min = static_cast((max)(static_cast(0), BOOST_MATH_NAMESPACE::ltrunc(ceil(t - 2)))); + size_t k_max = static_cast((min)(static_cast(m_beta.size() - 1), BOOST_MATH_NAMESPACE::ltrunc(floor(t + 2)))); for (size_t k = k_min; k <= k_max; ++k) { @@ -327,5 +329,5 @@ Real cardinal_cubic_b_spline_imp::double_prime(Real x) const return z*m_h_inv*m_h_inv; } -}}}} +}} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp b/include/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp index cb5ce9f571..2ec9ba12fd 100644 --- a/include/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp +++ b/include/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp @@ -6,11 +6,15 @@ #ifndef BOOST_MATH_INTERPOLATORS_CARDINAL_QUADRATIC_B_SPLINE_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_CARDINAL_QUADRATIC_B_SPLINE_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif + +#include -namespace boost{ namespace math{ namespace interpolators{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators{ namespace detail{ template Real b2_spline(Real x) { @@ -204,5 +208,5 @@ class cardinal_quadratic_b_spline_detail Real m_t0; }; -}}}} +}} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/cardinal_quintic_b_spline_detail.hpp b/include/boost/math/interpolators/detail/cardinal_quintic_b_spline_detail.hpp index fcaa33661e..39eb706e69 100644 --- a/include/boost/math/interpolators/detail/cardinal_quintic_b_spline_detail.hpp +++ b/include/boost/math/interpolators/detail/cardinal_quintic_b_spline_detail.hpp @@ -6,13 +6,16 @@ #ifndef BOOST_MATH_INTERPOLATORS_CARDINAL_QUINTIC_B_SPLINE_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_CARDINAL_QUINTIC_B_SPLINE_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#include #include #include +#endif #include -namespace boost{ namespace math{ namespace interpolators{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators{ namespace detail{ template @@ -167,7 +170,7 @@ class cardinal_quintic_b_spline_detail Real operator()(Real t) const { using std::ceil; using std::floor; - using boost::math::cardinal_b_spline; + using BOOST_MATH_NAMESPACE::cardinal_b_spline; // tf = t0 + (n-1)*h // alpha.size() = n+4 if (t < m_t0 || t > m_t0 + (m_alpha.size()-5)/m_inv_h) { @@ -190,7 +193,7 @@ class cardinal_quintic_b_spline_detail Real prime(Real t) const { using std::ceil; using std::floor; - using boost::math::cardinal_b_spline_prime; + using BOOST_MATH_NAMESPACE::cardinal_b_spline_prime; if (t < m_t0 || t > m_t0 + (m_alpha.size()-5)/m_inv_h) { const char* err_msg = "Tried to evaluate the cardinal quintic b-spline outside the domain of of interpolation; extrapolation does not work."; throw std::domain_error(err_msg); @@ -210,7 +213,7 @@ class cardinal_quintic_b_spline_detail Real double_prime(Real t) const { using std::ceil; using std::floor; - using boost::math::cardinal_b_spline_double_prime; + using BOOST_MATH_NAMESPACE::cardinal_b_spline_double_prime; if (t < m_t0 || t > m_t0 + (m_alpha.size()-5)/m_inv_h) { const char* err_msg = "Tried to evaluate the cardinal quintic b-spline outside the domain of of interpolation; extrapolation does not work."; throw std::domain_error(err_msg); @@ -237,5 +240,5 @@ class cardinal_quintic_b_spline_detail Real m_t0; }; -}}}} +}} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/cardinal_trigonometric_detail.hpp b/include/boost/math/interpolators/detail/cardinal_trigonometric_detail.hpp index 62ef4bacec..c16de5cefb 100644 --- a/include/boost/math/interpolators/detail/cardinal_trigonometric_detail.hpp +++ b/include/boost/math/interpolators/detail/cardinal_trigonometric_detail.hpp @@ -5,48 +5,27 @@ #ifndef BOOST_MATH_INTERPOLATORS_DETAIL_CARDINAL_TRIGONOMETRIC_HPP #define BOOST_MATH_INTERPOLATORS_DETAIL_CARDINAL_TRIGONOMETRIC_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - -#ifdef __has_include -# if __has_include() -# include -# else -# error "This feature is unavailable without fftw3 installed" -#endif +#include #endif +#include +#include +#include -namespace boost { namespace math { namespace interpolators { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { namespace detail { template class cardinal_trigonometric_detail { public: - cardinal_trigonometric_detail(const Real* data, size_t length, Real t0, Real h) - { - m_data = data; - m_length = length; - m_t0 = t0; - m_h = h; - throw std::domain_error("Not implemented."); - } -private: - size_t m_length; - Real m_t0; - Real m_h; - Real* m_data; -}; + using complex_type = typename BOOST_MATH_NAMESPACE::tools::detail::complex_from_real::type; -template<> -class cardinal_trigonometric_detail { -public: - cardinal_trigonometric_detail(const float* data, size_t length, float t0, float h) : m_t0{t0}, m_h{h} + template + cardinal_trigonometric_detail(RandomAccessContainer const & v, Real t0, Real h) : m_t0{t0}, m_h{h} { + std::size_t length = v.size(); if (length == 0) { throw std::logic_error("At least one sample is required."); @@ -55,630 +34,120 @@ class cardinal_trigonometric_detail { { throw std::logic_error("The step size must be > 0"); } - // The period sadly must be stored, since the complex vector has length that cannot be used to recover the period: - m_T = m_h*length; - m_complex_vector_size = length/2 + 1; - m_gamma = fftwf_alloc_complex(m_complex_vector_size); - // The const_cast is legitimate: FFTW does not change the data as long as FFTW_ESTIMATE is provided. - fftwf_plan plan = fftwf_plan_dft_r2c_1d(length, const_cast(data), m_gamma, FFTW_ESTIMATE); - // FFTW says a null plan is impossible with the basic interface we are using, and I have no reason to doubt them. - // But it just feels weird not to check this: - if (!plan) - { - throw std::logic_error("A null fftw plan was created."); - } - - fftwf_execute(plan); - fftwf_destroy_plan(plan); + // The period must be stored, since it cannot be recovered from the number of Fourier coefficients: + m_T = m_h*static_cast(length); + m_gamma.resize(length/2 + 1); + BOOST_MATH_NAMESPACE::tools::real_fft fft(length); + fft.transform(v, m_gamma); - float denom = length; - for (size_t k = 0; k < m_complex_vector_size; ++k) + Real denom = static_cast(length); + for (auto& g : m_gamma) { - m_gamma[k][0] /= denom; - m_gamma[k][1] /= denom; + g = complex_type(Real(g.real()/denom), Real(g.imag()/denom)); } + // The transform of real data has a real mean; drop any rounding in its imaginary part. + m_gamma[0] = complex_type(Real(m_gamma[0].real()), Real(0)); if (length % 2 == 0) { - m_gamma[m_complex_vector_size -1][0] /= 2; - // numerically, m_gamma[m_complex_vector_size -1][1] should be zero . . . - // I believe, but need to check, that FFTW guarantees that it is identically zero. + m_gamma.back() = complex_type(Real(m_gamma.back().real()/2), Real(m_gamma.back().imag())); } } - cardinal_trigonometric_detail(const cardinal_trigonometric_detail& old) = delete; - - cardinal_trigonometric_detail& operator=(const cardinal_trigonometric_detail&) = delete; - - cardinal_trigonometric_detail(cardinal_trigonometric_detail &&) = delete; - - float operator()(float t) const + Real operator()(Real t) const { using std::sin; using std::cos; - using boost::math::constants::two_pi; - using std::exp; - float s = m_gamma[0][0]; - float x = two_pi()*(t - m_t0)/m_T; - fftwf_complex z; - // boost::math::cos_pi with a redefinition of x? Not now . . . - z[0] = cos(x); - z[1] = sin(x); - fftwf_complex b{0, 0}; - // u = b*z - fftwf_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = m_gamma[k][0] + u[0]; - b[1] = m_gamma[k][1] + u[1]; - } - - s += 2*(b[0]*z[0] - b[1]*z[1]); + using BOOST_MATH_NAMESPACE::constants::two_pi; + Real s = m_gamma[0].real(); + Real x = two_pi()*(t - m_t0)/m_T; + Real z0 = cos(x); + Real z1 = sin(x); + // Horner's method on the complex polynomial with b <- gamma[k] + b*z: + Real b0 = 0; + Real b1 = 0; + for (std::size_t k = m_gamma.size() - 1; k >= 1; --k) + { + Real u0 = b0*z0 - b1*z1; + Real u1 = b0*z1 + b1*z0; + b0 = m_gamma[k].real() + u0; + b1 = m_gamma[k].imag() + u1; + } + + s += 2*(b0*z0 - b1*z1); return s; } - float prime(float t) const - { - using std::sin; - using std::cos; - using boost::math::constants::two_pi; - using std::exp; - float x = two_pi()*(t - m_t0)/m_T; - fftwf_complex z; - z[0] = cos(x); - z[1] = sin(x); - fftwf_complex b{0, 0}; - // u = b*z - fftwf_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = k*m_gamma[k][0] + u[0]; - b[1] = k*m_gamma[k][1] + u[1]; - } - // b*z = (b[0]*z[0] - b[1]*z[1]) + i(b[1]*z[0] + b[0]*z[1]) - return -2*two_pi()*(b[1]*z[0] + b[0]*z[1])/m_T; - } - - float double_prime(float t) const - { - using std::sin; - using std::cos; - using boost::math::constants::two_pi; - using std::exp; - float x = two_pi()*(t - m_t0)/m_T; - fftwf_complex z; - z[0] = cos(x); - z[1] = sin(x); - fftwf_complex b{0, 0}; - // u = b*z - fftwf_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = k*k*m_gamma[k][0] + u[0]; - b[1] = k*k*m_gamma[k][1] + u[1]; - } - // b*z = (b[0]*z[0] - b[1]*z[1]) + i(b[1]*z[0] + b[0]*z[1]) - return -2*two_pi()*two_pi()*(b[0]*z[0] - b[1]*z[1])/(m_T*m_T); - } - - float period() const - { - return m_T; - } - - float integrate() const - { - return m_T*m_gamma[0][0]; - } - - float squared_l2() const - { - float s = 0; - // Always add smallest to largest for accuracy. - for (size_t i = m_complex_vector_size - 1; i >= 1; --i) - { - s += (m_gamma[i][0]*m_gamma[i][0] + m_gamma[i][1]*m_gamma[i][1]); - } - s *= 2; - s += m_gamma[0][0]*m_gamma[0][0]; - return s*m_T; - } - - - ~cardinal_trigonometric_detail() - { - if (m_gamma) - { - fftwf_free(m_gamma); - m_gamma = nullptr; - } - } - - -private: - float m_t0; - float m_h; - float m_T; - fftwf_complex* m_gamma; - size_t m_complex_vector_size; -}; - - -template<> -class cardinal_trigonometric_detail { -public: - cardinal_trigonometric_detail(const double* data, size_t length, double t0, double h) : m_t0{t0}, m_h{h} - { - if (length == 0) - { - throw std::logic_error("At least one sample is required."); - } - if (h <= 0) - { - throw std::logic_error("The step size must be > 0"); - } - m_T = m_h*length; - m_complex_vector_size = length/2 + 1; - m_gamma = fftw_alloc_complex(m_complex_vector_size); - fftw_plan plan = fftw_plan_dft_r2c_1d(length, const_cast(data), m_gamma, FFTW_ESTIMATE); - if (!plan) - { - throw std::logic_error("A null fftw plan was created."); - } - - fftw_execute(plan); - fftw_destroy_plan(plan); - - double denom = length; - for (size_t k = 0; k < m_complex_vector_size; ++k) - { - m_gamma[k][0] /= denom; - m_gamma[k][1] /= denom; - } - - if (length % 2 == 0) - { - m_gamma[m_complex_vector_size -1][0] /= 2; - } - } - - cardinal_trigonometric_detail(const cardinal_trigonometric_detail& old) = delete; - - cardinal_trigonometric_detail& operator=(const cardinal_trigonometric_detail&) = delete; - - cardinal_trigonometric_detail(cardinal_trigonometric_detail &&) = delete; - - double operator()(double t) const + Real prime(Real t) const { using std::sin; using std::cos; - using boost::math::constants::two_pi; - using std::exp; - double s = m_gamma[0][0]; - double x = two_pi()*(t - m_t0)/m_T; - fftw_complex z; - z[0] = cos(x); - z[1] = sin(x); - fftw_complex b{0, 0}; - // u = b*z - fftw_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = m_gamma[k][0] + u[0]; - b[1] = m_gamma[k][1] + u[1]; - } - - s += 2*(b[0]*z[0] - b[1]*z[1]); - return s; - } - - double prime(double t) const - { - using std::sin; - using std::cos; - using boost::math::constants::two_pi; - using std::exp; - double x = two_pi()*(t - m_t0)/m_T; - fftw_complex z; - z[0] = cos(x); - z[1] = sin(x); - fftw_complex b{0, 0}; - // u = b*z - fftw_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = k*m_gamma[k][0] + u[0]; - b[1] = k*m_gamma[k][1] + u[1]; - } - // b*z = (b[0]*z[0] - b[1]*z[1]) + i(b[1]*z[0] + b[0]*z[1]) - return -2*two_pi()*(b[1]*z[0] + b[0]*z[1])/m_T; - } - - double double_prime(double t) const - { - using std::sin; - using std::cos; - using boost::math::constants::two_pi; - using std::exp; - double x = two_pi()*(t - m_t0)/m_T; - fftw_complex z; - z[0] = cos(x); - z[1] = sin(x); - fftw_complex b{0, 0}; - // u = b*z - fftw_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = k*k*m_gamma[k][0] + u[0]; - b[1] = k*k*m_gamma[k][1] + u[1]; - } - // b*z = (b[0]*z[0] - b[1]*z[1]) + i(b[1]*z[0] + b[0]*z[1]) - return -2*two_pi()*two_pi()*(b[0]*z[0] - b[1]*z[1])/(m_T*m_T); - } - - double period() const - { - return m_T; - } - - double integrate() const - { - return m_T*m_gamma[0][0]; - } - - double squared_l2() const - { - double s = 0; - for (size_t i = m_complex_vector_size - 1; i >= 1; --i) + using BOOST_MATH_NAMESPACE::constants::two_pi; + Real x = two_pi()*(t - m_t0)/m_T; + Real z0 = cos(x); + Real z1 = sin(x); + Real b0 = 0; + Real b1 = 0; + for (std::size_t k = m_gamma.size() - 1; k >= 1; --k) { - s += (m_gamma[i][0]*m_gamma[i][0] + m_gamma[i][1]*m_gamma[i][1]); + Real u0 = b0*z0 - b1*z1; + Real u1 = b0*z1 + b1*z0; + b0 = static_cast(k)*m_gamma[k].real() + u0; + b1 = static_cast(k)*m_gamma[k].imag() + u1; } - s *= 2; - s += m_gamma[0][0]*m_gamma[0][0]; - return s*m_T; + // b*z = (b0*z0 - b1*z1) + i(b1*z0 + b0*z1) + return -2*two_pi()*(b1*z0 + b0*z1)/m_T; } - ~cardinal_trigonometric_detail() - { - if (m_gamma) - { - fftw_free(m_gamma); - m_gamma = nullptr; - } - } - -private: - double m_t0; - double m_h; - double m_T; - fftw_complex* m_gamma; - size_t m_complex_vector_size; -}; - - -template<> -class cardinal_trigonometric_detail { -public: - cardinal_trigonometric_detail(const long double* data, size_t length, long double t0, long double h) : m_t0{t0}, m_h{h} - { - if (length == 0) - { - throw std::logic_error("At least one sample is required."); - } - if (h <= 0) - { - throw std::logic_error("The step size must be > 0"); - } - m_T = m_h*length; - m_complex_vector_size = length/2 + 1; - m_gamma = fftwl_alloc_complex(m_complex_vector_size); - fftwl_plan plan = fftwl_plan_dft_r2c_1d(length, const_cast(data), m_gamma, FFTW_ESTIMATE); - if (!plan) - { - throw std::logic_error("A null fftw plan was created."); - } - - fftwl_execute(plan); - fftwl_destroy_plan(plan); - - long double denom = length; - for (size_t k = 0; k < m_complex_vector_size; ++k) - { - m_gamma[k][0] /= denom; - m_gamma[k][1] /= denom; - } - - if (length % 2 == 0) { - m_gamma[m_complex_vector_size -1][0] /= 2; - } - } - - cardinal_trigonometric_detail(const cardinal_trigonometric_detail& old) = delete; - - cardinal_trigonometric_detail& operator=(const cardinal_trigonometric_detail&) = delete; - - cardinal_trigonometric_detail(cardinal_trigonometric_detail &&) = delete; - - long double operator()(long double t) const - { - using std::sin; - using std::cos; - using boost::math::constants::two_pi; - using std::exp; - long double s = m_gamma[0][0]; - long double x = two_pi()*(t - m_t0)/m_T; - fftwl_complex z; - z[0] = cos(x); - z[1] = sin(x); - fftwl_complex b{0, 0}; - fftwl_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = m_gamma[k][0] + u[0]; - b[1] = m_gamma[k][1] + u[1]; - } - - s += 2*(b[0]*z[0] - b[1]*z[1]); - return s; - } - - long double prime(long double t) const - { - using std::sin; - using std::cos; - using boost::math::constants::two_pi; - using std::exp; - long double x = two_pi()*(t - m_t0)/m_T; - fftwl_complex z; - z[0] = cos(x); - z[1] = sin(x); - fftwl_complex b{0, 0}; - // u = b*z - fftwl_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = k*m_gamma[k][0] + u[0]; - b[1] = k*m_gamma[k][1] + u[1]; - } - // b*z = (b[0]*z[0] - b[1]*z[1]) + i(b[1]*z[0] + b[0]*z[1]) - return -2*two_pi()*(b[1]*z[0] + b[0]*z[1])/m_T; - } - - long double double_prime(long double t) const - { - using std::sin; - using std::cos; - using boost::math::constants::two_pi; - using std::exp; - long double x = two_pi()*(t - m_t0)/m_T; - fftwl_complex z; - z[0] = cos(x); - z[1] = sin(x); - fftwl_complex b{0, 0}; - // u = b*z - fftwl_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = k*k*m_gamma[k][0] + u[0]; - b[1] = k*k*m_gamma[k][1] + u[1]; - } - // b*z = (b[0]*z[0] - b[1]*z[1]) + i(b[1]*z[0] + b[0]*z[1]) - return -2*two_pi()*two_pi()*(b[0]*z[0] - b[1]*z[1])/(m_T*m_T); - } - - long double period() const - { - return m_T; - } - - long double integrate() const - { - return m_T*m_gamma[0][0]; - } - - long double squared_l2() const - { - long double s = 0; - for (size_t i = m_complex_vector_size - 1; i >= 1; --i) - { - s += (m_gamma[i][0]*m_gamma[i][0] + m_gamma[i][1]*m_gamma[i][1]); - } - s *= 2; - s += m_gamma[0][0]*m_gamma[0][0]; - return s*m_T; - } - - ~cardinal_trigonometric_detail() - { - if (m_gamma) - { - fftwl_free(m_gamma); - m_gamma = nullptr; - } - } - -private: - long double m_t0; - long double m_h; - long double m_T; - fftwl_complex* m_gamma; - size_t m_complex_vector_size; -}; - -#ifdef BOOST_HAS_FLOAT128 -template<> -class cardinal_trigonometric_detail<__float128> { -public: - cardinal_trigonometric_detail(const __float128* data, size_t length, __float128 t0, __float128 h) : m_t0{t0}, m_h{h} - { - if (length == 0) - { - throw std::logic_error("At least one sample is required."); - } - if (h <= 0) - { - throw std::logic_error("The step size must be > 0"); - } - m_T = m_h*length; - m_complex_vector_size = length/2 + 1; - m_gamma = fftwq_alloc_complex(m_complex_vector_size); - fftwq_plan plan = fftwq_plan_dft_r2c_1d(length, reinterpret_cast<__float128*>(const_cast<__float128*>(data)), m_gamma, FFTW_ESTIMATE); - if (!plan) - { - throw std::logic_error("A null fftw plan was created."); - } - - fftwq_execute(plan); - fftwq_destroy_plan(plan); - - __float128 denom = length; - for (size_t k = 0; k < m_complex_vector_size; ++k) - { - m_gamma[k][0] /= denom; - m_gamma[k][1] /= denom; - } - if (length % 2 == 0) - { - m_gamma[m_complex_vector_size -1][0] /= 2; - } - } - - cardinal_trigonometric_detail(const cardinal_trigonometric_detail& old) = delete; - - cardinal_trigonometric_detail& operator=(const cardinal_trigonometric_detail&) = delete; - - cardinal_trigonometric_detail(cardinal_trigonometric_detail &&) = delete; - - __float128 operator()(__float128 t) const + Real double_prime(Real t) const { using std::sin; using std::cos; - using boost::math::constants::two_pi; - using std::exp; - __float128 s = m_gamma[0][0]; - __float128 x = two_pi<__float128>()*(t - m_t0)/m_T; - fftwq_complex z; - z[0] = cosq(x); - z[1] = sinq(x); - fftwq_complex b{0, 0}; - fftwq_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) + using BOOST_MATH_NAMESPACE::constants::two_pi; + Real x = two_pi()*(t - m_t0)/m_T; + Real z0 = cos(x); + Real z1 = sin(x); + Real b0 = 0; + Real b1 = 0; + for (std::size_t k = m_gamma.size() - 1; k >= 1; --k) { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = m_gamma[k][0] + u[0]; - b[1] = m_gamma[k][1] + u[1]; + Real u0 = b0*z0 - b1*z1; + Real u1 = b0*z1 + b1*z0; + b0 = static_cast(k*k)*m_gamma[k].real() + u0; + b1 = static_cast(k*k)*m_gamma[k].imag() + u1; } - - s += 2*(b[0]*z[0] - b[1]*z[1]); - return s; - } - - __float128 prime(__float128 t) const - { - using std::sin; - using std::cos; - using boost::math::constants::two_pi; - using std::exp; - __float128 x = two_pi<__float128>()*(t - m_t0)/m_T; - fftwq_complex z; - z[0] = cosq(x); - z[1] = sinq(x); - fftwq_complex b{0, 0}; - // u = b*z - fftwq_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = k*m_gamma[k][0] + u[0]; - b[1] = k*m_gamma[k][1] + u[1]; - } - // b*z = (b[0]*z[0] - b[1]*z[1]) + i(b[1]*z[0] + b[0]*z[1]) - return -2*two_pi<__float128>()*(b[1]*z[0] + b[0]*z[1])/m_T; - } - - __float128 double_prime(__float128 t) const - { - using std::sin; - using std::cos; - using boost::math::constants::two_pi; - using std::exp; - __float128 x = two_pi<__float128>()*(t - m_t0)/m_T; - fftwq_complex z; - z[0] = cosq(x); - z[1] = sinq(x); - fftwq_complex b{0, 0}; - // u = b*z - fftwq_complex u; - for (size_t k = m_complex_vector_size - 1; k >= 1; --k) - { - u[0] = b[0]*z[0] - b[1]*z[1]; - u[1] = b[0]*z[1] + b[1]*z[0]; - b[0] = k*k*m_gamma[k][0] + u[0]; - b[1] = k*k*m_gamma[k][1] + u[1]; - } - // b*z = (b[0]*z[0] - b[1]*z[1]) + i(b[1]*z[0] + b[0]*z[1]) - return -2*two_pi<__float128>()*two_pi<__float128>()*(b[0]*z[0] - b[1]*z[1])/(m_T*m_T); + return -2*two_pi()*two_pi()*(b0*z0 - b1*z1)/(m_T*m_T); } - __float128 period() const + Real period() const { return m_T; } - __float128 integrate() const + Real integrate() const { - return m_T*m_gamma[0][0]; + return m_T*m_gamma[0].real(); } - __float128 squared_l2() const + Real squared_l2() const { - __float128 s = 0; - for (size_t i = m_complex_vector_size - 1; i >= 1; --i) + Real s = 0; + // Add the smallest terms first for accuracy. + for (std::size_t i = m_gamma.size() - 1; i >= 1; --i) { - s += (m_gamma[i][0]*m_gamma[i][0] + m_gamma[i][1]*m_gamma[i][1]); + s += (m_gamma[i].real()*m_gamma[i].real() + m_gamma[i].imag()*m_gamma[i].imag()); } s *= 2; - s += m_gamma[0][0]*m_gamma[0][0]; + s += m_gamma[0].real()*m_gamma[0].real(); return s*m_T; } - ~cardinal_trigonometric_detail() - { - if (m_gamma) - { - fftwq_free(m_gamma); - m_gamma = nullptr; - } - } - - private: - __float128 m_t0; - __float128 m_h; - __float128 m_T; - fftwq_complex* m_gamma; - size_t m_complex_vector_size; + Real m_t0; + Real m_h; + Real m_T; + std::vector m_gamma; }; -#endif -}}}} +}} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/cubic_b_spline_detail.hpp b/include/boost/math/interpolators/detail/cubic_b_spline_detail.hpp index ac2ce29dd8..feb59ba792 100644 --- a/include/boost/math/interpolators/detail/cubic_b_spline_detail.hpp +++ b/include/boost/math/interpolators/detail/cubic_b_spline_detail.hpp @@ -7,14 +7,16 @@ #ifndef CUBIC_B_SPLINE_DETAIL_HPP #define CUBIC_B_SPLINE_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template @@ -52,12 +54,12 @@ Real b3_spline(Real x) { Real y = 2 - absx; Real z = 1 - absx; - return boost::math::constants::sixth()*(y*y*y - 4*z*z*z); + return BOOST_MATH_NAMESPACE::constants::sixth()*(y*y*y - 4*z*z*z); } if (absx < 2) { Real y = 2 - absx; - return boost::math::constants::sixth()*y*y*y; + return BOOST_MATH_NAMESPACE::constants::sixth()*y*y*y; } return static_cast(0); } @@ -72,11 +74,11 @@ Real b3_spline_prime(Real x) if (x < 1) { - return x*(3*boost::math::constants::half()*x - 2); + return x*(3*BOOST_MATH_NAMESPACE::constants::half()*x - 2); } if (x < 2) { - return -boost::math::constants::half()*(2 - x)*(2 - x); + return -BOOST_MATH_NAMESPACE::constants::half()*(2 - x)*(2 - x); } return static_cast(0); } @@ -106,13 +108,13 @@ template cubic_b_spline_imp::cubic_b_spline_imp(BidiIterator f, BidiIterator end_p, Real left_endpoint, Real step_size, Real left_endpoint_derivative, Real right_endpoint_derivative) : m_a(left_endpoint), m_avg(0) { - using boost::math::constants::third; + using BOOST_MATH_NAMESPACE::constants::third; std::size_t length = end_p - f; if (length < 5) { - if (boost::math::isnan(left_endpoint_derivative) || boost::math::isnan(right_endpoint_derivative)) + if (BOOST_MATH_NAMESPACE::isnan(left_endpoint_derivative) || BOOST_MATH_NAMESPACE::isnan(right_endpoint_derivative)) { throw std::logic_error("Interpolation using a cubic b spline with derivatives estimated at the endpoints requires at least 5 points.\n"); } @@ -122,7 +124,7 @@ cubic_b_spline_imp::cubic_b_spline_imp(BidiIterator f, BidiIterator end_p, } } - if (boost::math::isnan(left_endpoint)) + if (BOOST_MATH_NAMESPACE::isnan(left_endpoint)) { throw std::logic_error("Left endpoint is NAN; this is disallowed.\n"); } @@ -144,7 +146,7 @@ cubic_b_spline_imp::cubic_b_spline_imp(BidiIterator f, BidiIterator end_p, // to construct high-order estimates for one-sided derivatives: // https://en.wikipedia.org/wiki/Finite_difference_coefficient#Forward_and_backward_finite_difference // Here, we estimate then to O(h^4), as that is the maximum accuracy we could obtain from this method. - if (boost::math::isnan(a1)) + if (BOOST_MATH_NAMESPACE::isnan(a1)) { // For simple functions (linear, quadratic, so on) // almost all the error comes from derivative estimation. @@ -155,7 +157,7 @@ cubic_b_spline_imp::cubic_b_spline_imp(BidiIterator f, BidiIterator end_p, } Real b1 = right_endpoint_derivative; - if (boost::math::isnan(b1)) + if (BOOST_MATH_NAMESPACE::isnan(b1)) { size_t n = length - 1; Real t0 = 4*(f[n-3] + third()*f[n - 1]); @@ -177,7 +179,7 @@ cubic_b_spline_imp::cubic_b_spline_imp(BidiIterator f, BidiIterator end_p, Real t = 1; for (size_t i = 0; i < length; ++i) { - if (boost::math::isnan(f[i])) + if (BOOST_MATH_NAMESPACE::isnan(f[i])) { std::string err = "This function you are trying to interpolate is a nan at index " + std::to_string(i) + "\n"; throw std::logic_error(err); @@ -273,8 +275,8 @@ Real cubic_b_spline_imp::operator()(Real x) const using std::ceil; using std::floor; - size_t k_min = static_cast((max)(static_cast(0), boost::math::ltrunc(ceil(t - 2)))); - size_t k_max = static_cast((max)((min)(static_cast(m_beta.size() - 1), boost::math::ltrunc(floor(t + 2))), 0l)); + size_t k_min = static_cast((max)(static_cast(0), BOOST_MATH_NAMESPACE::ltrunc(ceil(t - 2)))); + size_t k_max = static_cast((max)((min)(static_cast(m_beta.size() - 1), BOOST_MATH_NAMESPACE::ltrunc(floor(t + 2))), 0l)); for (size_t k = k_min; k <= k_max; ++k) { z += m_beta[k]*b3_spline(t - k); @@ -294,8 +296,8 @@ Real cubic_b_spline_imp::prime(Real x) const using std::ceil; using std::floor; - size_t k_min = static_cast((max)(static_cast(0), boost::math::ltrunc(ceil(t - 2)))); - size_t k_max = static_cast((min)(static_cast(m_beta.size() - 1), boost::math::ltrunc(floor(t + 2)))); + size_t k_min = static_cast((max)(static_cast(0), BOOST_MATH_NAMESPACE::ltrunc(ceil(t - 2)))); + size_t k_max = static_cast((min)(static_cast(m_beta.size() - 1), BOOST_MATH_NAMESPACE::ltrunc(floor(t + 2)))); for (size_t k = k_min; k <= k_max; ++k) { @@ -315,8 +317,8 @@ Real cubic_b_spline_imp::double_prime(Real x) const using std::ceil; using std::floor; - size_t k_min = static_cast((max)(static_cast(0), boost::math::ltrunc(ceil(t - 2)))); - size_t k_max = static_cast((min)(static_cast(m_beta.size() - 1), boost::math::ltrunc(floor(t + 2)))); + size_t k_min = static_cast((max)(static_cast(0), BOOST_MATH_NAMESPACE::ltrunc(ceil(t - 2)))); + size_t k_max = static_cast((min)(static_cast(m_beta.size() - 1), BOOST_MATH_NAMESPACE::ltrunc(floor(t + 2)))); for (size_t k = k_min; k <= k_max; ++k) { @@ -326,5 +328,5 @@ Real cubic_b_spline_imp::double_prime(Real x) const } -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/cubic_hermite_detail.hpp b/include/boost/math/interpolators/detail/cubic_hermite_detail.hpp index 0e04d37390..f2ce9d03e1 100644 --- a/include/boost/math/interpolators/detail/cubic_hermite_detail.hpp +++ b/include/boost/math/interpolators/detail/cubic_hermite_detail.hpp @@ -6,6 +6,7 @@ #ifndef BOOST_MATH_INTERPOLATORS_DETAIL_CUBIC_HERMITE_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_DETAIL_CUBIC_HERMITE_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -13,13 +14,15 @@ #include #include #include +#endif + +#include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { namespace detail { -template +template> class cubic_hermite_detail { public: using Real = typename RandomAccessContainer::value_type; @@ -28,19 +31,29 @@ class cubic_hermite_detail { cubic_hermite_detail(RandomAccessContainer && x, RandomAccessContainer && y, RandomAccessContainer dydx) : x_{std::move(x)}, y_{std::move(y)}, dydx_{std::move(dydx)} { + static const char* function = "boost::math::interpolators::detail::cubic_hermite_detail::cubic_hermite_detail"; using std::abs; using std::isnan; if (x_.size() != y_.size()) { - throw std::domain_error("There must be the same number of ordinates as abscissas."); + error_msg_ = "There must be the same number of ordinates as abscissas."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } if (x_.size() != dydx_.size()) { - throw std::domain_error("There must be the same number of ordinates as derivative values."); + error_msg_ = "There must be the same number of ordinates as derivative values."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } if (x_.size() < 2) { - throw std::domain_error("Must be at least two data points."); + error_msg_ = "Must be at least two data points."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } Real x0 = x_[0]; for (size_t i = 1; i < x_.size(); ++i) @@ -52,19 +65,27 @@ class cubic_hermite_detail { oss.precision(std::numeric_limits::digits10+3); oss << "Abscissas must be listed in strictly increasing order x0 < x1 < ... < x_{n-1}, "; oss << "but at x[" << i - 1 << "] = " << x0 << ", and x[" << i << "] = " << x1 << ".\n"; - throw std::domain_error(oss.str()); + error_msg_ = oss.str(); + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } x0 = x1; } + valid_ = true; } void push_back(Real x, Real y, Real dydx) { + if ( ! valid_) return; // We do not realize if the object is constructed correctly here. + + static const char* function = "boost::math::interpolators::detail::cubic_hermite_detail::push_back"; using std::abs; using std::isnan; if (x <= x_.back()) { - throw std::domain_error("Calling push_back must preserve the monotonicity of the x's"); + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Calling push_back must preserve the monotonicity of the x's", false, Policy()); + return; } x_.push_back(x); y_.push_back(y); @@ -73,13 +94,16 @@ class cubic_hermite_detail { Real operator()(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); + + static const char* function = "boost::math::interpolators::detail::cubic_hermite_detail::operator()"; if (x < x_[0] || x > x_.back()) { std::ostringstream oss; oss.precision(std::numeric_limits::digits10+3); oss << "Requested abscissa x = " << x << ", which is outside of allowed range [" << x_[0] << ", " << x_.back() << "]"; - throw std::domain_error(oss.str()); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, oss.str().c_str(), x, Policy()); } // We need t := (x-x_k)/(x_{k+1}-x_k) \in [0,1) for this to work. // Sadly this neccessitates this loathesome check, otherwise we get t = 1 at x = xf. @@ -108,13 +132,16 @@ class cubic_hermite_detail { Real prime(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); + + static const char* function = "boost::math::interpolators::detail::cubic_hermite_detail::prime"; if (x < x_[0] || x > x_.back()) { std::ostringstream oss; oss.precision(std::numeric_limits::digits10+3); oss << "Requested abscissa x = " << x << ", which is outside of allowed range [" << x_[0] << ", " << x_.back() << "]"; - throw std::domain_error(oss.str()); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, oss.str().c_str(), x, Policy()); } if (x == x_.back()) { @@ -137,9 +164,10 @@ class cubic_hermite_detail { return s0 + 2*c2*(x-x0) + 3*c3*(x-x0)*(x-x0); } - friend std::ostream& operator<<(std::ostream & os, const cubic_hermite_detail & m) { + if ( ! m.valid_) return os; + os << "(x,y,y') = {"; for (size_t i = 0; i < m.x_.size() - 1; ++i) { @@ -152,25 +180,39 @@ class cubic_hermite_detail { Size size() const { + if ( ! valid_) return 0; return x_.size(); } std::int64_t bytes() const { + if ( ! valid_) return 0; return 3*x_.size()*sizeof(Real) + 3*sizeof(x_); } std::pair domain() const { + if ( ! valid_) return {0, 0}; return {x_.front(), x_.back()}; } + bool valid() const { + return valid_; + } + + std::string const& error_msg() const { + return error_msg_; + } + RandomAccessContainer x_; RandomAccessContainer y_; RandomAccessContainer dydx_; +private: + bool valid_ = false; + std::string error_msg_; }; -template +template> class cardinal_cubic_hermite_detail { public: using Real = typename RandomAccessContainer::value_type; @@ -179,25 +221,36 @@ class cardinal_cubic_hermite_detail { cardinal_cubic_hermite_detail(RandomAccessContainer && y, RandomAccessContainer dydx, Real x0, Real dx) : y_{std::move(y)}, dy_{std::move(dydx)}, x0_{x0}, inv_dx_{1/dx} { + static const char* function = "boost::math::interpolators::detail::cardinal_cubic_hermite_detail::cardinal_cubic_hermite_detail"; using std::abs; using std::isnan; if (y_.size() != dy_.size()) { - throw std::domain_error("There must be the same number of derivatives as ordinates."); + error_msg_ = "There must be the same number of derivatives as ordinates."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } if (y_.size() < 2) { - throw std::domain_error("Must be at least two data points."); + error_msg_ = "Must be at least two data points."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } if (dx <= 0) { - throw std::domain_error("dx > 0 is required."); + error_msg_ = "dx > 0 is required."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } for (auto & dy : dy_) { dy *= dx; } + valid_ = true; } // Why not implement push_back? It's awkward: If the buffer is circular, x0_ += dx_. @@ -206,6 +259,9 @@ class cardinal_cubic_hermite_detail { inline Real operator()(Real x) const { + static const char* function = "boost::math::interpolators::detail::cardinal_cubic_hermite_detail::operator()"; + if ( ! valid_) return std::numeric_limits::quiet_NaN(); + const Real xf = x0_ + (y_.size()-1)/inv_dx_; if (x < x0_ || x > xf) { @@ -213,7 +269,7 @@ class cardinal_cubic_hermite_detail { oss.precision(std::numeric_limits::digits10+3); oss << "Requested abscissa x = " << x << ", which is outside of allowed range [" << x0_ << ", " << xf << "]"; - throw std::domain_error(oss.str()); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, oss.str().c_str(), x, Policy()); } if (x == xf) { @@ -224,6 +280,7 @@ class cardinal_cubic_hermite_detail { inline Real unchecked_evaluation(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); using std::floor; Real s = (x-x0_)*inv_dx_; Real ii = floor(s); @@ -241,6 +298,8 @@ class cardinal_cubic_hermite_detail { inline Real prime(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); + static const char* function = "boost::math::interpolators::detail::cardinal_cubic_hermite_detail::prime"; const Real xf = x0_ + (y_.size()-1)/inv_dx_; if (x < x0_ || x > xf) { @@ -248,7 +307,7 @@ class cardinal_cubic_hermite_detail { oss.precision(std::numeric_limits::digits10+3); oss << "Requested abscissa x = " << x << ", which is outside of allowed range [" << x0_ << ", " << xf << "]"; - throw std::domain_error(oss.str()); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, oss.str().c_str(), x, Policy()); } if (x == xf) { @@ -259,6 +318,8 @@ class cardinal_cubic_hermite_detail { inline Real unchecked_prime(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); + using std::floor; Real s = (x-x0_)*inv_dx_; Real ii = floor(s); @@ -273,33 +334,44 @@ class cardinal_cubic_hermite_detail { return dy*inv_dx_; } - Size size() const { + if ( ! valid_) return 0; return y_.size(); } std::int64_t bytes() const { + if ( ! valid_) return 0; return 2*y_.size()*sizeof(Real) + 2*sizeof(y_) + 2*sizeof(Real); } std::pair domain() const { + if ( ! valid_) return {0, 0}; Real xf = x0_ + (y_.size()-1)/inv_dx_; return {x0_, xf}; } -private: + bool valid() const { + return valid_; + } + std::string const& error_msg() const { + return error_msg_; + } +private: RandomAccessContainer y_; RandomAccessContainer dy_; Real x0_; Real inv_dx_; + + bool valid_ = false; + std::string error_msg_; }; -template +template> class cardinal_cubic_hermite_detail_aos { public: using Point = typename RandomAccessContainer::value_type; @@ -307,29 +379,43 @@ class cardinal_cubic_hermite_detail_aos { using Size = typename RandomAccessContainer::size_type; cardinal_cubic_hermite_detail_aos(RandomAccessContainer && dat, Real x0, Real dx) - : dat_{std::move(dat)}, x0_{x0}, inv_dx_{1/dx} + : dat_{std::move(dat)}, x0_{x0}, inv_dx_{1/dx} { + static const char* function = "boost::math::interpolators::detail::cardinal_cubic_hermite_detail_aos::cardinal_cubic_hermite_detail_aos"; if (dat_.size() < 2) { - throw std::domain_error("Must be at least two data points."); + error_msg_ = "Must be at least two data points."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } if (dat_[0].size() != 2) { - throw std::domain_error("Each datum must contain (y, y'), and nothing else."); + error_msg_ = "Each datum must contain (y, y'), and nothing else."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } if (dx <= 0) { - throw std::domain_error("dx > 0 is required."); + error_msg_ = "dx > 0 is required."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } for (auto & d : dat_) { d[1] *= dx; } + valid_ = true; } inline Real operator()(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); + + static const char* function = "boost::math::interpolators::detail::cardinal_cubic_hermite_detail_aos::operator()"; const Real xf = x0_ + (dat_.size()-1)/inv_dx_; if (x < x0_ || x > xf) { @@ -337,7 +423,7 @@ class cardinal_cubic_hermite_detail_aos { oss.precision(std::numeric_limits::digits10+3); oss << "Requested abscissa x = " << x << ", which is outside of allowed range [" << x0_ << ", " << xf << "]"; - throw std::domain_error(oss.str()); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, oss.str().c_str(), x, Policy()); } if (x == xf) { @@ -348,6 +434,8 @@ class cardinal_cubic_hermite_detail_aos { inline Real unchecked_evaluation(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); + using std::floor; Real s = (x-x0_)*inv_dx_; Real ii = floor(s); @@ -372,6 +460,9 @@ class cardinal_cubic_hermite_detail_aos { inline Real prime(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); + + static const char* function = "boost::math::interpolators::detail::cardinal_cubic_hermite_detail_aos::prime"; const Real xf = x0_ + (dat_.size()-1)/inv_dx_; if (x < x0_ || x > xf) { @@ -379,7 +470,7 @@ class cardinal_cubic_hermite_detail_aos { oss.precision(std::numeric_limits::digits10+3); oss << "Requested abscissa x = " << x << ", which is outside of allowed range [" << x0_ << ", " << xf << "]"; - throw std::domain_error(oss.str()); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, oss.str().c_str(), x, Policy()); } if (x == xf) { @@ -390,6 +481,8 @@ class cardinal_cubic_hermite_detail_aos { inline Real unchecked_prime(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); + using std::floor; Real s = (x-x0_)*inv_dx_; Real ii = floor(s); @@ -408,32 +501,44 @@ class cardinal_cubic_hermite_detail_aos { return dy*inv_dx_; } - Size size() const { + if ( ! valid_) return 0; return dat_.size(); } std::int64_t bytes() const { + if ( ! valid_) return 0; return dat_.size()*dat_[0].size()*sizeof(Real) + sizeof(dat_) + 2*sizeof(Real); } std::pair domain() const { + if ( ! valid_) return {0, 0}; Real xf = x0_ + (dat_.size()-1)/inv_dx_; return {x0_, xf}; } + bool valid() const { + return valid_; + } + + std::string const& error_msg() const { + return error_msg_; + } private: RandomAccessContainer dat_; Real x0_; Real inv_dx_; + + bool valid_ = false; + std::string error_msg_; }; } } -} -} +BOOST_MATH_NAMESPACE_END #endif + diff --git a/include/boost/math/interpolators/detail/quintic_hermite_detail.hpp b/include/boost/math/interpolators/detail/quintic_hermite_detail.hpp index ad7eee13a1..efe1ae3eb7 100644 --- a/include/boost/math/interpolators/detail/quintic_hermite_detail.hpp +++ b/include/boost/math/interpolators/detail/quintic_hermite_detail.hpp @@ -6,15 +6,18 @@ */ #ifndef BOOST_MATH_INTERPOLATORS_DETAIL_QUINTIC_HERMITE_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_DETAIL_QUINTIC_HERMITE_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include +#endif + +#include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { namespace detail { @@ -137,11 +140,17 @@ class quintic_hermite_detail { Real a0 = d2ydx2_[i]; Real a1 = d2ydx2_[i+1]; Real t= (x-x0)/dx; - Real t2 = t*t; - Real dydx = 30*t2*(1 - 2*t + t*t)*(y1-y0)/dx; - dydx += (1-18*t*t + 32*t*t*t - 15*t*t*t*t)*v0 - t*t*(12 - 28*t + 15*t*t)*v1; - dydx += (t*dx/2)*((2 - 9*t + 12*t*t - 5*t*t*t)*a0 + t*(3 - 8*t + 5*t*t)*a1); + // The basis polynomials factored at their zeros, with u = 1 - t (exact for t >= 1/2), as in septic_hermite: + Real u = 1 - t; + Real z0 = 30*t*t*u*u; + Real z1 = u*u*(1 + t*(2 - 15*t)); + Real z2 = t*t*(1 + u*(2 - 15*u)); + // z0 m + z1 v0 + z2 v1 (m the secant slope) cancels; with z0 + z1 + z2 = 1 it is anchored at the + // nearer endpoint's derivative instead, as in septic_hermite: + Real m = (y1-y0)/dx; + Real dydx = t < Real(0.5) ? Real(v0 + (z0*(m - v0) + z2*(v1 - v0))) : Real(v1 + (z0*(m - v1) + z1*(v0 - v1))); + dydx += (t*dx/2)*(u*u*(2 - 5*t)*a0 + t*u*(3 - 5*t)*a1); return dydx; } @@ -331,9 +340,16 @@ class cardinal_quintic_hermite_detail { Real d2y0 = d2y_[i]; Real d2y1 = d2y_[i+1]; - Real dydx = 30*t*t*(1 - 2*t + t*t)*(y1-y0); - dydx += (1-18*t*t + 32*t*t*t - 15*t*t*t*t)*dy0 - t*t*(12 - 28*t + 15*t*t)*dy1; - dydx += t*((2 - 9*t + 12*t*t - 5*t*t*t)*d2y0 + t*(3 - 8*t + 5*t*t)*d2y1); + // The basis polynomials factored at their zeros, with u = 1 - t (exact for t >= 1/2), as in septic_hermite: + Real u = 1 - t; + Real z0 = 30*t*t*u*u; + Real z1 = u*u*(1 + t*(2 - 15*t)); + Real z2 = t*t*(1 + u*(2 - 15*u)); + // z0 m + z1 v0 + z2 v1 (m the secant slope) cancels; with z0 + z1 + z2 = 1 it is anchored at the + // nearer endpoint's derivative instead, as in septic_hermite: + Real m = y1 - y0; + Real dydx = t < Real(0.5) ? Real(dy0 + (z0*(m - dy0) + z2*(dy1 - dy0))) : Real(dy1 + (z0*(m - dy1) + z1*(dy0 - dy1))); + dydx += t*(u*u*(2 - 5*t)*d2y0 + t*u*(3 - 5*t)*d2y1); dydx *= inv_dx_; return dydx; } @@ -376,7 +392,7 @@ class cardinal_quintic_hermite_detail { Real d2y1 = d2y_[i+1]; Real d2ydx2 = 60*t*(1 - 3*t + 2*t*t)*(y1 - y0)*inv_dx_*inv_dx_; - d2ydx2 += (12*t)*((-3 + 8*t - 5*t*t)*dy0 - (2 - 7*t + 5*t*t)*dy1); + d2ydx2 += (12*t)*((-3 + 8*t - 5*t*t)*dy0 - (2 - 7*t + 5*t*t)*dy1)*inv_dx_*inv_dx_; d2ydx2 += (1 - 9*t + 18*t*t - 10*t*t*t)*d2y0*(2*inv_dx_*inv_dx_) + t*(3 - 12*t + 10*t*t)*d2y1*(2*inv_dx_*inv_dx_); return d2ydx2; } @@ -514,9 +530,16 @@ class cardinal_quintic_hermite_detail_aos { Real a0 = data_[i][2]; Real a1 = data_[i+1][2]; - Real dy = 30*t*t*(1 - 2*t + t*t)*(y1-y0); - dy += (1-18*t*t + 32*t*t*t - 15*t*t*t*t)*v0 - t*t*(12 - 28*t + 15*t*t)*v1; - dy += t*((2 - 9*t + 12*t*t - 5*t*t*t)*a0 + t*(3 - 8*t + 5*t*t)*a1); + // The basis polynomials factored at their zeros, with u = 1 - t (exact for t >= 1/2), as in septic_hermite: + Real u = 1 - t; + Real z0 = 30*t*t*u*u; + Real z1 = u*u*(1 + t*(2 - 15*t)); + Real z2 = t*t*(1 + u*(2 - 15*u)); + // z0 m + z1 v0 + z2 v1 (m the secant slope) cancels; with z0 + z1 + z2 = 1 it is anchored at the + // nearer endpoint's derivative instead, as in septic_hermite: + Real m = y1 - y0; + Real dy = t < Real(0.5) ? Real(v0 + (z0*(m - v0) + z2*(v1 - v0))) : Real(v1 + (z0*(m - v1) + z1*(v0 - v1))); + dy += t*(u*u*(2 - 5*t)*a0 + t*u*(3 - 5*t)*a1); return dy*inv_dx_; } @@ -557,7 +580,7 @@ class cardinal_quintic_hermite_detail_aos { Real d2y1 = data_[i+1][2]; Real d2ydx2 = 60*t*(1 - 3*t + 2*t*t)*(y1 - y0)*inv_dx_*inv_dx_; - d2ydx2 += (12*t)*((-3 + 8*t - 5*t*t)*dy0 - (2 - 7*t + 5*t*t)*dy1); + d2ydx2 += (12*t)*((-3 + 8*t - 5*t*t)*dy0 - (2 - 7*t + 5*t*t)*dy1)*inv_dx_*inv_dx_; d2ydx2 += (1 - 9*t + 18*t*t - 10*t*t*t)*d2y0*(2*inv_dx_*inv_dx_) + t*(3 - 12*t + 10*t*t)*d2y1*(2*inv_dx_*inv_dx_); return d2ydx2; } @@ -581,6 +604,5 @@ class cardinal_quintic_hermite_detail_aos { } } -} -} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/septic_hermite_detail.hpp b/include/boost/math/interpolators/detail/septic_hermite_detail.hpp index f4677ce0b6..c0d866aa8e 100644 --- a/include/boost/math/interpolators/detail/septic_hermite_detail.hpp +++ b/include/boost/math/interpolators/detail/septic_hermite_detail.hpp @@ -6,15 +6,18 @@ */ #ifndef BOOST_MATH_INTERPOLATORS_DETAIL_SEPTIC_HERMITE_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_DETAIL_SEPTIC_HERMITE_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include +#endif + +#include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { namespace detail { @@ -159,16 +162,24 @@ class septic_hermite_detail { Real t = (x-x0)/dx; Real t2 = t*t; Real t3 = t2*t; - Real z0 = 140*t3*(1 + t*(-3 + t*(3 - t))); - Real z1 = 1 + t3*(-80 + t*(225 + t*(-216 + 70*t))); - Real z2 = t3*(-60 + t*(195 + t*(-204 + 70*t))); - Real z3 = 1 + t2*(-20 + t*(50 + t*(-45 + 14*t))); - Real z4 = t2*(10 + t*(-35 + t*(39 - 14*t))); - Real z5 = 3 + t*(-16 + t*(30 + t*(-24 + 7*t))); - Real z6 = t*(-4 + t*(15 + t*(-18 + 7*t))); - - Real dydx = z0*(y1-y0)/dx; - dydx += z1*v0 + z2*v1; + // The basis polynomials factored at their zeros, with u = 1 - t (exact for t >= 1/2): expanded, + // they lose up to ~60 eps to cancellation near their zeros. + Real u = 1 - t; + Real u2 = u*u; + Real u3 = u2*u; + Real z1 = u3*(1 + t*(3 + t*(6 - 70*t))); + Real z2 = t3*(1 + u*(3 + u*(6 - 70*u))); + Real z3 = u3*(1 + t*(3 - 14*t)); + Real z4 = t2*u*(10 + t*(-25 + 14*t)); + Real z5 = u3*(3 - 7*t); + Real z6 = t*u2*(-4 + 7*t); + + // z0 m + z1 v0 + z2 v1, with m the secant slope, has terms ~10x the result that cancel. Since + // z0 + z1 + z2 = 1 (lines are reproduced), it is v0 + z0 (m - v0) + z2 (v1 - v0), whose terms + // vanish at t = 0, or, nearer t = 1, the same anchored at v1: + Real m = (y1-y0)/dx; + Real z0 = 140*t3*u3; + Real dydx = t < Real(0.5) ? Real(v0 + (z0*(m - v0) + z2*(v1 - v0))) : Real(v1 + (z0*(m - v1) + z1*(v0 - v1))); dydx += (x-x0)*(z3*a0 + z4*a1); dydx += (x-x0)*(x-x0)*(z5*j0 + z6*j1)/6; return dydx; @@ -320,7 +331,7 @@ class cardinal_septic_hermite_detail { } if (x == xf) { - return dy_.back()/inv_dx_; + return dy_.back()*inv_dx_; } return this->unchecked_prime(x); @@ -335,7 +346,7 @@ class cardinal_septic_hermite_detail { Real t = s3 - ii; if (t==0) { - return dy_[i]/inv_dx_; + return dy_[i]*inv_dx_; } Real y0 = y_[i]; @@ -348,18 +359,24 @@ class cardinal_septic_hermite_detail { Real j1 = d3y_[i+1]; Real t2 = t*t; Real t3 = t2*t; - Real z0 = 140*t3*(1 + t*(-3 + t*(3 - t))); - Real z1 = 1 + t3*(-80 + t*(225 + t*(-216 + 70*t))); - Real z2 = t3*(-60 + t*(195 + t*(-204 + 70*t))); - Real z3 = 1 + t2*(-20 + t*(50 + t*(-45 + 14*t))); - Real z4 = t2*(10 + t*(-35 + t*(39 - 14*t))); - Real z5 = 3 + t*(-16 + t*(30 + t*(-24 + 7*t))); - Real z6 = t*(-4 + t*(15 + t*(-18 + 7*t))); - - Real dydx = z0*(y1-y0)*inv_dx_; - dydx += (z1*dy0 + z2*dy1)*inv_dx_; + // The basis polynomials factored at their zeros, with u = 1 - t (exact for t >= 1/2): expanded, + // they lose up to ~60 eps to cancellation near their zeros. + Real u = 1 - t; + Real u2 = u*u; + Real u3 = u2*u; + Real z1 = u3*(1 + t*(3 + t*(6 - 70*t))); + Real z2 = t3*(1 + u*(3 + u*(6 - 70*u))); + Real z3 = u3*(1 + t*(3 - 14*t)); + Real z4 = t2*u*(10 + t*(-25 + 14*t)); + Real z5 = u3*(3 - 7*t); + Real z6 = t*u2*(-4 + 7*t); + + // As in septic_hermite_detail::prime, with the slope y1 - y0 in units of dx: + Real m = y1 - y0; + Real z0 = 140*t3*u3; + Real dydx = (t < Real(0.5) ? Real(dy0 + (z0*(m - dy0) + z2*(dy1 - dy0))) : Real(dy1 + (z0*(m - dy1) + z1*(dy0 - dy1))))*inv_dx_; dydx += 2*t*(z3*a0 + z4*a1)*inv_dx_; - dydx += t*t*(z5*j0 + z6*j1); + dydx += t*t*(z5*j0 + z6*j1)*inv_dx_; return dydx; } @@ -415,7 +432,7 @@ class cardinal_septic_hermite_detail { Real d2ydx2 = z0*(y1-y0)*inv_dx_*inv_dx_; d2ydx2 += (z1*dy0 + z2*dy1)*inv_dx_*inv_dx_; d2ydx2 += (z3*a0 + z4*a1)*2*inv_dx_*inv_dx_; - d2ydx2 += 6*(z5*j0 + z6*j1)/(inv_dx_*inv_dx_); + d2ydx2 += 6*(z5*j0 + z6*j1)*inv_dx_*inv_dx_; return d2ydx2; } @@ -559,18 +576,24 @@ class cardinal_septic_hermite_detail_aos { Real j1 = data_[i+1][3]; Real t2 = t*t; Real t3 = t2*t; - Real z0 = 140*t3*(1 + t*(-3 + t*(3 - t))); - Real z1 = 1 + t3*(-80 + t*(225 + t*(-216 + 70*t))); - Real z2 = t3*(-60 + t*(195 + t*(-204 + 70*t))); - Real z3 = 1 + t2*(-20 + t*(50 + t*(-45 + 14*t))); - Real z4 = t2*(10 + t*(-35 + t*(39 - 14*t))); - Real z5 = 3 + t*(-16 + t*(30 + t*(-24 + 7*t))); - Real z6 = t*(-4 + t*(15 + t*(-18 + 7*t))); - - Real dydx = z0*(y1-y0)*inv_dx_; - dydx += (z1*dy0 + z2*dy1)*inv_dx_; + // The basis polynomials factored at their zeros, with u = 1 - t (exact for t >= 1/2): expanded, + // they lose up to ~60 eps to cancellation near their zeros. + Real u = 1 - t; + Real u2 = u*u; + Real u3 = u2*u; + Real z1 = u3*(1 + t*(3 + t*(6 - 70*t))); + Real z2 = t3*(1 + u*(3 + u*(6 - 70*u))); + Real z3 = u3*(1 + t*(3 - 14*t)); + Real z4 = t2*u*(10 + t*(-25 + 14*t)); + Real z5 = u3*(3 - 7*t); + Real z6 = t*u2*(-4 + 7*t); + + // As in septic_hermite_detail::prime, with the slope y1 - y0 in units of dx: + Real m = y1 - y0; + Real z0 = 140*t3*u3; + Real dydx = (t < Real(0.5) ? Real(dy0 + (z0*(m - dy0) + z2*(dy1 - dy0))) : Real(dy1 + (z0*(m - dy1) + z1*(dy0 - dy1))))*inv_dx_; dydx += 2*t*(z3*a0 + z4*a1)*inv_dx_; - dydx += t*t*(z5*j0 + z6*j1); + dydx += t*t*(z5*j0 + z6*j1)*inv_dx_; return dydx; } @@ -625,7 +648,7 @@ class cardinal_septic_hermite_detail_aos { Real d2ydx2 = z0*(y1-y0)*inv_dx_*inv_dx_; d2ydx2 += (z1*dy0 + z2*dy1)*inv_dx_*inv_dx_; d2ydx2 += (z3*a0 + z4*a1)*2*inv_dx_*inv_dx_; - d2ydx2 += 6*(z5*j0 + z6*j1)/(inv_dx_*inv_dx_); + d2ydx2 += 6*(z5*j0 + z6*j1)*inv_dx_*inv_dx_; return d2ydx2; } @@ -648,6 +671,5 @@ class cardinal_septic_hermite_detail_aos { } } -} -} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/vector_barycentric_rational_detail.hpp b/include/boost/math/interpolators/detail/vector_barycentric_rational_detail.hpp index fdece724c1..bff030c7ac 100644 --- a/include/boost/math/interpolators/detail/vector_barycentric_rational_detail.hpp +++ b/include/boost/math/interpolators/detail/vector_barycentric_rational_detail.hpp @@ -8,15 +8,17 @@ #ifndef BOOST_MATH_INTERPOLATORS_VECTOR_BARYCENTRIC_RATIONAL_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_VECTOR_BARYCENTRIC_RATIONAL_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include // for std::move #include #include +#endif #include -namespace boost{ namespace math{ namespace interpolators{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators{ namespace detail{ template class vector_barycentric_rational_imp @@ -63,7 +65,6 @@ vector_barycentric_rational_imp::vector_barycentr template void vector_barycentric_rational_imp::calculate_weights(size_t approximation_order) { - using Real = typename TimeContainer::value_type; using std::abs; std::int64_t n = t_.size(); w_.resize(n, Real(0)); @@ -105,7 +106,6 @@ void vector_barycentric_rational_imp::calculate_w template void vector_barycentric_rational_imp::operator()(typename SpaceContainer::value_type& p, typename TimeContainer::value_type t) const { - using Real = typename TimeContainer::value_type; for (auto & x : p) { x = Real(0); @@ -136,8 +136,6 @@ void vector_barycentric_rational_imp::operator()( template void vector_barycentric_rational_imp::eval_with_prime(typename SpaceContainer::value_type& x, typename SpaceContainer::value_type& dxdt, typename TimeContainer::value_type t) const { - using Point = typename SpaceContainer::value_type; - using Real = typename TimeContainer::value_type; this->operator()(x, t); Point numerator; for (decltype(x.size()) i = 0; i < x.size(); ++i) @@ -150,9 +148,9 @@ void vector_barycentric_rational_imp::eval_with_p if (t == t_[i]) { Point sum; - for (decltype(x.size()) i = 0; i < x.size(); ++i) + for (decltype(x.size()) m = 0; m < x.size(); ++m) { - sum[i] = 0; + sum[m] = 0; } for (decltype(t_.size()) j = 0; j < t_.size(); ++j) @@ -192,5 +190,5 @@ void vector_barycentric_rational_imp::eval_with_p return; } -}}}} +}} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/detail/whittaker_shannon_detail.hpp b/include/boost/math/interpolators/detail/whittaker_shannon_detail.hpp index 74ff47c463..12647a4ef9 100644 --- a/include/boost/math/interpolators/detail/whittaker_shannon_detail.hpp +++ b/include/boost/math/interpolators/detail/whittaker_shannon_detail.hpp @@ -5,13 +5,15 @@ // or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_INTERPOLATORS_WHITAKKER_SHANNON_DETAIL_HPP #define BOOST_MATH_INTERPOLATORS_WHITAKKER_SHANNON_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include #include -namespace boost { namespace math { namespace interpolators { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { namespace detail { template class whittaker_shannon_detail { @@ -27,7 +29,7 @@ class whittaker_shannon_detail { } inline Real operator()(Real t) const { - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; using std::isfinite; using std::floor; using std::ceil; @@ -55,11 +57,11 @@ class whittaker_shannon_detail { } return m_y[i]; } - return y*boost::math::sin_pi(x)/pi(); + return y*BOOST_MATH_NAMESPACE::sin_pi(x)/pi(); } Real prime(Real t) const { - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; using std::isfinite; using std::floor; using std::ceil; @@ -86,8 +88,8 @@ class whittaker_shannon_detail { } Real z = x; auto it = m_y.begin(); - Real cospix = boost::math::cos_pi(x); - Real sinpix_div_pi = boost::math::sin_pi(x)/pi(); + Real cospix = BOOST_MATH_NAMESPACE::cos_pi(x); + Real sinpix_div_pi = BOOST_MATH_NAMESPACE::sin_pi(x)/pi(); Real s = 0; auto end = m_y.end(); @@ -124,5 +126,5 @@ class whittaker_shannon_detail { Real m_t0; Real m_h; }; -}}}} +}} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/makima.hpp b/include/boost/math/interpolators/makima.hpp index f69fe40733..c8729c507b 100644 --- a/include/boost/math/interpolators/makima.hpp +++ b/include/boost/math/interpolators/makima.hpp @@ -9,15 +9,18 @@ #ifndef BOOST_MATH_INTERPOLATORS_MAKIMA_HPP #define BOOST_MATH_INTERPOLATORS_MAKIMA_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template> class makima { public: using Real = typename RandomAccessContainer::value_type; @@ -26,11 +29,15 @@ class makima { Real left_endpoint_derivative = std::numeric_limits::quiet_NaN(), Real right_endpoint_derivative = std::numeric_limits::quiet_NaN()) { + static const char* function = "boost::math::interpolators::makima::makima"; using std::isnan; using std::abs; if (x.size() < 4) { - throw std::domain_error("Must be at least four data points."); + error_msg_ = "Must be at least four data points."; + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, error_msg_.c_str(), false, Policy()); + valid_ = false; + return; } RandomAccessContainer s(x.size(), std::numeric_limits::quiet_NaN()); Real m2 = (y[3]-y[2])/(x[3]-x[2]); @@ -54,14 +61,12 @@ class makima { { s[0] = left_endpoint_derivative; } - w1 = abs(m2-m1) + abs(m2+m1)/2; w2 = abs(m0-mm1) + abs(m0+mm1)/2; s[1] = (w1*m0 + w2*m1)/(w1+w2); if (isnan(s[1])) { s[1] = 0; } - for (decltype(s.size()) i = 2; i < s.size()-2; ++i) { Real mim2 = (y[i-1]-y[i-2])/(x[i-1]-x[i-2]); Real mim1 = (y[i ]-y[i-1])/(x[i ]-x[i-1]); @@ -84,16 +89,12 @@ class makima { Real mn = 2*mnm1 - mnm2; w1 = abs(mnm1 - mnm2) + abs(mnm1+mnm2)/2; w2 = abs(mnm3 - mnm4) + abs(mnm3+mnm4)/2; - s[n-2] = (w1*mnm3 + w2*mnm2)/(w1 + w2); if (isnan(s[n-2])) { s[n-2] = 0; } - w1 = abs(mn - mnm1) + abs(mn+mnm1)/2; w2 = abs(mnm2 - mnm3) + abs(mnm2+mnm3)/2; - - if (isnan(right_endpoint_derivative)) { s[n-1] = (w1*mnm2 + w2*mnm1)/(w1+w2); @@ -106,28 +107,38 @@ class makima { s[n-1] = right_endpoint_derivative; } - impl_ = std::make_shared>(std::move(x), std::move(y), std::move(s)); + impl_ = std::make_shared>(std::move(x), std::move(y), std::move(s)); + valid_ = impl_->valid(); + if ( ! valid_) { + error_msg_ = impl_->error_msg(); + } } Real operator()(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); return impl_->operator()(x); } Real prime(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); return impl_->prime(x); } friend std::ostream& operator<<(std::ostream & os, const makima & m) { + if ( ! m.valid_) return os; os << *m.impl_; return os; } void push_back(Real x, Real y) { + if ( ! valid_) return; // We do not realize if the object is constructed properly here. + static const char* function = "boost::math::interpolators::makima::push_back"; using std::abs; using std::isnan; if (x <= impl_->x_.back()) { - throw std::domain_error("Calling push_back must preserve the monotonicity of the x's"); + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Calling push_back must preserve the monotonicity of the x's", false, Policy()); + return; } impl_->x_.push_back(x); impl_->y_.push_back(y); @@ -168,11 +179,18 @@ class makima { } } + std::pair domain() const + { + if ( ! valid_) return {0, 0}; + return impl_->domain(); + } + private: - std::shared_ptr> impl_; + std::shared_ptr> impl_; + bool valid_ = false; + std::string error_msg_; }; } -} -} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/pchip.hpp b/include/boost/math/interpolators/pchip.hpp index a4ad5a3579..6da540547f 100644 --- a/include/boost/math/interpolators/pchip.hpp +++ b/include/boost/math/interpolators/pchip.hpp @@ -6,15 +6,18 @@ #ifndef BOOST_MATH_INTERPOLATORS_PCHIP_HPP #define BOOST_MATH_INTERPOLATORS_PCHIP_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template> class pchip { public: using Real = typename RandomAccessContainer::value_type; @@ -29,9 +32,16 @@ class pchip { std::ostringstream oss; oss << __FILE__ << ":" << __LINE__ << ":" << __func__; oss << " This interpolator requires at least four data points."; - throw std::domain_error(oss.str()); + error_msg_ = oss.str(); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("boost::math::interpolators::pchip::pchip", error_msg_.c_str(), false, Policy()); + valid_ = false; + return; + } + // Preserve capacity for fixed-capacity containers such as circular_buffer. + RandomAccessContainer s(x); + for (auto& si : s) { + si = std::numeric_limits::quiet_NaN(); } - RandomAccessContainer s(x.size(), std::numeric_limits::quiet_NaN()); if (isnan(left_endpoint_derivative)) { // If the derivative is not specified, this seems as good a choice as any. @@ -43,11 +53,9 @@ class pchip { { s[0] = left_endpoint_derivative; } - for (decltype(s.size()) k = 1; k < s.size()-1; ++k) { Real hkm1 = x[k] - x[k-1]; Real dkm1 = (y[k] - y[k-1])/hkm1; - Real hk = x[k+1] - x[k]; Real dk = (y[k+1] - y[k])/hk; Real w1 = 2*hk + hkm1; @@ -63,7 +71,6 @@ class pchip { // Un-numbered equation just before Section 3.5: s[k] = (w1+w2)/(w1/dkm1 + w2/dk); } - } auto n = s.size(); if (isnan(right_endpoint_derivative)) @@ -74,28 +81,38 @@ class pchip { { s[n-1] = right_endpoint_derivative; } - impl_ = std::make_shared>(std::move(x), std::move(y), std::move(s)); + impl_ = std::make_shared>(std::move(x), std::move(y), std::move(s)); + valid_ = impl_->valid(); + if ( ! valid_) { + error_msg_ = impl_->error_msg(); + } } Real operator()(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); return impl_->operator()(x); } Real prime(Real x) const { + if ( ! valid_) return std::numeric_limits::quiet_NaN(); return impl_->prime(x); } friend std::ostream& operator<<(std::ostream & os, const pchip & m) { + if ( ! m.valid_) return os; os << *m.impl_; return os; } void push_back(Real x, Real y) { + if ( ! valid_) return; // We do not realize if the object is constructed properly here. + static const char* function = "boost::math::interpolators::pchip::push_back"; using std::abs; using std::isnan; if (x <= impl_->x_.back()) { - throw std::domain_error("Calling push_back must preserve the monotonicity of the x's"); + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Calling push_back must preserve the monotonicity of the x's", false, Policy()); + return; } impl_->x_.push_back(x); impl_->y_.push_back(y); @@ -123,14 +140,16 @@ class pchip { std::pair domain() const { + if ( ! valid_) return {0, 0}; return impl_->domain(); } private: - std::shared_ptr> impl_; + std::shared_ptr> impl_; + bool valid_ = false; + std::string error_msg_; }; } -} -} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/quintic_hermite.hpp b/include/boost/math/interpolators/quintic_hermite.hpp index 1c00b15469..b8ec5ab0ae 100644 --- a/include/boost/math/interpolators/quintic_hermite.hpp +++ b/include/boost/math/interpolators/quintic_hermite.hpp @@ -7,17 +7,20 @@ #ifndef BOOST_MATH_INTERPOLATORS_QUINTIC_HERMITE_HPP #define BOOST_MATH_INTERPOLATORS_QUINTIC_HERMITE_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template class quintic_hermite { public: using Real = typename RandomAccessContainer::value_type; @@ -65,7 +68,7 @@ class quintic_hermite { std::shared_ptr> impl_; }; -template +BOOST_MATH_EXPORT template class cardinal_quintic_hermite { public: using Real = typename RandomAccessContainer::value_type; @@ -100,7 +103,7 @@ class cardinal_quintic_hermite { std::shared_ptr> impl_; }; -template +BOOST_MATH_EXPORT template class cardinal_quintic_hermite_aos { public: using Point = typename RandomAccessContainer::value_type; @@ -138,6 +141,5 @@ class cardinal_quintic_hermite_aos { }; } -} -} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/septic_hermite.hpp b/include/boost/math/interpolators/septic_hermite.hpp index e8cb8e5493..e79a462fc5 100644 --- a/include/boost/math/interpolators/septic_hermite.hpp +++ b/include/boost/math/interpolators/septic_hermite.hpp @@ -6,17 +6,20 @@ */ #ifndef BOOST_MATH_INTERPOLATORS_SEPTIC_HERMITE_HPP #define BOOST_MATH_INTERPOLATORS_SEPTIC_HERMITE_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template class septic_hermite { public: @@ -62,7 +65,7 @@ class septic_hermite std::shared_ptr> impl_; }; -template +BOOST_MATH_EXPORT template class cardinal_septic_hermite { public: @@ -103,7 +106,7 @@ class cardinal_septic_hermite }; -template +BOOST_MATH_EXPORT template class cardinal_septic_hermite_aos { public: using Point = typename RandomAccessContainer::value_type; @@ -142,6 +145,5 @@ class cardinal_septic_hermite_aos { }; } -} -} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/vector_barycentric_rational.hpp b/include/boost/math/interpolators/vector_barycentric_rational.hpp index 1b899fbd5f..0b2516eb9f 100644 --- a/include/boost/math/interpolators/vector_barycentric_rational.hpp +++ b/include/boost/math/interpolators/vector_barycentric_rational.hpp @@ -12,12 +12,14 @@ #ifndef BOOST_MATH_INTERPOLATORS_VECTOR_BARYCENTRIC_RATIONAL_HPP #define BOOST_MATH_INTERPOLATORS_VECTOR_BARYCENTRIC_RATIONAL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include -namespace boost{ namespace math{ namespace interpolators{ +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators{ -template +BOOST_MATH_EXPORT template class vector_barycentric_rational { public: @@ -78,5 +80,5 @@ void vector_barycentric_rational::operator()(type return; } -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/interpolators/whittaker_shannon.hpp b/include/boost/math/interpolators/whittaker_shannon.hpp index a5c5367a9d..fbcb60ea94 100644 --- a/include/boost/math/interpolators/whittaker_shannon.hpp +++ b/include/boost/math/interpolators/whittaker_shannon.hpp @@ -5,12 +5,14 @@ // or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_INTERPOLATORS_WHITAKKER_SHANNON_HPP #define BOOST_MATH_INTERPOLATORS_WHITAKKER_SHANNON_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include -namespace boost { namespace math { namespace interpolators { +BOOST_MATH_NAMESPACE_BEGIN namespace interpolators { -template +BOOST_MATH_EXPORT template class whittaker_shannon { public: @@ -43,5 +45,5 @@ class whittaker_shannon { private: std::shared_ptr> m_impl; }; -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/octonion.hpp b/include/boost/math/octonion.hpp index 4239140564..a0c133df20 100644 --- a/include/boost/math/octonion.hpp +++ b/include/boost/math/octonion.hpp @@ -12,13 +12,12 @@ #define BOOST_OCTONION_HPP #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN #define BOOST_OCTONION_ACCESSOR_GENERATOR(type) \ type real() const \ @@ -91,14 +90,14 @@ namespace boost return(::std::complex(g,h)); \ } \ \ - ::boost::math::quaternion H_component_1() const \ + ::BOOST_MATH_NAMESPACE::quaternion H_component_1() const \ { \ - return(::boost::math::quaternion(a,b,c,d)); \ + return(::BOOST_MATH_NAMESPACE::quaternion(a,b,c,d)); \ } \ \ - ::boost::math::quaternion H_component_2() const \ + ::BOOST_MATH_NAMESPACE::quaternion H_component_2() const \ { \ - return(::boost::math::quaternion(e,f,g,h)); \ + return(::BOOST_MATH_NAMESPACE::quaternion(e,f,g,h)); \ } @@ -151,7 +150,7 @@ namespace boost return(*this); \ } \ \ - octonion & operator = (::boost::math::quaternion const & a_affecter) \ + octonion & operator = (::BOOST_MATH_NAMESPACE::quaternion const & a_affecter) \ { \ a = a_affecter.R_component_1(); \ b = a_affecter.R_component_2(); \ @@ -179,7 +178,7 @@ namespace boost // the The behavior of octonion is unspecified if T is not // one of float, double or long double. - template + BOOST_MATH_EXPORT template class octonion { public: @@ -231,8 +230,8 @@ namespace boost // constructor for O seen as H^2 - explicit octonion( ::boost::math::quaternion const & q0, - ::boost::math::quaternion const & q1 = ::boost::math::quaternion()) + explicit octonion( ::BOOST_MATH_NAMESPACE::quaternion const & q0, + ::BOOST_MATH_NAMESPACE::quaternion const & q1 = ::BOOST_MATH_NAMESPACE::quaternion()) : a(q0.R_component_1()), b(q0.R_component_2()), c(q0.R_component_3()), @@ -315,7 +314,7 @@ namespace boost } - octonion & operator += (::boost::math::quaternion const & rhs) + octonion & operator += (::BOOST_MATH_NAMESPACE::quaternion const & rhs) { T at = a + rhs.R_component_1(); // exception guard T bt = b + rhs.R_component_2(); // exception guard @@ -379,7 +378,7 @@ namespace boost } - octonion & operator -= (::boost::math::quaternion const & rhs) + octonion & operator -= (::BOOST_MATH_NAMESPACE::quaternion const & rhs) { T at = a - rhs.R_component_1(); // exception guard T bt = b - rhs.R_component_2(); // exception guard @@ -471,7 +470,7 @@ namespace boost } - octonion & operator *= (::boost::math::quaternion const & rhs) + octonion & operator *= (::BOOST_MATH_NAMESPACE::quaternion const & rhs) { T ar = rhs.R_component_1(); T br = rhs.R_component_2(); @@ -587,7 +586,7 @@ namespace boost } - octonion & operator /= (::boost::math::quaternion const & rhs) + octonion & operator /= (::BOOST_MATH_NAMESPACE::quaternion const & rhs) { T ar = rhs.R_component_1(); T br = rhs.R_component_2(); @@ -721,8 +720,8 @@ namespace boost { \ } \ \ - explicit octonion( ::boost::math::quaternion const & q0, \ - ::boost::math::quaternion const & q1 = ::boost::math::quaternion()) \ + explicit octonion( ::BOOST_MATH_NAMESPACE::quaternion const & q0, \ + ::BOOST_MATH_NAMESPACE::quaternion const & q1 = ::BOOST_MATH_NAMESPACE::quaternion()) \ : a(q0.R_component_1()), \ b(q0.R_component_2()), \ c(q0.R_component_3()), \ @@ -753,7 +752,7 @@ namespace boost } #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type) \ - octonion & operator += (::boost::math::quaternion const & rhs) \ + octonion & operator += (::BOOST_MATH_NAMESPACE::quaternion const & rhs) \ { \ a += rhs.R_component_1(); \ b += rhs.R_component_2(); \ @@ -797,7 +796,7 @@ namespace boost } #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type) \ - octonion & operator -= (::boost::math::quaternion const & rhs) \ + octonion & operator -= (::BOOST_MATH_NAMESPACE::quaternion const & rhs) \ { \ a -= rhs.R_component_1(); \ b -= rhs.R_component_2(); \ @@ -866,7 +865,7 @@ namespace boost } #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type) \ - octonion & operator *= (::boost::math::quaternion const & rhs) \ + octonion & operator *= (::BOOST_MATH_NAMESPACE::quaternion const & rhs) \ { \ type ar = rhs.R_component_1(); \ type br = rhs.R_component_2(); \ @@ -950,7 +949,6 @@ namespace boost return(*this); \ } -#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \ octonion & operator /= (::std::complex const & rhs) \ { \ @@ -992,52 +990,9 @@ namespace boost \ return(*this); \ } -#else - #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \ - octonion & operator /= (::std::complex const & rhs) \ - { \ - using ::std::valarray; \ - \ - valarray tr(2); \ - \ - tr[0] = rhs.real(); \ - tr[1] = rhs.imag(); \ - \ - type mixam = static_cast(1)/(abs(tr).max)(); \ - \ - tr *= mixam; \ - \ - valarray tt(8); \ - \ - tt[0] = +a*tr[0]-b*tr[1]; \ - tt[1] = -a*tr[1]+b*tr[0]; \ - tt[2] = +c*tr[0]-d*tr[1]; \ - tt[3] = +c*tr[1]+d*tr[0]; \ - tt[4] = +e*tr[0]-f*tr[1]; \ - tt[5] = +e*tr[1]+f*tr[0]; \ - tt[6] = +g*tr[0]+h*tr[1]; \ - tt[7] = +g*tr[1]+h*tr[0]; \ - \ - tr *= tr; \ - \ - tt *= (mixam/tr.sum()); \ - \ - a = tt[0]; \ - b = tt[1]; \ - c = tt[2]; \ - d = tt[3]; \ - e = tt[4]; \ - f = tt[5]; \ - g = tt[6]; \ - h = tt[7]; \ - \ - return(*this); \ - } -#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ -#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \ - octonion & operator /= (::boost::math::quaternion const & rhs) \ + octonion & operator /= (::BOOST_MATH_NAMESPACE::quaternion const & rhs) \ { \ using ::std::valarray; \ using ::std::abs; \ @@ -1079,52 +1034,7 @@ namespace boost \ return(*this); \ } -#else - #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \ - octonion & operator /= (::boost::math::quaternion const & rhs) \ - { \ - using ::std::valarray; \ - \ - valarray tr(4); \ - \ - tr[0] = static_cast(rhs.R_component_1()); \ - tr[1] = static_cast(rhs.R_component_2()); \ - tr[2] = static_cast(rhs.R_component_3()); \ - tr[3] = static_cast(rhs.R_component_4()); \ - \ - type mixam = static_cast(1)/(abs(tr).max)(); \ - \ - tr *= mixam; \ - \ - valarray tt(8); \ - \ - tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \ - tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \ - tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \ - tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \ - tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \ - tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \ - tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \ - tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \ - \ - tr *= tr; \ - \ - tt *= (mixam/tr.sum()); \ - \ - a = tt[0]; \ - b = tt[1]; \ - c = tt[2]; \ - d = tt[3]; \ - e = tt[4]; \ - f = tt[5]; \ - g = tt[6]; \ - h = tt[7]; \ - \ - return(*this); \ - } -#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ -#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \ template \ octonion & operator /= (octonion const & rhs) \ @@ -1173,55 +1083,6 @@ namespace boost \ return(*this); \ } -#else - #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \ - template \ - octonion & operator /= (octonion const & rhs) \ - { \ - using ::std::valarray; \ - \ - valarray tr(8); \ - \ - tr[0] = static_cast(rhs.R_component_1()); \ - tr[1] = static_cast(rhs.R_component_2()); \ - tr[2] = static_cast(rhs.R_component_3()); \ - tr[3] = static_cast(rhs.R_component_4()); \ - tr[4] = static_cast(rhs.R_component_5()); \ - tr[5] = static_cast(rhs.R_component_6()); \ - tr[6] = static_cast(rhs.R_component_7()); \ - tr[7] = static_cast(rhs.R_component_8()); \ - \ - type mixam = static_cast(1)/(abs(tr).max)(); \ - \ - tr *= mixam; \ - \ - valarray tt(8); \ - \ - tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]+e*tr[4]+f*tr[5]+g*tr[6]+h*tr[7]; \ - tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]-e*tr[5]+f*tr[4]+g*tr[7]-h*tr[6]; \ - tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]-e*tr[6]-f*tr[7]+g*tr[4]+h*tr[5]; \ - tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]-e*tr[7]+f*tr[6]-g*tr[5]+h*tr[4]; \ - tt[4] = -a*tr[4]+b*tr[5]+c*tr[6]+d*tr[7]+e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \ - tt[5] = -a*tr[5]-b*tr[4]+c*tr[7]-d*tr[6]+e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \ - tt[6] = -a*tr[6]-b*tr[7]-c*tr[4]+d*tr[5]+e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \ - tt[7] = -a*tr[7]+b*tr[6]-c*tr[5]-d*tr[4]+e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \ - \ - tr *= tr; \ - \ - tt *= (mixam/tr.sum()); \ - \ - a = tt[0]; \ - b = tt[1]; \ - c = tt[2]; \ - d = tt[3]; \ - e = tt[4]; \ - f = tt[5]; \ - g = tt[6]; \ - h = tt[7]; \ - \ - return(*this); \ - } -#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ #define BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \ @@ -1481,37 +1342,37 @@ namespace boost } #define BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op) \ - template \ + BOOST_MATH_EXPORT template \ inline octonion operator op (T const & lhs, octonion const & rhs) \ BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) #define BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op) \ - template \ + BOOST_MATH_EXPORT template \ inline octonion operator op (octonion const & lhs, T const & rhs) \ BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) #define BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op) \ - template \ + BOOST_MATH_EXPORT template \ inline octonion operator op (::std::complex const & lhs, octonion const & rhs) \ BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) #define BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op) \ - template \ + BOOST_MATH_EXPORT template \ inline octonion operator op (octonion const & lhs, ::std::complex const & rhs) \ BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) #define BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op) \ - template \ - inline octonion operator op (::boost::math::quaternion const & lhs, octonion const & rhs) \ + BOOST_MATH_EXPORT template \ + inline octonion operator op (::BOOST_MATH_NAMESPACE::quaternion const & lhs, octonion const & rhs) \ BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) #define BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op) \ - template \ - inline octonion operator op (octonion const & lhs, ::boost::math::quaternion const & rhs) \ + BOOST_MATH_EXPORT template \ + inline octonion operator op (octonion const & lhs, ::BOOST_MATH_NAMESPACE::quaternion const & rhs) \ BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) #define BOOST_OCTONION_OPERATOR_GENERATOR_4(op) \ - template \ + BOOST_MATH_EXPORT template \ inline octonion operator op (octonion const & lhs, octonion const & rhs) \ BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) @@ -1544,21 +1405,21 @@ namespace boost #undef BOOST_OCTONION_OPERATOR_GENERATOR_BODY - template + BOOST_MATH_EXPORT template inline octonion operator + (octonion const & o) { return(o); } - template + BOOST_MATH_EXPORT template inline octonion operator - (octonion const & o) { return(octonion(-o.R_component_1(),-o.R_component_2(),-o.R_component_3(),-o.R_component_4(),-o.R_component_5(),-o.R_component_6(),-o.R_component_7(),-o.R_component_8())); } - template + BOOST_MATH_EXPORT template inline bool operator == (T const & lhs, octonion const & rhs) { return( @@ -1574,7 +1435,7 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline bool operator == (octonion const & lhs, T const & rhs) { return( @@ -1590,7 +1451,7 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline bool operator == (::std::complex const & lhs, octonion const & rhs) { return( @@ -1606,7 +1467,7 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline bool operator == (octonion const & lhs, ::std::complex const & rhs) { return( @@ -1622,8 +1483,8 @@ namespace boost } - template - inline bool operator == (::boost::math::quaternion const & lhs, octonion const & rhs) + BOOST_MATH_EXPORT template + inline bool operator == (::BOOST_MATH_NAMESPACE::quaternion const & lhs, octonion const & rhs) { return( (rhs.R_component_1() == lhs.R_component_1())&& @@ -1638,8 +1499,8 @@ namespace boost } - template - inline bool operator == (octonion const & lhs, ::boost::math::quaternion const & rhs) + BOOST_MATH_EXPORT template + inline bool operator == (octonion const & lhs, ::BOOST_MATH_NAMESPACE::quaternion const & rhs) { return( (lhs.R_component_1() == rhs.R_component_1())&& @@ -1654,7 +1515,7 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline bool operator == (octonion const & lhs, octonion const & rhs) { return( @@ -1675,31 +1536,31 @@ namespace boost return(!(lhs == rhs)); \ } - template + BOOST_MATH_EXPORT template inline bool operator != (T const & lhs, octonion const & rhs) BOOST_OCTONION_NOT_EQUAL_GENERATOR - template + BOOST_MATH_EXPORT template inline bool operator != (octonion const & lhs, T const & rhs) BOOST_OCTONION_NOT_EQUAL_GENERATOR - template + BOOST_MATH_EXPORT template inline bool operator != (::std::complex const & lhs, octonion const & rhs) BOOST_OCTONION_NOT_EQUAL_GENERATOR - template + BOOST_MATH_EXPORT template inline bool operator != (octonion const & lhs, ::std::complex const & rhs) BOOST_OCTONION_NOT_EQUAL_GENERATOR - template - inline bool operator != (::boost::math::quaternion const & lhs, octonion const & rhs) + BOOST_MATH_EXPORT template + inline bool operator != (::BOOST_MATH_NAMESPACE::quaternion const & lhs, octonion const & rhs) BOOST_OCTONION_NOT_EQUAL_GENERATOR - template - inline bool operator != (octonion const & lhs, ::boost::math::quaternion const & rhs) + BOOST_MATH_EXPORT template + inline bool operator != (octonion const & lhs, ::BOOST_MATH_NAMESPACE::quaternion const & rhs) BOOST_OCTONION_NOT_EQUAL_GENERATOR - template + BOOST_MATH_EXPORT template inline bool operator != (octonion const & lhs, octonion const & rhs) BOOST_OCTONION_NOT_EQUAL_GENERATOR @@ -1710,7 +1571,7 @@ namespace boost // Note: the default values in the constructors of the complex and quaternions make for // a very complex and ambiguous situation; we have made choices to disambiguate. - template + BOOST_MATH_EXPORT template ::std::basic_istream & operator >> ( ::std::basic_istream & is, octonion & o) { @@ -1733,8 +1594,8 @@ namespace boost ::std::complex x = ::std::complex(); ::std::complex y = ::std::complex(); - ::boost::math::quaternion p = ::boost::math::quaternion(); - ::boost::math::quaternion q = ::boost::math::quaternion(); + ::BOOST_MATH_NAMESPACE::quaternion p = ::BOOST_MATH_NAMESPACE::quaternion(); + ::BOOST_MATH_NAMESPACE::quaternion q = ::BOOST_MATH_NAMESPACE::quaternion(); charT ch = charT(); char cc; @@ -1809,7 +1670,7 @@ namespace boost } else if (cc == ',') // read "((u)," { - p = ::boost::math::quaternion(u); + p = ::BOOST_MATH_NAMESPACE::quaternion(u); is >> q; // read "((u),q" @@ -1857,7 +1718,7 @@ namespace boost if (cc == ')') // read "((u,v)" { - p = ::boost::math::quaternion(u,v); + p = ::BOOST_MATH_NAMESPACE::quaternion(u,v); is >> ch; // get the next lexeme @@ -1993,7 +1854,7 @@ namespace boost if (cc == ')') // read "((a),q)" { - p = ::boost::math::quaternion(a); + p = ::BOOST_MATH_NAMESPACE::quaternion(a); o = octonion(p,q); } @@ -2109,7 +1970,7 @@ namespace boost if (cc == '(') // read "((a),(e,(" (ambiguity resolution) { - p = ::boost::math::quaternion(a); + p = ::BOOST_MATH_NAMESPACE::quaternion(a); x = ::std::complex(c); // "c" was actually "e" @@ -2129,7 +1990,7 @@ namespace boost if (cc == ')') // read "((a),(e,y)" { - q = ::boost::math::quaternion(x,y); + q = ::BOOST_MATH_NAMESPACE::quaternion(x,y); is >> ch; // get the next lexeme @@ -2248,7 +2109,7 @@ namespace boost } else if (cc == ',') // read "((a),(e,f," (ambiguity resolution) { - p = ::boost::math::quaternion(a); + p = ::BOOST_MATH_NAMESPACE::quaternion(a); is >> g; // read "((a),(e,f,g" (too late to backtrack) @@ -2266,7 +2127,7 @@ namespace boost if (cc == ')') // read "((a),(e,f,g)" { - q = ::boost::math::quaternion(c,d,g); // "c" was actually "e", and "d" was actually "f" + q = ::BOOST_MATH_NAMESPACE::quaternion(c,d,g); // "c" was actually "e", and "d" was actually "f" is >> ch; // get the next lexeme @@ -2305,7 +2166,7 @@ namespace boost if (cc == ')') // read "((a),(e,f,g,h)" { - q = ::boost::math::quaternion(c,d,g,h); // "c" was actually "e", and "d" was actually "f" + q = ::BOOST_MATH_NAMESPACE::quaternion(c,d,g,h); // "c" was actually "e", and "d" was actually "f" is >> ch; // get the next lexeme @@ -2479,7 +2340,7 @@ namespace boost } else if (cc == ',') // read "((a,v)," { - p = ::boost::math::quaternion(u,v); + p = ::BOOST_MATH_NAMESPACE::quaternion(u,v); is >> q; // read "((a,v),q" @@ -2574,7 +2435,7 @@ namespace boost if (cc == '(') // read "((a,b),((" { - p = ::boost::math::quaternion(a,b); + p = ::BOOST_MATH_NAMESPACE::quaternion(a,b); is.putback(ch); @@ -2851,7 +2712,7 @@ namespace boost } else if (cc == ',') // read "((a,b),(e,f," (ambiguity resolution) { - p = ::boost::math::quaternion(a,b); // too late to backtrack + p = ::BOOST_MATH_NAMESPACE::quaternion(a,b); // too late to backtrack is >> g; // read "((a,b),(e,f,g" @@ -2881,7 +2742,7 @@ namespace boost if (cc == ')') // read "((a,b),(e,f,g))" { - q = ::boost::math::quaternion(c,d,g); // "c" is actually "e" and "d" is actually "f" + q = ::BOOST_MATH_NAMESPACE::quaternion(c,d,g); // "c" is actually "e" and "d" is actually "f" o = octonion(p,q); } @@ -2920,7 +2781,7 @@ namespace boost if (cc == ')') // read ((a,b),(e,f,g,h))" { - q = ::boost::math::quaternion(c,d,g,h); // "c" is actually "e" and "d" is actually "f" + q = ::BOOST_MATH_NAMESPACE::quaternion(c,d,g,h); // "c" is actually "e" and "d" is actually "f" o = octonion(p,q); } @@ -2995,7 +2856,7 @@ namespace boost } else if (cc == ',') // read "((a,b,c)," { - p = ::boost::math::quaternion(a,b,c); + p = ::BOOST_MATH_NAMESPACE::quaternion(a,b,c); is >> q; // read "((a,b,c),q" @@ -3059,7 +2920,7 @@ namespace boost } else if (cc == ',') // read "((a,b,c,d)," { - p = ::boost::math::quaternion(a,b,c,d); + p = ::BOOST_MATH_NAMESPACE::quaternion(a,b,c,d); is >> q; // read "((a,b,c,d),q" @@ -3159,7 +3020,7 @@ namespace boost if (cc == '(') // read "(a,((" { - p = ::boost::math::quaternion(a); + p = ::BOOST_MATH_NAMESPACE::quaternion(a); is.putback(ch); @@ -3436,7 +3297,7 @@ namespace boost } else if (cc == ',') // read "(a,(e,f," (ambiguity resolution) { - p = ::boost::math::quaternion(a); + p = ::BOOST_MATH_NAMESPACE::quaternion(a); is >> g; // read "(a,(e,f,g" @@ -3466,7 +3327,7 @@ namespace boost if (cc == ')') // read "(a,(e,f,g))" { - q = ::boost::math::quaternion(c,d,g); // "c" is actually "e" and "d" is actually "f" + q = ::BOOST_MATH_NAMESPACE::quaternion(c,d,g); // "c" is actually "e" and "d" is actually "f" o = octonion(p,q); } @@ -3505,7 +3366,7 @@ namespace boost if (cc == ')') // read "(a,(e,f,g,h))" { - q = ::boost::math::quaternion(c,d,g,h); // "c" is actually "e" and "d" is actually "f" + q = ::BOOST_MATH_NAMESPACE::quaternion(c,d,g,h); // "c" is actually "e" and "d" is actually "f" o = octonion(p,q); } @@ -3856,7 +3717,7 @@ namespace boost // LCOV_EXCL_STOP - template + BOOST_MATH_EXPORT template ::std::basic_ostream & operator << ( ::std::basic_ostream & os, octonion const & o) { @@ -3884,14 +3745,14 @@ namespace boost // values - template + BOOST_MATH_EXPORT template inline T real(octonion const & o) { return(o.real()); } - template + BOOST_MATH_EXPORT template inline octonion unreal(octonion const & o) { return(o.unreal()); @@ -3913,12 +3774,10 @@ namespace boost temp[7] = o.R_component_8(); - template + BOOST_MATH_EXPORT template inline T sup(octonion const & o) { -#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP using ::std::abs; -#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ BOOST_OCTONION_VALARRAY_LOADER @@ -3926,12 +3785,10 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline T l1(octonion const & o) { -#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP using ::std::abs; -#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ BOOST_OCTONION_VALARRAY_LOADER @@ -3939,12 +3796,10 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline T abs(const octonion & o) { -#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP using ::std::abs; -#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ using ::std::sqrt; @@ -3976,14 +3831,14 @@ namespace boost // Note: This is the Cayley norm, not the Euclidean norm... - template + BOOST_MATH_EXPORT template inline T norm(octonion const & o) { return(real(o*conj(o))); } - template + BOOST_MATH_EXPORT template inline octonion conj(octonion const & o) { return(octonion( +o.R_component_1(), @@ -4001,7 +3856,7 @@ namespace boost // to the complex "arg" and the quaternionic "cylindropolar". - template + BOOST_MATH_EXPORT template inline octonion spherical(T const & rho, T const & theta, T const & phi1, @@ -4056,7 +3911,7 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline octonion multipolar(T const & rho1, T const & theta1, T const & rho2, @@ -4082,7 +3937,7 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline octonion cylindrical(T const & r, T const & angle, T const & h1, @@ -4102,13 +3957,13 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline octonion exp(octonion const & o) { using ::std::exp; using ::std::cos; - using ::boost::math::sinc_pi; + using ::BOOST_MATH_NAMESPACE::sinc_pi; T u = exp(real(o)); @@ -4124,14 +3979,14 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline octonion cos(octonion const & o) { using ::std::sin; using ::std::cos; using ::std::cosh; - using ::boost::math::sinhc_pi; + using ::BOOST_MATH_NAMESPACE::sinhc_pi; T z = abs(unreal(o)); @@ -4145,14 +4000,14 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline octonion sin(octonion const & o) { using ::std::sin; using ::std::cos; using ::std::cosh; - using ::boost::math::sinhc_pi; + using ::BOOST_MATH_NAMESPACE::sinhc_pi; T z = abs(unreal(o)); @@ -4166,35 +4021,35 @@ namespace boost } - template + BOOST_MATH_EXPORT template inline octonion tan(octonion const & o) { return(sin(o)/cos(o)); } - template + BOOST_MATH_EXPORT template inline octonion cosh(octonion const & o) { return((exp(+o)+exp(-o))/static_cast(2)); } - template + BOOST_MATH_EXPORT template inline octonion sinh(octonion const & o) { return((exp(+o)-exp(-o))/static_cast(2)); } - template + BOOST_MATH_EXPORT template inline octonion tanh(octonion const & o) { return(sinh(o)/cosh(o)); } - template + BOOST_MATH_EXPORT template octonion pow(octonion const & o, int n) { @@ -4248,7 +4103,6 @@ namespace boost static_cast(rhs.R_component_8()))); } } - } -} + BOOST_MATH_NAMESPACE_END #endif /* BOOST_OCTONION_HPP */ diff --git a/include/boost/math/optimization/cma_es.hpp b/include/boost/math/optimization/cma_es.hpp index 42b901a190..fac3950d28 100644 --- a/include/boost/math/optimization/cma_es.hpp +++ b/include/boost/math/optimization/cma_es.hpp @@ -6,6 +6,7 @@ */ #ifndef BOOST_MATH_OPTIMIZATION_CMA_ES_HPP #define BOOST_MATH_OPTIMIZATION_CMA_ES_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -15,6 +16,7 @@ #include #include #include +#endif #include #include #if __has_include() @@ -36,9 +38,9 @@ #define BOOST_MATH_DEBUG_CMA_ES 0 #endif -namespace boost::math::optimization { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { -template struct cma_es_parameters { +BOOST_MATH_EXPORT template struct cma_es_parameters { using Real = typename ArgumentContainer::value_type; using DimensionlessReal = decltype(Real()/Real()); ArgumentContainer lower_bounds; @@ -53,7 +55,7 @@ template struct cma_es_parameters { DimensionlessReal learning_rate = 1; }; -template +BOOST_MATH_EXPORT template void validate_cma_es_parameters(cma_es_parameters ¶ms) { using Real = typename ArgumentContainer::value_type; using DimensionlessReal = decltype(Real()/Real()); @@ -84,7 +86,7 @@ void validate_cma_es_parameters(cma_es_parameters ¶ms) { } } -template +BOOST_MATH_EXPORT template ArgumentContainer cma_es( const Func cost_function, cma_es_parameters ¶ms, @@ -388,5 +390,5 @@ ArgumentContainer cma_es( return best_vector; } -} // namespace boost::math::optimization +} BOOST_MATH_NAMESPACE_END // namespace boost::math::optimization #endif diff --git a/include/boost/math/optimization/detail/common.hpp b/include/boost/math/optimization/detail/common.hpp index 05124026e7..a24ffa537c 100644 --- a/include/boost/math/optimization/detail/common.hpp +++ b/include/boost/math/optimization/detail/common.hpp @@ -6,6 +6,7 @@ */ #ifndef BOOST_MATH_OPTIMIZATION_DETAIL_COMMON_HPP #define BOOST_MATH_OPTIMIZATION_DETAIL_COMMON_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include // for std::sort #include #include @@ -13,15 +14,18 @@ #include #include #include // for std::false_type +#endif + +#include -namespace boost::math::optimization::detail { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization::detail { template struct has_resize : std::false_type {}; template struct has_resize().resize(size_t{}))>> : std::true_type {}; -template constexpr bool has_resize_v = has_resize::value; +template BOOST_MATH_INLINE_CONSTEXPR bool has_resize_v = has_resize::value; template void validate_bounds(ArgumentContainer const &lower_bounds, ArgumentContainer const &upper_bounds) { @@ -64,7 +68,7 @@ void validate_bounds(ArgumentContainer const &lower_bounds, ArgumentContainer co } } -template +BOOST_MATH_TEST_EXPORT template std::vector random_initial_population(ArgumentContainer const &lower_bounds, ArgumentContainer const &upper_bounds, size_t initial_population_size, URBG &&gen) { @@ -112,7 +116,7 @@ std::vector random_initial_population(ArgumentContainer const return population; } -template +BOOST_MATH_TEST_EXPORT template void validate_initial_guess(ArgumentContainer const &initial_guess, ArgumentContainer const &lower_bounds, ArgumentContainer const &upper_bounds) { using std::isfinite; @@ -144,7 +148,7 @@ void validate_initial_guess(ArgumentContainer const &initial_guess, ArgumentCont } // Return indices corresponding to the minimum function values. -template std::vector best_indices(std::vector const &function_values) { +BOOST_MATH_TEST_EXPORT template std::vector best_indices(std::vector const &function_values) { using std::isnan; const size_t n = function_values.size(); std::vector indices(n); @@ -164,7 +168,7 @@ template std::vector best_indices(std::vector cons return indices; } -template +BOOST_MATH_TEST_EXPORT template auto weighted_lehmer_mean(RandomAccessContainer const & values, RandomAccessContainer const & weights) { using std::isfinite; if (values.size() != weights.size()) { @@ -196,5 +200,5 @@ auto weighted_lehmer_mean(RandomAccessContainer const & values, RandomAccessCont return numerator/denominator; } -} // namespace boost::math::optimization::detail +} BOOST_MATH_NAMESPACE_END // namespace boost::math::optimization::detail #endif diff --git a/include/boost/math/optimization/detail/differentiable_opt_utilties.hpp b/include/boost/math/optimization/detail/differentiable_opt_utilties.hpp index 8fd3c2a083..a737c8e8a6 100644 --- a/include/boost/math/optimization/detail/differentiable_opt_utilties.hpp +++ b/include/boost/math/optimization/detail/differentiable_opt_utilties.hpp @@ -5,16 +5,17 @@ #ifndef BOOST_MATH_OPTIMIZATION_DETAIL_DIFFERENTIABLE_OPT_UTILITIES_HPP #define BOOST_MATH_OPTIMIZATION_DETAIL_DIFFERENTIABLE_OPT_UTILITIES_HPP #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { -namespace rdiff = boost::math::differentiation::reverse_mode; +namespace rdiff = BOOST_MATH_NAMESPACE::differentiation::reverse_mode; /** @brief> helper to get the underlying realtype from * update policy @@ -152,6 +153,5 @@ random_vector(size_t n) } } // namespace optimization -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/optimization/detail/gradient_opt_base.hpp b/include/boost/math/optimization/detail/gradient_opt_base.hpp index e13b79279d..ea9f070ad7 100644 --- a/include/boost/math/optimization/detail/gradient_opt_base.hpp +++ b/include/boost/math/optimization/detail/gradient_opt_base.hpp @@ -6,11 +6,10 @@ #define BOOST_MATH_OPTIMIZATION_DETAIL_GRADIENT_OPT_BASE_HPP #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { -namespace rdiff = boost::math::differentiation::reverse_mode; +namespace rdiff = BOOST_MATH_NAMESPACE::differentiation::reverse_mode; /** * @brief The abstract_optimizer class implementing common variables @@ -87,6 +86,5 @@ class abstract_optimizer const std::vector& gradients() const { return derived().g_; } }; } // namespace optimization -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/optimization/detail/line_search_policies.hpp b/include/boost/math/optimization/detail/line_search_policies.hpp index 1bc3c1cc4d..073e0bee4e 100644 --- a/include/boost/math/optimization/detail/line_search_policies.hpp +++ b/include/boost/math/optimization/detail/line_search_policies.hpp @@ -7,10 +7,11 @@ #define BOOST_MATH_OPTIMIZATION_DETAIL_LINE_SEARCH_POLICIES_HPP #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include -namespace boost { -namespace math { +#endif +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { /** @@ -53,7 +54,7 @@ class armijo_line_search_policy class ArgumentContainer> RealType operator()(Objective& objective, ObjectiveEvalPolicy& obj_eval, - GradientEvalPolicy& grad_eval, + GradientEvalPolicy& /*grad_eval*/, ArgumentContainer& x, const std::vector& g, const std::vector& p, @@ -201,6 +202,5 @@ class strong_wolfe_line_search_policy }; } // namespace optimization -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // LINE_SEARCH_POLICIES_HPP diff --git a/include/boost/math/optimization/detail/rdiff_optimization_policies.hpp b/include/boost/math/optimization/detail/rdiff_optimization_policies.hpp index b4cad4b004..1e86c81657 100644 --- a/include/boost/math/optimization/detail/rdiff_optimization_policies.hpp +++ b/include/boost/math/optimization/detail/rdiff_optimization_policies.hpp @@ -6,14 +6,15 @@ #define BOOST_MATH_OPTIMIZATION_DETAIL_RDIFF_OPTIMIZATION_POLICIES_HPP #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { -namespace rdiff = boost::math::differentiation::reverse_mode; +namespace rdiff = BOOST_MATH_NAMESPACE::differentiation::reverse_mode; /******************************************************************/ /** @@ -76,7 +77,7 @@ template struct tape_initializer_rvar { template - void operator()(ArgumentContainer& x) const noexcept + void operator()(ArgumentContainer& /*x*/) const noexcept { static_assert(std::is_same>::value, @@ -128,7 +129,6 @@ struct costant_initializer_rvar } }; } // namespace optimization -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/optimization/differential_evolution.hpp b/include/boost/math/optimization/differential_evolution.hpp index f734f92111..ede792ab9b 100644 --- a/include/boost/math/optimization/differential_evolution.hpp +++ b/include/boost/math/optimization/differential_evolution.hpp @@ -6,8 +6,13 @@ */ #ifndef BOOST_MATH_OPTIMIZATION_DIFFERENTIAL_EVOLUTION_HPP #define BOOST_MATH_OPTIMIZATION_DIFFERENTIAL_EVOLUTION_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -17,8 +22,9 @@ #include #include #include +#endif -namespace boost::math::optimization { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { // Storn, R., Price, K. (1997). Differential evolution-a simple and efficient heuristic for global optimization over // continuous spaces. @@ -27,7 +33,7 @@ namespace boost::math::optimization { // https://www.cp.eng.chula.ac.th/~prabhas//teaching/ec/ec2012/storn_price_de.pdf // We provide the parameters in a struct-there are too many of them and they are too unwieldy to pass individually: -template struct differential_evolution_parameters { +BOOST_MATH_EXPORT template struct differential_evolution_parameters { using Real = typename ArgumentContainer::value_type; using DimensionlessReal = decltype(Real()/Real()); ArgumentContainer lower_bounds; @@ -42,7 +48,7 @@ template struct differential_evolution_parameters { unsigned threads = std::thread::hardware_concurrency(); }; -template +BOOST_MATH_EXPORT template void validate_differential_evolution_parameters(differential_evolution_parameters const &de_params) { using std::isfinite; using std::isnan; @@ -80,7 +86,7 @@ void validate_differential_evolution_parameters(differential_evolution_parameter } } -template +BOOST_MATH_EXPORT template ArgumentContainer differential_evolution( const Func cost_function, differential_evolution_parameters const &de_params, URBG &gen, std::invoke_result_t target_value = @@ -232,5 +238,5 @@ ArgumentContainer differential_evolution( return population[std::distance(cost.begin(), it)]; } -} // namespace boost::math::optimization +} BOOST_MATH_NAMESPACE_END // namespace boost::math::optimization #endif diff --git a/include/boost/math/optimization/gradient_descent.hpp b/include/boost/math/optimization/gradient_descent.hpp index 68972e2968..3ba303a27b 100644 --- a/include/boost/math/optimization/gradient_descent.hpp +++ b/include/boost/math/optimization/gradient_descent.hpp @@ -8,11 +8,10 @@ #include #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { -template +BOOST_MATH_EXPORT template struct gradient_descent_update_policy { RealType lr_; @@ -21,14 +20,14 @@ struct gradient_descent_update_policy template::value>::type> void operator()(ArgumentType& x, RealType& g) { x.get_value() -= lr_ * g; } template::value, int>::type = 0> void operator()(ArgumentType& x, RealType& g) const @@ -124,7 +123,7 @@ class gradient_descent * custom learning rate */ -template +BOOST_MATH_EXPORT template auto make_gradient_descent(Objective&& obj, ArgumentContainer& x, @@ -144,7 +143,7 @@ make_gradient_descent(Objective&& obj, gradient_descent_update_policy(lr)); } -template @@ -168,7 +167,7 @@ make_gradient_descent(Objective&& obj, gradient_descent_update_policy(lr)); } -template #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { } // namespace optimization -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/optimization/jso.hpp b/include/boost/math/optimization/jso.hpp index 44359a00dc..dac33c7466 100644 --- a/include/boost/math/optimization/jso.hpp +++ b/include/boost/math/optimization/jso.hpp @@ -6,8 +6,13 @@ */ #ifndef BOOST_MATH_OPTIMIZATION_JSO_HPP #define BOOST_MATH_OPTIMIZATION_JSO_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -18,8 +23,9 @@ #include #include #include +#endif -namespace boost::math::optimization { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { #ifndef BOOST_MATH_DEBUG_JSO #define BOOST_MATH_DEBUG_JSO 0 @@ -31,7 +37,7 @@ namespace boost::math::optimization { // to understand without also reading: Zhang, J., & Sanderson, A. C. (2009). // JADE: adaptive differential evolution with optional external archive. // IEEE Transactions on evolutionary computation, 13(5), 945-958." -template struct jso_parameters { +BOOST_MATH_EXPORT template struct jso_parameters { using Real = typename ArgumentContainer::value_type; using DimensionlessReal = decltype(Real()/Real()); ArgumentContainer lower_bounds; @@ -49,7 +55,7 @@ template struct jso_parameters { ArgumentContainer const *initial_guess = nullptr; }; -template +BOOST_MATH_EXPORT template void validate_jso_parameters(jso_parameters &jso_params) { using std::isfinite; using std::isnan; @@ -67,6 +73,9 @@ void validate_jso_parameters(jso_parameters &jso_params) { // but if we followed the reference, the population size would then be zero. jso_params.initial_population_size = static_cast( std::ceil(25 * std::log(dimension + 1.0) * sqrt(dimension))); + if (jso_params.initial_population_size < jso_params.threads) { + jso_params.initial_population_size = jso_params.threads; + } } if (jso_params.max_function_evaluations == 0) { // Recommended value from the reference: @@ -91,7 +100,7 @@ void validate_jso_parameters(jso_parameters &jso_params) { } } -template +BOOST_MATH_EXPORT template ArgumentContainer jso(const Func cost_function, jso_parameters &jso_params, URBG &gen, @@ -461,5 +470,5 @@ jso(const Func cost_function, jso_parameters &jso_params, return population[indices[0]]; } -} // namespace boost::math::optimization +} BOOST_MATH_NAMESPACE_END // namespace boost::math::optimization #endif diff --git a/include/boost/math/optimization/lbfgs.hpp b/include/boost/math/optimization/lbfgs.hpp index 5554b7721d..7395c042e1 100644 --- a/include/boost/math/optimization/lbfgs.hpp +++ b/include/boost/math/optimization/lbfgs.hpp @@ -7,13 +7,16 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { /** @brief> Helper struct for L-BFGS @@ -35,7 +38,7 @@ namespace optimization { * pages 176-180 * algorithms 7.4/7.5 * */ -template +BOOST_MATH_EXPORT template struct lbfgs_optimizer_state { size_t m = 10; // default history length @@ -96,19 +99,19 @@ struct lbfgs_optimizer_state /** @brief> helper update for l-bfgs * x += alpha * search direction * */ -template +BOOST_MATH_EXPORT template struct lbfgs_update_policy { template::value>::type> void operator()(ArgumentType& x, RealType pk, RealType alpha) { x.get_value() += alpha * pk; } template::value, int>::type = 0> void operator()(ArgumentType& x, RealType pk, RealType alpha) @@ -264,7 +267,7 @@ class lbfgs } }; -template +BOOST_MATH_EXPORT template auto make_lbfgs(Objective&& obj, ArgumentContainer& x, std::size_t m = 10) { @@ -286,7 +289,7 @@ make_lbfgs(Objective&& obj, ArgumentContainer& x, std::size_t m = 10) strong_wolfe_line_search_policy{}); } -template auto @@ -314,7 +317,7 @@ make_lbfgs(Objective&& obj, strong_wolfe_line_search_policy{}); } -template @@ -344,7 +347,7 @@ make_lbfgs(Objective&& obj, std::forward(lsp)); } -template #include +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include #include #include -namespace boost { -namespace math { +#endif +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { -template +BOOST_MATH_EXPORT template struct optimization_result { size_t num_iter = 0; @@ -20,7 +23,7 @@ struct optimization_result bool converged; }; -template +BOOST_MATH_EXPORT template std::ostream& operator<<(std::ostream& os, const optimization_result& r) { @@ -40,7 +43,7 @@ operator<<(std::ostream& os, const optimization_result& r) return os; } /*****************************************************************************************/ -template +BOOST_MATH_EXPORT template struct gradient_norm_convergence_policy { RealType tol_; @@ -56,7 +59,7 @@ struct gradient_norm_convergence_policy } }; -template +BOOST_MATH_EXPORT template struct objective_tol_convergence_policy { RealType tol_; @@ -84,7 +87,7 @@ struct objective_tol_convergence_policy } }; -template +BOOST_MATH_EXPORT template struct relative_objective_tol_policy { RealType rel_tol_; @@ -106,14 +109,15 @@ struct relative_objective_tol_policy first_call_ = false; return false; } - RealType denom = max(1, abs(last_value_)); + using std::abs; + RealType denom = (std::max)(static_cast(1), static_cast(abs(last_value_))); RealType rel_diff = abs(objective_v - last_value_) / denom; last_value_ = objective_v; return rel_diff < rel_tol_; } }; -template +BOOST_MATH_EXPORT template struct combined_convergence_policy { Policy1 p1_; @@ -165,13 +169,13 @@ struct wallclock_termination_policy }; /*****************************************************************************************/ -template +BOOST_MATH_EXPORT template struct unconstrained_policy { void operator()(ArgumentContainer&) {} }; -template +BOOST_MATH_EXPORT template struct box_constraints { RealType min_, max_; @@ -186,7 +190,7 @@ struct box_constraints } }; -template +BOOST_MATH_EXPORT template struct nonnegativity_constraint { void operator()(ArgumentContainer& x) const @@ -197,7 +201,7 @@ struct nonnegativity_constraint } } }; -template +BOOST_MATH_EXPORT template struct l2_ball_constraint { RealType radius_; @@ -218,7 +222,7 @@ struct l2_ball_constraint } }; -template +BOOST_MATH_EXPORT template struct l1_ball_constraint { RealType radius_; @@ -239,7 +243,7 @@ struct l1_ball_constraint } } }; -template +BOOST_MATH_EXPORT template struct simplex_constraint { void operator()(ArgumentContainer& x) const @@ -257,7 +261,7 @@ struct simplex_constraint } }; -template +BOOST_MATH_EXPORT template struct function_constraint { using func_t = void (*)(ArgumentContainer&); @@ -271,7 +275,7 @@ struct function_constraint void operator()(ArgumentContainer& x) const { f_(x); } }; -template +BOOST_MATH_EXPORT template struct unit_sphere_constraint { void operator()(ArgumentContainer& x) const @@ -313,7 +317,7 @@ minimize_impl(Optimizer& opt, result.converged = converged(opt.gradients(), opt.objective_value()); return result; } -template, class ConvergencePolicy = @@ -331,6 +335,5 @@ minimize(Optimizer& opt, return minimize_impl(opt, project, converged, terminate, history); } } // namespace optimization -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/optimization/nesterov.hpp b/include/boost/math/optimization/nesterov.hpp index 1c882f4019..e784ccdc57 100644 --- a/include/boost/math/optimization/nesterov.hpp +++ b/include/boost/math/optimization/nesterov.hpp @@ -7,18 +7,19 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { -namespace rdiff = boost::math::differentiation::reverse_mode; +namespace rdiff = BOOST_MATH_NAMESPACE::differentiation::reverse_mode; /** * @brief The nesterov_update_policy class */ -template +BOOST_MATH_EXPORT template struct nesterov_update_policy { RealType lr_, mu_; @@ -28,7 +29,7 @@ struct nesterov_update_policy template::value>::type> void operator()(ArgumentType& x, RealType& g, RealType& v) { @@ -37,7 +38,7 @@ struct nesterov_update_policy x.get_value() += -mu_ * v_prev + (static_cast(1) + mu_) * v; } template::value, int>::type = 0> void operator()(ArgumentType& x, RealType& g, RealType& v) const @@ -128,7 +129,7 @@ class nesterov_accelerated_gradient } } }; -template +BOOST_MATH_EXPORT template auto make_nag(Objective&& obj, ArgumentContainer& x, @@ -149,7 +150,7 @@ make_nag(Objective&& obj, reverse_mode_gradient_evaluation_policy{}, nesterov_update_policy(lr, mu)); } -template @@ -174,7 +175,7 @@ make_nag(Objective&& obj, reverse_mode_gradient_evaluation_policy{}, nesterov_update_policy(lr, mu)); } -template{ lr, mu }); } } // namespace optimization -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/optimization/random_search.hpp b/include/boost/math/optimization/random_search.hpp index 4ecd4ce367..237ee12488 100644 --- a/include/boost/math/optimization/random_search.hpp +++ b/include/boost/math/optimization/random_search.hpp @@ -6,6 +6,9 @@ */ #ifndef BOOST_MATH_OPTIMIZATION_RANDOM_SEARCH_HPP #define BOOST_MATH_OPTIMIZATION_RANDOM_SEARCH_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -16,11 +19,12 @@ #include #include #include +#endif #include -namespace boost::math::optimization { +BOOST_MATH_NAMESPACE_BEGIN namespace optimization { -template struct random_search_parameters { +BOOST_MATH_EXPORT template struct random_search_parameters { using Real = typename ArgumentContainer::value_type; ArgumentContainer lower_bounds; ArgumentContainer upper_bounds; @@ -29,7 +33,7 @@ template struct random_search_parameters { unsigned threads = std::thread::hardware_concurrency(); }; -template +BOOST_MATH_EXPORT template void validate_random_search_parameters(random_search_parameters const ¶ms) { using std::isfinite; using std::isnan; @@ -45,7 +49,7 @@ void validate_random_search_parameters(random_search_parameters +BOOST_MATH_EXPORT template ArgumentContainer random_search( const Func cost_function, random_search_parameters const ¶ms, @@ -141,5 +145,5 @@ ArgumentContainer random_search( return best_vector; } -} // namespace boost::math::optimization +} BOOST_MATH_NAMESPACE_END // namespace boost::math::optimization #endif diff --git a/include/boost/math/policies/error_handling.hpp b/include/boost/math/policies/error_handling.hpp index adcb56f3e5..8d1c144d25 100644 --- a/include/boost/math/policies/error_handling.hpp +++ b/include/boost/math/policies/error_handling.hpp @@ -21,20 +21,28 @@ #include #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include +#endif #ifndef BOOST_MATH_NO_EXCEPTIONS +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #endif +#endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #ifndef BOOST_MATH_NO_RTTI +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif #ifdef _MSC_VER # pragma warning(push) // Quiet warnings in boost/format.hpp @@ -47,17 +55,17 @@ // for example when policy macros are used to ignore errors rather than throw. #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN #ifndef BOOST_MATH_NO_EXCEPTIONS -class evaluation_error : public std::runtime_error +BOOST_MATH_EXPORT class evaluation_error : public std::runtime_error { public: explicit evaluation_error(const std::string& s) : std::runtime_error(s){} }; -class rounding_error : public std::runtime_error +BOOST_MATH_EXPORT class rounding_error : public std::runtime_error { public: explicit rounding_error(const std::string& s) : std::runtime_error(s){} @@ -65,8 +73,8 @@ class rounding_error : public std::runtime_error #else -class evaluation_error {}; -class rounding_error {}; +BOOST_MATH_EXPORT class evaluation_error {}; +BOOST_MATH_EXPORT class rounding_error {}; #endif @@ -100,7 +108,7 @@ namespace detail template inline std::string prec_format(const T& val) { - using prec_type = typename boost::math::policies::precision >::type; + using prec_type = typename BOOST_MATH_NAMESPACE::policies::precision >::type; std::stringstream strm { }; @@ -179,7 +187,7 @@ void raise_error(const char* pfunction, const char* message) std::string function(pfunction); std::string msg("Error in function "); #ifndef BOOST_MATH_NO_RTTI - replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of()); + replace_all_in_string(function, "%1%", BOOST_MATH_NAMESPACE::policies::detail::name_of()); #else replace_all_in_string(function, "%1%", "Unknown"); #endif @@ -206,7 +214,7 @@ void raise_error(const char* pfunction, const char* pmessage, const T& val) std::string message(pmessage); std::string msg("Error in function "); #ifndef BOOST_MATH_NO_RTTI - replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of()); + replace_all_in_string(function, "%1%", BOOST_MATH_NAMESPACE::policies::detail::name_of()); #else replace_all_in_string(function, "%1%", "Unknown"); #endif @@ -221,208 +229,208 @@ void raise_error(const char* pfunction, const char* pmessage, const T& val) } #endif -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_domain_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::domain_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>&) { #ifdef BOOST_MATH_NO_EXCEPTIONS static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set."); #else raise_error(function, message, val); // we never get here: - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error( const char* , const char* , const T& , - const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::domain_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_domain_error( const char* , const char* , const T& , - const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::domain_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) { errno = EDOM; // This may or may not do the right thing, but the user asked for the error // to be silent so here we go anyway: - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_domain_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&) + const ::BOOST_MATH_NAMESPACE::policies::domain_error< ::BOOST_MATH_NAMESPACE::policies::user_error>&) { return user_domain_error(function, message, val); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_pole_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::pole_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>&) { #ifdef BOOST_MATH_NO_EXCEPTIONS static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set."); #else - return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>()); + return BOOST_MATH_NAMESPACE::policies::detail::raise_domain_error(function, message, val, ::BOOST_MATH_NAMESPACE::policies::domain_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>()); #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::pole_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) { - return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>()); + return ::BOOST_MATH_NAMESPACE::policies::detail::raise_domain_error(function, message, val, ::BOOST_MATH_NAMESPACE::policies::domain_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::pole_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) { - return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>()); + return ::BOOST_MATH_NAMESPACE::policies::detail::raise_domain_error(function, message, val, ::BOOST_MATH_NAMESPACE::policies::domain_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_pole_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&) + const ::BOOST_MATH_NAMESPACE::policies::pole_error< ::BOOST_MATH_NAMESPACE::policies::user_error>&) { return user_pole_error(function, message, val); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_overflow_error( const char* function, const char* message, - const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::overflow_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>&) { #ifdef BOOST_MATH_NO_EXCEPTIONS static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set."); #else raise_error(function, message ? message : "numeric overflow"); // We should never get here: - return boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : boost::math::tools::max_value(); + return BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : BOOST_MATH_NAMESPACE::tools::max_value(); #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_overflow_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::overflow_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>&) { #ifdef BOOST_MATH_NO_EXCEPTIONS static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set."); #else raise_error(function, message ? message : "numeric overflow", val); // We should never get here: - return boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : boost::math::tools::max_value(); + return BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : BOOST_MATH_NAMESPACE::tools::max_value(); #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error( const char* , const char* , - const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::overflow_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: - return boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : boost::math::tools::max_value(); + return BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : BOOST_MATH_NAMESPACE::tools::max_value(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error( const char* , const char* , const T&, - const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::overflow_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: - return boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : boost::math::tools::max_value(); + return BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : BOOST_MATH_NAMESPACE::tools::max_value(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_overflow_error( const char* , const char* , - const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::overflow_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) { errno = ERANGE; // This may or may not do the right thing, but the user asked for the error // to be silent so here we go anyway: - return boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : boost::math::tools::max_value(); + return BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : BOOST_MATH_NAMESPACE::tools::max_value(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_overflow_error( const char* , const char* , const T&, - const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::overflow_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) { errno = ERANGE; // This may or may not do the right thing, but the user asked for the error // to be silent so here we go anyway: - return boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : boost::math::tools::max_value(); + return BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : BOOST_MATH_NAMESPACE::tools::max_value(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_overflow_error( const char* function, const char* message, - const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&) + const ::BOOST_MATH_NAMESPACE::policies::overflow_error< ::BOOST_MATH_NAMESPACE::policies::user_error>&) { - return user_overflow_error(function, message, boost::math::numeric_limits::infinity()); + return user_overflow_error(function, message, BOOST_MATH_NAMESPACE::numeric_limits::infinity()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_overflow_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&) + const ::BOOST_MATH_NAMESPACE::policies::overflow_error< ::BOOST_MATH_NAMESPACE::policies::user_error>&) { std::string m(message ? message : ""); std::string sval = prec_format(val); replace_all_in_string(m, "%1%", sval.c_str()); - return user_overflow_error(function, m.c_str(), boost::math::numeric_limits::infinity()); + return user_overflow_error(function, m.c_str(), BOOST_MATH_NAMESPACE::numeric_limits::infinity()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_underflow_error( const char* function, const char* message, - const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::underflow_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>&) { #ifdef BOOST_MATH_NO_EXCEPTIONS static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set."); @@ -433,22 +441,22 @@ BOOST_MATH_GPU_ENABLED inline T raise_underflow_error( #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error( const char* , const char* , - const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::underflow_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: return T(0); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_underflow_error( const char* /* function */, const char* /* message */, - const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::underflow_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) { errno = ERANGE; // This may or may not do the right thing, but the user asked for the error @@ -456,21 +464,21 @@ BOOST_MATH_GPU_ENABLED inline T raise_underflow_error( return T(0); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_underflow_error( const char* function, const char* message, - const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&) + const ::BOOST_MATH_NAMESPACE::policies::underflow_error< ::BOOST_MATH_NAMESPACE::policies::user_error>&) { return user_underflow_error(function, message, T(0)); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_denorm_error( const char* function, const char* message, const T& /* val */, - const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::denorm_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>&) { #ifdef BOOST_MATH_NO_EXCEPTIONS static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set."); @@ -481,24 +489,24 @@ BOOST_MATH_GPU_ENABLED inline T raise_denorm_error( #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline constexpr T raise_denorm_error( const char* , const char* , const T& val, - const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::denorm_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: return val; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_denorm_error( const char* , const char* , const T& val, - const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::denorm_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) { errno = ERANGE; // This may or may not do the right thing, but the user asked for the error @@ -506,50 +514,50 @@ BOOST_MATH_GPU_ENABLED inline T raise_denorm_error( return val; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_denorm_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&) + const ::BOOST_MATH_NAMESPACE::policies::denorm_error< ::BOOST_MATH_NAMESPACE::policies::user_error>&) { return user_denorm_error(function, message, val); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::evaluation_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>&) { #ifdef BOOST_MATH_NO_EXCEPTIONS static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set."); #else - raise_error(function, message, val); + raise_error(function, message, val); // we never get here: return T(0); #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error( const char* , const char* , const T& val, - const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::evaluation_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: return val; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error( const char* , const char* , const T& val, - const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::evaluation_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) { errno = EDOM; // This may or may not do the right thing, but the user asked for the error @@ -557,109 +565,109 @@ BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error( return val; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_evaluation_error( const char* function, const char* message, const T& val, - const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&) + const ::BOOST_MATH_NAMESPACE::policies::evaluation_error< ::BOOST_MATH_NAMESPACE::policies::user_error>&) { return user_evaluation_error(function, message, val); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline TargetType raise_rounding_error( const char* function, const char* message, const T& val, const TargetType&, - const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::rounding_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>&) { #ifdef BOOST_MATH_NO_EXCEPTIONS static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set."); #else - raise_error(function, message, val); + raise_error(function, message, val); // we never get here: return TargetType(0); #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error( const char* , const char* , const T& val, const TargetType&, - const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::rounding_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: - static_assert(boost::math::numeric_limits::is_specialized, "The target type must have std::numeric_limits specialized."); - return val > 0 ? (boost::math::numeric_limits::max)() : (boost::math::numeric_limits::is_integer ? (boost::math::numeric_limits::min)() : -(boost::math::numeric_limits::max)()); + static_assert(BOOST_MATH_NAMESPACE::numeric_limits::is_specialized, "The target type must have std::numeric_limits specialized."); + return val > 0 ? (BOOST_MATH_NAMESPACE::numeric_limits::max)() : (BOOST_MATH_NAMESPACE::numeric_limits::is_integer ? (BOOST_MATH_NAMESPACE::numeric_limits::min)() : -(BOOST_MATH_NAMESPACE::numeric_limits::max)()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline TargetType raise_rounding_error( const char* , const char* , const T& val, const TargetType&, - const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::rounding_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T) { errno = ERANGE; // This may or may not do the right thing, but the user asked for the error // to be silent so here we go anyway: - static_assert(boost::math::numeric_limits::is_specialized, "The target type must have std::numeric_limits specialized."); - return val > 0 ? (boost::math::numeric_limits::max)() : (boost::math::numeric_limits::is_integer ? (boost::math::numeric_limits::min)() : -(boost::math::numeric_limits::max)()); + static_assert(BOOST_MATH_NAMESPACE::numeric_limits::is_specialized, "The target type must have std::numeric_limits specialized."); + return val > 0 ? (BOOST_MATH_NAMESPACE::numeric_limits::max)() : (BOOST_MATH_NAMESPACE::numeric_limits::is_integer ? (BOOST_MATH_NAMESPACE::numeric_limits::min)() : -(BOOST_MATH_NAMESPACE::numeric_limits::max)()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline TargetType raise_rounding_error( const char* function, const char* message, const T& val, const TargetType& t, - const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&) + const ::BOOST_MATH_NAMESPACE::policies::rounding_error< ::BOOST_MATH_NAMESPACE::policies::user_error>&) { return user_rounding_error(function, message, val, t); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error( const char* function, const char* message, const T& val, const R& , - const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::indeterminate_result_error< ::BOOST_MATH_NAMESPACE::policies::throw_on_error>&) { #ifdef BOOST_MATH_NO_EXCEPTIONS static_assert(sizeof(T) == 0, "Error handler called with throw_on_error and BOOST_MATH_NO_EXCEPTIONS set."); #else raise_error(function, message, val); // we never get here: - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline constexpr T raise_indeterminate_result_error( const char* , const char* , const T& , const R& result, - const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) + const ::BOOST_MATH_NAMESPACE::policies::indeterminate_result_error< ::BOOST_MATH_NAMESPACE::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T) { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error( const char* , const char* , const T& , const R& result, - const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&) + const ::BOOST_MATH_NAMESPACE::policies::indeterminate_result_error< ::BOOST_MATH_NAMESPACE::policies::errno_on_error>&) { errno = EDOM; // This may or may not do the right thing, but the user asked for the error @@ -667,20 +675,20 @@ BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error( return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T raise_indeterminate_result_error( const char* function, const char* message, const T& val, const R& , - const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&) + const ::BOOST_MATH_NAMESPACE::policies::indeterminate_result_error< ::BOOST_MATH_NAMESPACE::policies::user_error>&) { return user_indeterminate_result_error(function, message, val); } } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T)) { typedef typename Policy::domain_error_type policy_type; @@ -689,7 +697,7 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error(const char* function, cons val, policy_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T)) { typedef typename Policy::pole_error_type policy_type; @@ -698,7 +706,7 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error(const char* function, const val, policy_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(const char* function, const char* message, const Policy&) noexcept(is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T)) { typedef typename Policy::overflow_error_type policy_type; @@ -707,7 +715,7 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(const char* function, co policy_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T)) { typedef typename Policy::overflow_error_type policy_type; @@ -716,7 +724,7 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error(const char* function, co val, policy_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error(const char* function, const char* message, const Policy&) noexcept(is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T)) { typedef typename Policy::underflow_error_type policy_type; @@ -725,7 +733,7 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error(const char* function, c policy_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T)) { typedef typename Policy::denorm_error_type policy_type; @@ -735,7 +743,7 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_denorm_error(const char* function, cons policy_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&) noexcept(is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T)) { typedef typename Policy::evaluation_error_type policy_type; @@ -744,7 +752,7 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error(const char* function, val, policy_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&) noexcept(is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T)) { typedef typename Policy::rounding_error_type policy_type; @@ -753,7 +761,7 @@ BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error(const char* fun val, t, policy_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&) noexcept(is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T)) { typedef typename Policy::indeterminate_result_error_type policy_type; @@ -768,64 +776,70 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_indeterminate_result_error(const char* namespace detail { -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_overflow(T val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error)) { BOOST_MATH_STD_USING if(fabs(val) > tools::max_value()) { - boost::math::policies::detail::raise_overflow_error(function, nullptr, pol); + BOOST_MATH_NAMESPACE::policies::detail::raise_overflow_error(function, nullptr, pol); *result = static_cast(val); return true; } return false; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_overflow(std::complex val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error)) { typedef typename R::value_type r_type; - r_type re, im; + // Start from the converted value: the checks below only write to a component that fails, + // and reading the other one uninitialized is undefined behaviour. + r_type re = static_cast(val.real()), im = static_cast(val.imag()); bool r = check_overflow(val.real(), &re, function, pol); r = check_overflow(val.imag(), &im, function, pol) || r; *result = R(re, im); return r; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_underflow(T val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error)) { if((val != 0) && (static_cast(val) == 0)) { - *result = static_cast(boost::math::policies::detail::raise_underflow_error(function, nullptr, pol)); + *result = static_cast(BOOST_MATH_NAMESPACE::policies::detail::raise_underflow_error(function, nullptr, pol)); return true; } return false; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_underflow(std::complex val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error)) { typedef typename R::value_type r_type; - r_type re, im; + // Start from the converted value: the checks below only write to a component that fails, + // and reading the other one uninitialized is undefined behaviour. + r_type re = static_cast(val.real()), im = static_cast(val.imag()); bool r = check_underflow(val.real(), &re, function, pol); r = check_underflow(val.imag(), &im, function, pol) || r; *result = R(re, im); return r; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_denorm(T val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error)) { BOOST_MATH_STD_USING if((fabs(val) < static_cast(tools::min_value())) && (static_cast(val) != 0)) { - *result = static_cast(boost::math::policies::detail::raise_denorm_error(function, 0, static_cast(val), pol)); + *result = static_cast(BOOST_MATH_NAMESPACE::policies::detail::raise_denorm_error(function, 0, static_cast(val), pol)); return true; } return false; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE bool check_denorm(std::complex val, R* result, const char* function, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error)) { typedef typename R::value_type r_type; - r_type re, im; + // Start from the converted value: the checks below only write to a component that fails, + // and reading the other one uninitialized is undefined behaviour. + r_type re = static_cast(val.real()), im = static_cast(val.imag()); bool r = check_denorm(val.real(), &re, function, pol); r = check_denorm(val.imag(), &im, function, pol) || r; *result = R(re, im); @@ -854,7 +868,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE constexpr bool check_denorm(std::c } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE R checked_narrowing_cast(T val, const char* function) noexcept(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy::value) { typedef typename Policy::overflow_error_type overflow_type; @@ -863,7 +877,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE R checked_narrowing_cast(T val, co // // Most of what follows will evaluate to a no-op: // - R result = 0; + R result = R(0); if(detail::check_overflow(val, &result, function, overflow_type())) return result; if(detail::check_underflow(val, &result, function, underflow_type())) @@ -874,7 +888,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE R checked_narrowing_cast(T val, co return static_cast(val); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline void check_series_iterations(const char* function, std::uintmax_t max_iter, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy::value) { if(max_iter >= policies::get_max_series_iterations()) @@ -883,7 +897,7 @@ BOOST_MATH_GPU_ENABLED inline void check_series_iterations(const char* function, "Series evaluation exceeded %1% iterations, giving up now.", static_cast(static_cast(max_iter)), pol); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline void check_root_iterations(const char* function, std::uintmax_t max_iter, const Policy& pol) noexcept(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy::value) { if(max_iter >= policies::get_max_root_iterations()) @@ -898,15 +912,14 @@ BOOST_MATH_GPU_ENABLED inline void check_root_iterations(const char* function, s # pragma warning(pop) #endif -}} // namespaces boost/math +BOOST_MATH_NAMESPACE_END // namespaces boost/math #else // Special values for NVRTC -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace policies { -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error( const char* , const char* , @@ -915,20 +928,20 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_domain_error( { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_pole_error( const char* function, const char* message, const T& val, const Policy&) BOOST_MATH_NOEXCEPT(T) { - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error( const char* , const char* , @@ -936,10 +949,10 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error( { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: - return boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : (boost::math::numeric_limits::max)(); + return BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : (BOOST_MATH_NAMESPACE::numeric_limits::max)(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error( const char* , const char* , @@ -948,10 +961,10 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_overflow_error( { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: - return boost::math::numeric_limits::has_infinity ? boost::math::numeric_limits::infinity() : (boost::math::numeric_limits::max)(); + return BOOST_MATH_NAMESPACE::numeric_limits::has_infinity ? BOOST_MATH_NAMESPACE::numeric_limits::infinity() : (BOOST_MATH_NAMESPACE::numeric_limits::max)(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error( const char* , const char* , @@ -962,7 +975,7 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_underflow_error( return static_cast(0); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline constexpr T raise_denorm_error( const char* , const char* , @@ -974,7 +987,7 @@ BOOST_MATH_GPU_ENABLED inline constexpr T raise_denorm_error( return val; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error( const char* , const char* , @@ -986,7 +999,7 @@ BOOST_MATH_GPU_ENABLED constexpr T raise_evaluation_error( return val; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error( const char* , const char* , @@ -996,11 +1009,11 @@ BOOST_MATH_GPU_ENABLED constexpr TargetType raise_rounding_error( { // This may or may not do the right thing, but the user asked for the error // to be ignored so here we go anyway: - static_assert(boost::math::numeric_limits::is_specialized, "The target type must have std::numeric_limits specialized."); - return val > 0 ? (boost::math::numeric_limits::max)() : (boost::math::numeric_limits::is_integer ? (boost::math::numeric_limits::min)() : -(boost::math::numeric_limits::max)()); + static_assert(BOOST_MATH_NAMESPACE::numeric_limits::is_specialized, "The target type must have std::numeric_limits specialized."); + return val > 0 ? (BOOST_MATH_NAMESPACE::numeric_limits::max)() : (BOOST_MATH_NAMESPACE::numeric_limits::is_integer ? (BOOST_MATH_NAMESPACE::numeric_limits::min)() : -(BOOST_MATH_NAMESPACE::numeric_limits::max)()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline constexpr T raise_indeterminate_result_error( const char* , const char* , @@ -1013,15 +1026,15 @@ BOOST_MATH_GPU_ENABLED inline constexpr T raise_indeterminate_result_error( return result; } -template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE R checked_narrowing_cast(T val, const char* function) noexcept(boost::math::is_floating_point_v && boost::math::is_floating_point_v) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE R checked_narrowing_cast(T val, const char* function) noexcept(BOOST_MATH_NAMESPACE::is_floating_point_v && BOOST_MATH_NAMESPACE::is_floating_point_v) { // We only have ignore error policy so no reason to check return static_cast(val); } -template -BOOST_MATH_GPU_ENABLED inline void check_series_iterations(const char* function, boost::math::uintmax_t max_iter, const Policy& pol) noexcept(boost::math::is_floating_point_v) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline void check_series_iterations(const char* function, BOOST_MATH_NAMESPACE::uintmax_t max_iter, const Policy& pol) noexcept(BOOST_MATH_NAMESPACE::is_floating_point_v) { if(max_iter >= policies::get_max_series_iterations()) raise_evaluation_error( @@ -1029,8 +1042,8 @@ BOOST_MATH_GPU_ENABLED inline void check_series_iterations(const char* function, "Series evaluation exceeded %1% iterations, giving up now.", static_cast(static_cast(max_iter)), pol); } -template -BOOST_MATH_GPU_ENABLED inline void check_root_iterations(const char* function, boost::math::uintmax_t max_iter, const Policy& pol) noexcept(boost::math::is_floating_point_v) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline void check_root_iterations(const char* function, BOOST_MATH_NAMESPACE::uintmax_t max_iter, const Policy& pol) noexcept(BOOST_MATH_NAMESPACE::is_floating_point_v) { if(max_iter >= policies::get_max_root_iterations()) raise_evaluation_error( @@ -1039,24 +1052,23 @@ BOOST_MATH_GPU_ENABLED inline void check_root_iterations(const char* function, b } } // namespace policies -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC -namespace boost { namespace math { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // // Simple helper function to assist in returning a pair from a single value, // that value usually comes from one of the error handlers above: // template -BOOST_MATH_GPU_ENABLED boost::math::pair pair_from_single(const T& val) BOOST_MATH_NOEXCEPT(T) +BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::pair pair_from_single(const T& val) BOOST_MATH_NOEXCEPT(T) { - return boost::math::make_pair(val, val); + return BOOST_MATH_NAMESPACE::make_pair(val, val); } -}}} // boost::math::detail +} BOOST_MATH_NAMESPACE_END // boost::math::detail #endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP diff --git a/include/boost/math/policies/policy.hpp b/include/boost/math/policies/policy.hpp index 6d80b2b292..b233f8f914 100644 --- a/include/boost/math/policies/policy.hpp +++ b/include/boost/math/policies/policy.hpp @@ -13,16 +13,16 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace mp = tools::meta_programming; namespace tools{ -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept; -template -BOOST_MATH_GPU_ENABLED constexpr T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value); +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED constexpr T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value); } @@ -111,14 +111,16 @@ namespace policies{ #define BOOST_MATH_PROMOTE_FLOAT_POLICY true #endif #ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY -#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +// long double is slow almost everywhere (x87 on x86, software emulated 128 bit +// on AArch64), so double is not promoted to it by default. Define +// BOOST_MATH_PROMOTE_DOUBLE_POLICY as true to get the old behaviour. #define BOOST_MATH_PROMOTE_DOUBLE_POLICY false -#else -#define BOOST_MATH_PROMOTE_DOUBLE_POLICY true -#endif #endif #ifndef BOOST_MATH_DISCRETE_QUANTILE_POLICY -#define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_round_outwards +// The smallest k with cdf(k) >= p, as R, SciPy, Julia and Mathematica define +// it. Define BOOST_MATH_DISCRETE_QUANTILE_POLICY as integer_round_outwards to +// get the old behaviour. +#define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_round_up #endif #ifndef BOOST_MATH_ASSERT_UNDEFINED_POLICY #define BOOST_MATH_ASSERT_UNDEFINED_POLICY true @@ -131,8 +133,8 @@ namespace policies{ #endif #define BOOST_MATH_META_INT(Type, name, Default) \ - template \ - class name : public boost::math::integral_constant { }; \ + BOOST_MATH_EXPORT template \ + class name : public BOOST_MATH_NAMESPACE::integral_constant { }; \ \ namespace detail{ \ template \ @@ -151,17 +153,17 @@ namespace policies{ }; \ } \ \ - template \ + BOOST_MATH_EXPORT template \ class is_##name \ { \ public: \ - static constexpr bool value = boost::math::policies::detail::is_##name##_imp::value; \ - using type = boost::math::integral_constant; \ + static constexpr bool value = BOOST_MATH_NAMESPACE::policies::detail::is_##name##_imp::value; \ + using type = BOOST_MATH_NAMESPACE::integral_constant; \ }; #define BOOST_MATH_META_BOOL(name, Default) \ - template \ - class name : public boost::math::integral_constant{}; \ + BOOST_MATH_EXPORT template \ + class name : public BOOST_MATH_NAMESPACE::integral_constant{}; \ \ namespace detail{ \ template \ @@ -180,18 +182,18 @@ namespace policies{ }; \ } \ \ - template \ + BOOST_MATH_EXPORT template \ class is_##name \ { \ public: \ - static constexpr bool value = boost::math::policies::detail::is_##name##_imp::value; \ - using type = boost::math::integral_constant; \ + static constexpr bool value = BOOST_MATH_NAMESPACE::policies::detail::is_##name##_imp::value; \ + using type = BOOST_MATH_NAMESPACE::integral_constant; \ }; // // Begin by defining policy types for error handling: // -enum error_policy_type +BOOST_MATH_EXPORT enum error_policy_type { throw_on_error = 0, errno_on_error = 1, @@ -217,7 +219,7 @@ BOOST_MATH_META_BOOL(assert_undefined, BOOST_MATH_ASSERT_UNDEFINED_POLICY) // // Policy types for discrete quantiles: // -enum discrete_quantile_policy_type +BOOST_MATH_EXPORT enum discrete_quantile_policy_type { real, integer_round_outwards, @@ -245,7 +247,7 @@ BOOST_MATH_META_INT(unsigned long, max_root_iterations, BOOST_MATH_MAX_ROOT_ITER BOOST_PARAMETER_TEMPLATE_KEYWORD(name##_name)\ BOOST_PARAMETER_NAME(name##_name) -struct default_policy{}; +BOOST_MATH_EXPORT struct default_policy{}; namespace detail{ // @@ -257,18 +259,18 @@ struct precision // // Now work out the precision: // - using digits2_type = typename boost::math::conditional< + using digits2_type = typename BOOST_MATH_NAMESPACE::conditional< (Digits10::value == 0), digits2<0>, digits2<((Digits10::value + 1) * 1000L) / 301L> >::type; public: #ifdef BOOST_BORLANDC - using type = typename boost::math::conditional< - (Digits2::value > ::boost::math::policies::detail::precision::digits2_type::value), + using type = typename BOOST_MATH_NAMESPACE::conditional< + (Digits2::value > ::BOOST_MATH_NAMESPACE::policies::detail::precision::digits2_type::value), Digits2, digits2_type>::type; #else - using type = typename boost::math::conditional< + using type = typename BOOST_MATH_NAMESPACE::conditional< (Digits2::value > digits2_type::value), Digits2, digits2_type>::type; #endif @@ -283,29 +285,29 @@ template class is_valid_policy_imp { public: - static constexpr bool value = sizeof(boost::math::policies::detail::test_is_valid_arg(static_cast(nullptr))) == sizeof(char); + static constexpr bool value = sizeof(BOOST_MATH_NAMESPACE::policies::detail::test_is_valid_arg(static_cast(nullptr))) == sizeof(char); }; template class is_valid_policy { public: - static constexpr bool value = boost::math::policies::detail::is_valid_policy_imp::value; + static constexpr bool value = BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy_imp::value; }; template class is_default_policy_imp { public: - static constexpr bool value = sizeof(boost::math::policies::detail::test_is_default_arg(static_cast(nullptr))) == sizeof(char); + static constexpr bool value = sizeof(BOOST_MATH_NAMESPACE::policies::detail::test_is_default_arg(static_cast(nullptr))) == sizeof(char); }; template class is_default_policy { public: - static constexpr bool value = boost::math::policies::detail::is_default_policy_imp::value; - using type = boost::math::integral_constant; + static constexpr bool value = BOOST_MATH_NAMESPACE::policies::detail::is_default_policy_imp::value; + using type = BOOST_MATH_NAMESPACE::integral_constant; template struct apply @@ -314,7 +316,7 @@ class is_default_policy }; }; -template +template struct append_N { using type = typename append_N, T, N-1>::type; @@ -367,7 +369,7 @@ typedef default_args::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); - static_assert(::boost::math::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); + static_assert(::BOOST_MATH_NAMESPACE::policies::detail::is_valid_policy::value, "::boost::math::policies::detail::is_valid_policy::value"); // // Typelist of the arguments: // using arg_list = mp::mp_list; - static constexpr boost::math::size_t arg_list_size = mp::mp_size::value; + static constexpr BOOST_MATH_NAMESPACE::size_t arg_list_size = mp::mp_size::value; template struct pick_arg @@ -491,6 +493,8 @@ class policy; }; +// When neither float nor double is promoted, policy<> already is the forwarding policy: +#if BOOST_MATH_PROMOTE_FLOAT_POLICY || BOOST_MATH_PROMOTE_DOUBLE_POLICY template <> struct policy { @@ -515,8 +519,9 @@ struct policy; using max_root_iterations_type = max_root_iterations<>; }; +#endif -template ; - static constexpr boost::math::size_t arg_list_size = mp::mp_size::value; + static constexpr BOOST_MATH_NAMESPACE::size_t arg_list_size = mp::mp_size::value; template struct pick_arg @@ -648,6 +653,7 @@ struct normalise, using type = policy; }; +#if BOOST_MATH_PROMOTE_FLOAT_POLICY || BOOST_MATH_PROMOTE_DOUBLE_POLICY template <> struct normalise, promote_float, @@ -664,81 +670,82 @@ struct normalise, { using type = policy; }; +#endif -BOOST_MATH_GPU_ENABLED constexpr policy<> make_policy() noexcept +BOOST_MATH_EXPORT BOOST_MATH_GPU_ENABLED constexpr policy<> make_policy() noexcept { return {}; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1>::type make_policy(const A1&) noexcept { typedef typename normalise, A1>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2>::type make_policy(const A1&, const A2&) noexcept { typedef typename normalise, A1, A2>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&) noexcept { typedef typename normalise, A1, A2, A3>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&) noexcept { typedef typename normalise, A1, A2, A3, A4>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3, A4, A5>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&) noexcept { typedef typename normalise, A1, A2, A3, A4, A5>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&) noexcept { typedef typename normalise, A1, A2, A3, A4, A5, A6>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3, A4, A5, A6, A7>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&) noexcept { typedef typename normalise, A1, A2, A3, A4, A5, A6, A7>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3, A4, A5, A6, A7, A8>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&) noexcept { typedef typename normalise, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&) noexcept { typedef typename normalise, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&) noexcept { typedef typename normalise, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type result_type; return result_type(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&, const A11&) noexcept { typedef typename normalise, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type result_type; @@ -748,7 +755,7 @@ BOOST_MATH_GPU_ENABLED constexpr typename normalise, A1, A2, A3, A4, A5 // // Traits class to handle internal promotion: // -template +BOOST_MATH_EXPORT template struct evaluation { typedef Real type; @@ -757,50 +764,50 @@ struct evaluation template struct evaluation { - using type = typename boost::math::conditional::type; + using type = typename BOOST_MATH_NAMESPACE::conditional::type; }; template struct evaluation { - using type = typename boost::math::conditional::type; + using type = typename BOOST_MATH_NAMESPACE::conditional::type; }; -template +BOOST_MATH_EXPORT template using evaluation_t = typename evaluation::type; -template +BOOST_MATH_EXPORT template struct precision { - static_assert((boost::math::numeric_limits::radix == 2) || ((boost::math::numeric_limits::is_specialized == 0) || (boost::math::numeric_limits::digits == 0)), + static_assert((BOOST_MATH_NAMESPACE::numeric_limits::radix == 2) || ((BOOST_MATH_NAMESPACE::numeric_limits::is_specialized == 0) || (BOOST_MATH_NAMESPACE::numeric_limits::digits == 0)), "(boost::math::numeric_limits::radix == 2) || ((boost::math::numeric_limits::is_specialized == 0) || (boost::math::numeric_limits::digits == 0))"); #ifndef BOOST_BORLANDC using precision_type = typename Policy::precision_type; - using type = typename boost::math::conditional< - ((boost::math::numeric_limits::is_specialized == 0) || (boost::math::numeric_limits::digits == 0)), + using type = typename BOOST_MATH_NAMESPACE::conditional< + ((BOOST_MATH_NAMESPACE::numeric_limits::is_specialized == 0) || (BOOST_MATH_NAMESPACE::numeric_limits::digits == 0)), // Possibly unknown precision: precision_type, - typename boost::math::conditional< - ((boost::math::numeric_limits::digits <= precision_type::value) + typename BOOST_MATH_NAMESPACE::conditional< + ((BOOST_MATH_NAMESPACE::numeric_limits::digits <= precision_type::value) || (Policy::precision_type::value <= 0)), // Default case, full precision for RealType: - digits2< boost::math::numeric_limits::digits>, + digits2< BOOST_MATH_NAMESPACE::numeric_limits::digits>, // User customised precision: precision_type >::type >::type; #else using precision_type = typename Policy::precision_type; - using digits_t = boost::math::integral_constant::digits>; - using spec_t = boost::math::integral_constant::is_specialized>; - using type = typename boost::math::conditional< - (spec_t::value == true boost::math::true_type || digits_t::value == 0), + using digits_t = BOOST_MATH_NAMESPACE::integral_constant::digits>; + using spec_t = BOOST_MATH_NAMESPACE::integral_constant::is_specialized>; + using type = typename BOOST_MATH_NAMESPACE::conditional< + (spec_t::value == true BOOST_MATH_NAMESPACE::true_type || digits_t::value == 0), // Possibly unknown precision: precision_type, - typename boost::math::conditional< + typename BOOST_MATH_NAMESPACE::conditional< (digits_t::value <= precision_type::value || precision_type::value <= 0), // Default case, full precision for RealType: - digits2< boost::math::numeric_limits::digits>, + digits2< BOOST_MATH_NAMESPACE::numeric_limits::digits>, // User customised precision: precision_type >::type @@ -813,7 +820,7 @@ struct precision template struct precision { - typedef boost::math::integral_constant type; + typedef BOOST_MATH_NAMESPACE::integral_constant type; }; #endif @@ -821,41 +828,41 @@ struct precision namespace detail{ template -BOOST_MATH_GPU_ENABLED constexpr int digits_imp(boost::math::true_type const&) noexcept +BOOST_MATH_GPU_ENABLED constexpr int digits_imp(BOOST_MATH_NAMESPACE::true_type const&) noexcept { - static_assert( boost::math::numeric_limits::is_specialized, "boost::math::numeric_limits::is_specialized"); - typedef typename boost::math::policies::precision::type p_t; + static_assert( BOOST_MATH_NAMESPACE::numeric_limits::is_specialized, "boost::math::numeric_limits::is_specialized"); + typedef typename BOOST_MATH_NAMESPACE::policies::precision::type p_t; return p_t::value; } template -BOOST_MATH_GPU_ENABLED constexpr int digits_imp(boost::math::false_type const&) noexcept +BOOST_MATH_GPU_ENABLED constexpr int digits_imp(BOOST_MATH_NAMESPACE::false_type const&) noexcept { return tools::digits(); } } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept { - typedef boost::math::integral_constant::is_specialized > tag_type; + typedef BOOST_MATH_NAMESPACE::integral_constant::is_specialized > tag_type; return detail::digits_imp(tag_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr int digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept { - return boost::math::policies::digits() * 301 / 1000L; + return BOOST_MATH_NAMESPACE::policies::digits() * 301 / 1000L; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr unsigned long get_max_series_iterations() noexcept { typedef typename Policy::max_series_iterations_type iter_type; return iter_type::value; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr unsigned long get_max_root_iterations() noexcept { typedef typename Policy::max_root_iterations_type iter_type; @@ -867,61 +874,61 @@ namespace detail{ template struct series_factor_calc { - BOOST_MATH_GPU_ENABLED static T get() noexcept(boost::math::is_floating_point::value) + BOOST_MATH_GPU_ENABLED static T get() noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return ldexp(T(1.0), 1 - Digits::value); } }; template -struct series_factor_calc +struct series_factor_calc { - BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(boost::math::is_floating_point::value) + BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { - return boost::math::tools::epsilon(); + return BOOST_MATH_NAMESPACE::tools::epsilon(); } }; template -struct series_factor_calc +struct series_factor_calc { - BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(boost::math::is_floating_point::value) + BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { - return 1 / static_cast(static_cast(1u) << (Digits::value - 1)); + return 1 / static_cast(static_cast(1u) << (Digits::value - 1)); } }; template -struct series_factor_calc +struct series_factor_calc { - BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(boost::math::is_floating_point::value) + BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { - return boost::math::tools::epsilon(); + return BOOST_MATH_NAMESPACE::tools::epsilon(); } }; template -BOOST_MATH_GPU_ENABLED constexpr T get_epsilon_imp(boost::math::true_type const&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED constexpr T get_epsilon_imp(BOOST_MATH_NAMESPACE::true_type const&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { - static_assert(boost::math::numeric_limits::is_specialized, "boost::math::numeric_limits::is_specialized"); - static_assert(boost::math::numeric_limits::radix == 2, "boost::math::numeric_limits::radix == 2"); + static_assert(BOOST_MATH_NAMESPACE::numeric_limits::is_specialized, "boost::math::numeric_limits::is_specialized"); + static_assert(BOOST_MATH_NAMESPACE::numeric_limits::radix == 2, "boost::math::numeric_limits::radix == 2"); - typedef typename boost::math::policies::precision::type p_t; - typedef boost::math::integral_constant::digits> is_small_int; - typedef boost::math::integral_constant= boost::math::numeric_limits::digits> is_default_value; + typedef typename BOOST_MATH_NAMESPACE::policies::precision::type p_t; + typedef BOOST_MATH_NAMESPACE::integral_constant::digits> is_small_int; + typedef BOOST_MATH_NAMESPACE::integral_constant= BOOST_MATH_NAMESPACE::numeric_limits::digits> is_default_value; return series_factor_calc::get(); } template -BOOST_MATH_GPU_ENABLED constexpr T get_epsilon_imp(boost::math::false_type const&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED constexpr T get_epsilon_imp(BOOST_MATH_NAMESPACE::false_type const&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return tools::epsilon(); } } // namespace detail -template -BOOST_MATH_GPU_ENABLED constexpr T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED constexpr T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { - typedef boost::math::integral_constant::is_specialized && (boost::math::numeric_limits::radix == 2)) > tag_type; + typedef BOOST_MATH_NAMESPACE::integral_constant::is_specialized && (BOOST_MATH_NAMESPACE::numeric_limits::radix == 2)) > tag_type; return detail::get_epsilon_imp(tag_type()); } @@ -945,48 +952,48 @@ template class is_policy_imp { public: - static constexpr bool value = (sizeof(detail::test_is_policy(static_cast>*>(nullptr))) == sizeof(char)); + static constexpr bool value = (sizeof(detail::test_is_policy(static_cast>*>(nullptr))) == sizeof(char)); }; } -template +BOOST_MATH_EXPORT template class is_policy { public: - static constexpr bool value = boost::math::policies::detail::is_policy_imp

    ::value; - using type = boost::math::integral_constant; + static constexpr bool value = BOOST_MATH_NAMESPACE::policies::detail::is_policy_imp

    ::value; + using type = BOOST_MATH_NAMESPACE::integral_constant; }; -template +BOOST_MATH_EXPORT template BOOST_MATH_INLINE_CONSTEXPR bool is_policy_v = is_policy::value; // // Helper traits class for distribution error handling: // -template +BOOST_MATH_EXPORT template struct constructor_error_check { using domain_error_type = typename Policy::domain_error_type; - using type = typename boost::math::conditional< + using type = typename BOOST_MATH_NAMESPACE::conditional< (domain_error_type::value == throw_on_error) || (domain_error_type::value == user_error) || (domain_error_type::value == errno_on_error), - boost::math::true_type, - boost::math::false_type>::type; + BOOST_MATH_NAMESPACE::true_type, + BOOST_MATH_NAMESPACE::false_type>::type; }; -template +BOOST_MATH_EXPORT template struct method_error_check { using domain_error_type = typename Policy::domain_error_type; - using type = typename boost::math::conditional< + using type = typename BOOST_MATH_NAMESPACE::conditional< (domain_error_type::value == throw_on_error), - boost::math::false_type, - boost::math::true_type>::type; + BOOST_MATH_NAMESPACE::false_type, + BOOST_MATH_NAMESPACE::true_type>::type; }; // // Does the Policy ever throw on error? // -template +BOOST_MATH_EXPORT template struct is_noexcept_error_policy { typedef typename Policy::domain_error_type t1; @@ -1028,7 +1035,7 @@ struct make_forwarding_policy template using make_forwarding_policy_t = typename make_forwarding_policy::type; -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_POLICY_HPP diff --git a/include/boost/math/quadrature/detail/exp_sinh_detail.hpp b/include/boost/math/quadrature/detail/exp_sinh_detail.hpp index 77f2fbf060..257b07ae05 100644 --- a/include/boost/math/quadrature/detail/exp_sinh_detail.hpp +++ b/include/boost/math/quadrature/detail/exp_sinh_detail.hpp @@ -10,20 +10,25 @@ #include #ifndef BOOST_MATH_HAS_NVRTC +#include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include #include #ifdef BOOST_MATH_HAS_THREADS +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif -namespace boost{ namespace math{ namespace quadrature { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail{ // Returns the exp-sinh quadrature of a function f over the open interval (0, infinity) @@ -49,6 +54,8 @@ class exp_sinh_detail template auto integrate(const F& f, Real* error, Real* L1, const char* function, Real tolerance, std::size_t* levels) const ->decltype(std::declval()(std::declval())); + template + auto integrate(const F& f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real* error, Real* L1, const char* function, Real tolerance, std::size_t* levels) const ->decltype(std::declval()(std::declval())); private: const std::vector& get_abscissa_row(std::size_t n)const @@ -111,7 +118,7 @@ class exp_sinh_detail Real h = ldexp(static_cast(1), -static_cast(row)); const Real t_max = m_t_min + m_abscissas[0].size() - 1; - size_t k = static_cast(boost::math::lltrunc(ceil((t_max - m_t_min) / (2 * h)))); + size_t k = static_cast(BOOST_MATH_NAMESPACE::lltrunc(ceil((t_max - m_t_min) / (2 * h)))); m_abscissas[row].reserve(k); m_weights[row].reserve(k); Real arg = m_t_min; @@ -134,7 +141,7 @@ class exp_sinh_detail mutable std::vector> m_weights; std::size_t m_max_refinements; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - mutable boost::math::detail::atomic_unsigned_type m_committed_refinements{}; + mutable BOOST_MATH_NAMESPACE::detail::atomic_unsigned_type m_committed_refinements{}; mutable std::mutex m_mutex; #else mutable unsigned m_committed_refinements; @@ -158,8 +165,8 @@ auto exp_sinh_detail::integrate(const F& f, Real* error, Real* L1, using std::tanh; using std::sinh; using std::sqrt; - using boost::math::constants::half; - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::constants::half_pi; // This provided a nice error message for real valued integrals, but it's super awkward for complex-valued integrals: /*K y_max = f(tools::max_value()); @@ -172,7 +179,7 @@ auto exp_sinh_detail::integrate(const F& f, Real* error, Real* L1, //std::cout << std::setprecision(5*std::numeric_limits::digits10); // Get the party started with two estimates of the integral: - Real min_abscissa{ 0 }, max_abscissa{ boost::math::tools::max_value() }; + Real min_abscissa{ 0 }, max_abscissa{ BOOST_MATH_NAMESPACE::tools::max_value() }; K I0 = 0; Real L1_I0 = 0; for(size_t i = 0; i < m_abscissas[0].size(); ++i) @@ -222,7 +229,7 @@ auto exp_sinh_detail::integrate(const F& f, Real* error, Real* L1, // We failed to find anything, is the integral zero, or have we just not found it yet? // We'll try one more level, if that still finds nothing then it'll terminate. min_abscissa = 0; - max_abscissa = boost::math::tools::max_value(); + max_abscissa = BOOST_MATH_NAMESPACE::tools::max_value(); } I1 *= half(); @@ -263,7 +270,7 @@ auto exp_sinh_detail::integrate(const F& f, Real* error, Real* L1, err = abs(I0 - I1); //std::cout << "Estimate: " << I1 << " Error estimate at level " << i << " = " << err << std::endl; // Use L1_I1 here to make it work with both complex and real valued integrands: - if (!(boost::math::isfinite)(L1_I1)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(L1_I1)) { return static_cast(policies::raise_evaluation_error(function, "The exp_sinh quadrature evaluated your function at a singular point and returned %1%. Please ensure your function evaluates to a finite number over its entire domain.", I1, Policy())); } @@ -291,6 +298,144 @@ auto exp_sinh_detail::integrate(const F& f, Real* error, Real* L1, return I1; } +template +template +auto exp_sinh_detail::integrate(const F& f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real* error, Real* L1, const char* function, Real tolerance, std::size_t* levels) const ->decltype(std::declval()(std::declval())) +{ + const auto magnitude = [&](const decltype(std::declval()(std::declval()))& value) -> Real { return static_cast(norm(value)); }; + typedef decltype(f(static_cast(0))) K; + using std::abs; + using std::floor; + using std::tanh; + using std::sinh; + using std::sqrt; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::constants::half_pi; + + + //std::cout << std::setprecision(5*std::numeric_limits::digits10); + + // Get the party started with two estimates of the integral: + Real min_abscissa{ 0 }, max_abscissa{ BOOST_MATH_NAMESPACE::tools::max_value() }; + K I0 = zero; + Real L1_I0 = 0; + for(size_t i = 0; i < m_abscissas[0].size(); ++i) + { + K y = f(m_abscissas[0][i]); + K I0_last = I0; + I0 += y*m_weights[0][i]; + L1_I0 += magnitude(y)*m_weights[0][i]; + if ((magnitude(I0_last - I0) == 0) && (magnitude(I0) != 0)) + { + max_abscissa = m_abscissas[0][i]; + break; + } + } + + //std::cout << "First estimate : " << I0 << std::endl; + K I1 = I0; + Real L1_I1 = L1_I0; + bool have_first_j = false; + std::size_t first_j = 0; + for (size_t i = 0; (i < m_abscissas[1].size()) && (m_abscissas[1][i] < max_abscissa); ++i) + { + K y = f(m_abscissas[1][i]); + K I1_last = I1; + I1 += y*m_weights[1][i]; + L1_I1 += magnitude(y)*m_weights[1][i]; + if (!have_first_j && (magnitude(I1_last - I1) == 0)) + { + // No change to the sum, disregard these values on the LHS: + if ((i < m_abscissas[1].size() - 1) && (m_abscissas[1][i + 1] > max_abscissa)) + { + // The summit is so high, that we found nothing in this row which added to the integral!! + have_first_j = true; + } + else + { + min_abscissa = m_abscissas[1][i]; + first_j = i; + } + } + else + have_first_j = true; + } + + if (magnitude(I0) == 0) + { + // We failed to find anything, is the integral zero, or have we just not found it yet? + // We'll try one more level, if that still finds nothing then it'll terminate. + min_abscissa = 0; + max_abscissa = BOOST_MATH_NAMESPACE::tools::max_value(); + } + + I1 *= half(); + L1_I1 *= half(); + Real err = magnitude(I0 - I1); + //std::cout << "Second estimate: " << I1 << " Error estimate at level " << 1 << " = " << err << std::endl; + + size_t i = 2; + for(; i < m_abscissas.size(); ++i) + { + I0 = I1; + L1_I0 = L1_I1; + + I1 = half()*I0; + L1_I1 = half()*L1_I0; + Real h = static_cast(1)/static_cast(1 << i); + K sum = zero; + Real absum = 0; + + auto abscissas_row = get_abscissa_row(i); + auto weight_row = get_weight_row(i); + + first_j = first_j == 0 ? 0 : 2 * first_j - 1; // appoximate location to start looking for lowest meaningful abscissa value + std::size_t j = first_j; + while (abscissas_row[j] < min_abscissa) + ++j; + for(; (j < m_weights[i].size()) && (abscissas_row[j] < max_abscissa); ++j) + { + Real x = abscissas_row[j]; + K y = f(x); + sum += y*weight_row[j]; + Real abterm0 = magnitude(y)*weight_row[j]; + absum += abterm0; + } + + I1 += sum*h; + L1_I1 += absum*h; + err = magnitude(I0 - I1); + //std::cout << "Estimate: " << I1 << " Error estimate at level " << i << " = " << err << std::endl; + // Use L1_I1 here to make it work with both complex and real valued integrands: + if (!(BOOST_MATH_NAMESPACE::isfinite)(L1_I1)) + { + policies::raise_evaluation_error(function, "The exp_sinh quadrature evaluated your function at a singular point and returned %1%. Please ensure your function evaluates to a finite number over its entire domain.", magnitude(I1), Policy()); + return I1; + } + if (err <= tolerance*L1_I1) + { + break; + } + } + + if (error) + { + *error = err; + } + + if(L1) + { + *L1 = L1_I1; + } + + if (levels) + { + *levels = i; + } + + return I1; +} + template void exp_sinh_detail::init(const std::integral_constant&) @@ -302,9 +447,9 @@ void exp_sinh_detail::init(const std::integral_constant&) using std::sinh; using std::asinh; using std::ceil; - using boost::math::constants::two_div_pi; - using boost::math::constants::half_pi; - using boost::math::constants::half; + using BOOST_MATH_NAMESPACE::constants::two_div_pi; + using BOOST_MATH_NAMESPACE::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half; m_committed_refinements = 4; // m_t_min is chosen such that x = exp(pi/2 sinh(-t_max)) = very small, but not too small. @@ -313,7 +458,7 @@ void exp_sinh_detail::init(const std::integral_constant&) // If we choose the small number as the min(), then we round off to zero and hit the singularity. // The logarithmic average of the min() and the epsilon() has been found to be a reasonable compromise, which achieves high accuracy // but does not evaluate the function at the singularity. - Real tmp = (boost::math::tools::log_min_value() + log(boost::math::tools::epsilon()))*half(); + Real tmp = (BOOST_MATH_NAMESPACE::tools::log_min_value() + log(BOOST_MATH_NAMESPACE::tools::epsilon()))*half(); m_t_min = asinh(two_div_pi()*tmp); // t_max is chosen to make g'(t_max) ~ sqrt(max) (g' grows faster than g). @@ -324,7 +469,7 @@ void exp_sinh_detail::init(const std::integral_constant&) for (size_t i = 0; i <= m_committed_refinements; ++i) { Real h = static_cast(1) / static_cast(1 << i); - size_t k = static_cast(boost::math::lltrunc(ceil((t_max - m_t_min) / (2 * h)))); + size_t k = static_cast(BOOST_MATH_NAMESPACE::lltrunc(ceil((t_max - m_t_min) / (2 * h)))); m_abscissas[i].reserve(k); m_weights[i].reserve(k); Real arg = m_t_min; @@ -394,7 +539,7 @@ void exp_sinh_detail::init(const std::integral_constant&) { 2.67108015e-21f, 5.82833463e-21f, 1.25616316e-20f, 2.67469785e-20f, 5.62745845e-20f, 1.17014394e-19f, 2.40511019e-19f, 4.88739481e-19f, 9.82072303e-19f, 1.95168062e-18f, 3.83661097e-18f, 7.46163208e-18f, 1.43594942e-17f, 2.73485792e-17f, 5.15573612e-17f, 9.62223075e-17f, 1.77810682e-16f, 3.25389618e-16f, 5.89765054e-16f, 1.05888451e-15f, 1.88354538e-15f, 3.31989417e-15f, 5.79902273e-15f, 1.00398818e-14f, 1.72308010e-14f, 2.93186753e-14f, 4.94655967e-14f, 8.27635884e-14f, 1.37343706e-13f, 2.26082511e-13f, 3.69205736e-13f, 5.98228147e-13f, 9.61866975e-13f, 1.53484658e-12f, 2.43090464e-12f, 3.82185577e-12f, 5.96531965e-12f, 9.24474797e-12f, 1.42267754e-11f, 2.17427910e-11f, 3.30041201e-11f, 4.97635091e-11f, 7.45399354e-11f, 1.10929412e-10f, 1.64031748e-10f, 2.41032586e-10f, 3.51991946e-10f, 5.10905560e-10f, 7.37124150e-10f, 1.05723929e-09f, 1.50757352e-09f, 2.13744796e-09f, 3.01344401e-09f, 4.22492806e-09f, 5.89117093e-09f, 8.17046854e-09f, 1.12717587e-08f, 1.54693324e-08f, 2.11213594e-08f, 2.86930859e-08f, 3.87857241e-08f, 5.21722335e-08f, 6.98414017e-08f, 9.30518593e-08f, 1.23397923e-07f, 1.62889442e-07f, 2.14048123e-07f, 2.80023159e-07f, 3.64729321e-07f, 4.73011070e-07f, 6.10836627e-07f, 7.85526363e-07f, 1.00602028e-06f, 1.28318979e-06f, 1.63019938e-06f, 2.06292424e-06f, 2.60043021e-06f, 3.26552286e-06f, 4.08537275e-06f, 5.09222413e-06f, 6.32419483e-06f, 7.82617466e-06f, 9.65083023e-06f, 1.18597236e-05f, 1.45245521e-05f, 1.77285168e-05f, 2.15678251e-05f, 2.61533347e-05f, 3.16123436e-05f, 3.80905295e-05f, 4.57540432e-05f, 5.47917575e-05f, 6.54176707e-05f, 7.78734661e-05f, 9.24312223e-05f, 1.09396271e-04f, 1.29110197e-04f, 1.51953965e-04f, 1.78351176e-04f, 2.08771424e-04f, 2.43733750e-04f, 2.83810168e-04f, 3.29629253e-04f, 3.81879756e-04f, 4.41314233e-04f, 5.08752659e-04f, 5.85085996e-04f, 6.71279692e-04f, 7.68377076e-04f, 8.77502620e-04f, 9.99865030e-04f, 1.13676015e-03f, 1.28957360e-03f, 1.45978322e-03f, 1.64896113e-03f, 1.85877551e-03f, 2.09099200e-03f, 2.34747474e-03f, 2.63018699e-03f, 2.94119122e-03f, 3.28264890e-03f, 3.65681963e-03f, 4.06605991e-03f, 4.51282135e-03f, 4.99964828e-03f, 5.52917497e-03f, 6.10412222e-03f, 6.72729343e-03f, 7.40157020e-03f, 8.12990738e-03f, 8.91532760e-03f, 9.76091537e-03f, 1.06698107e-02f, 1.16452023e-02f, 1.26903202e-02f, 1.38084285e-02f, 1.50028172e-02f, 1.62767940e-02f, 1.76336759e-02f, 1.90767806e-02f, 2.06094173e-02f, 2.22348784e-02f, 2.39564300e-02f, 2.57773028e-02f, 2.77006834e-02f, 2.97297055e-02f, 3.18674406e-02f, 3.41168899e-02f, 3.64809756e-02f, 3.89625331e-02f, 4.15643030e-02f, 4.42889240e-02f, 4.71389254e-02f, 5.01167213e-02f, 5.32246039e-02f, 5.64647382e-02f, 5.98391571e-02f, 6.33497571e-02f, 6.69982939e-02f, 7.07863800e-02f, 7.47154815e-02f, 7.87869165e-02f, 8.30018539e-02f, 8.73613125e-02f, 9.18661613e-02f, 9.65171203e-02f, 1.01314762e-01f, 1.06259513e-01f, 1.11351656e-01f, 1.16591337e-01f, 1.21978563e-01f, 1.27513213e-01f, 1.33195039e-01f, 1.39023671e-01f, 1.44998628e-01f, 1.51119321e-01f, 1.57385061e-01f, 1.63795066e-01f, 1.70348473e-01f, 1.77044340e-01f, 1.83881662e-01f, 1.90859375e-01f, 1.97976367e-01f, 2.05231492e-01f, 2.12623572e-01f, 2.20151415e-01f, 2.27813822e-01f, 2.35609599e-01f, 2.43537565e-01f, 2.51596569e-01f, 2.59785494e-01f, 2.68103274e-01f, 2.76548903e-01f, 2.85121445e-01f, 2.93820047e-01f, 3.02643950e-01f, 3.11592502e-01f, 3.20665165e-01f, 3.29861530e-01f, 3.39181328e-01f, 3.48624439e-01f, 3.58190905e-01f, 3.67880941e-01f, 3.77694943e-01f, 3.87633504e-01f, 3.97697421e-01f, 4.07887708e-01f, 4.18205605e-01f, 4.28652591e-01f, 4.39230391e-01f, 4.49940993e-01f, 4.60786652e-01f, 4.71769905e-01f, 4.82893580e-01f, 4.94160809e-01f, 5.05575036e-01f, 5.17140031e-01f, 5.28859900e-01f, 5.40739096e-01f, 5.52782432e-01f, 5.64995090e-01f, 5.77382639e-01f, 5.89951040e-01f, 6.02706666e-01f, 6.15656310e-01f, 6.28807202e-01f, 6.42167019e-01f, 6.55743908e-01f, 6.69546490e-01f, 6.83583887e-01f, 6.97865729e-01f, 7.12402181e-01f, 7.27203953e-01f, 7.42282322e-01f, 7.57649155e-01f, 7.73316926e-01f, 7.89298740e-01f, 8.05608358e-01f, 8.22260217e-01f, 8.39269463e-01f, 8.56651970e-01f, 8.74424378e-01f, 8.92604116e-01f, 9.11209442e-01f, 9.30259469e-01f, 9.49774208e-01f, 9.69774604e-01f, 9.90282579e-01f, 1.01132107e+00f, 1.03291408e+00f, 1.05508673e+00f, 1.07786529e+00f, 1.10127728e+00f, 1.12535146e+00f, 1.15011796e+00f, 1.17560829e+00f, 1.20185546e+00f, 1.22889400e+00f, 1.25676010e+00f, 1.28549162e+00f, 1.31512826e+00f, 1.34571158e+00f, 1.37728514e+00f, 1.40989460e+00f, 1.44358784e+00f, 1.47841507e+00f, 1.51442894e+00f, 1.55168471e+00f, 1.59024039e+00f, 1.63015687e+00f, 1.67149810e+00f, 1.71433126e+00f, 1.75872698e+00f, 1.80475947e+00f, 1.85250679e+00f, 1.90205105e+00f, 1.95347869e+00f, 2.00688065e+00f, 2.06235275e+00f, 2.11999592e+00f, 2.17991652e+00f, 2.24222670e+00f, 2.30704472e+00f, 2.37449538e+00f, 2.44471039e+00f, 2.51782884e+00f, 2.59399766e+00f, 2.67337209e+00f, 2.75611628e+00f, 2.84240383e+00f, 2.93241843e+00f, 3.02635449e+00f, 3.12441791e+00f, 3.22682682e+00f, 3.33381238e+00f, 3.44561973e+00f, 3.56250887e+00f, 3.68475574e+00f, 3.81265333e+00f, 3.94651282e+00f, 4.08666490e+00f, 4.23346116e+00f, 4.38727553e+00f, 4.54850596e+00f, 4.71757611e+00f, 4.89493722e+00f, 5.08107015e+00f, 5.27648761e+00f, 5.48173646e+00f, 5.69740032e+00f, 5.92410235e+00f, 6.16250823e+00f, 6.41332946e+00f, 6.67732689e+00f, 6.95531455e+00f, 7.24816384e+00f, 7.55680807e+00f, 7.88224735e+00f, 8.22555401e+00f, 8.58787841e+00f, 8.97045530e+00f, 9.37461076e+00f, 9.80176975e+00f, 1.02534643e+01f, 1.07313428e+01f, 1.12371793e+01f, 1.17728848e+01f, 1.23405187e+01f, 1.29423019e+01f, 1.35806306e+01f, 1.42580922e+01f, 1.49774818e+01f, 1.57418213e+01f, 1.65543795e+01f, 1.74186947e+01f, 1.83385994e+01f, 1.93182476e+01f, 2.03621450e+01f, 2.14751816e+01f, 2.26626686e+01f, 2.39303784e+01f, 2.52845893e+01f, 2.67321348e+01f, 2.82804577e+01f, 2.99376708e+01f, 3.17126238e+01f, 3.36149769e+01f, 3.56552840e+01f, 3.78450835e+01f, 4.01970005e+01f, 4.27248599e+01f, 4.54438126e+01f, 4.83704762e+01f, 5.15230921e+01f, 5.49217006e+01f, 5.85883374e+01f, 6.25472527e+01f, 6.68251567e+01f, 7.14514957e+01f, 7.64587609e+01f, 8.18828353e+01f, 8.77633847e+01f, 9.41442967e+01f, 1.01074176e+02f, 1.08606902e+02f, 1.16802259e+02f, 1.25726650e+02f, 1.35453899e+02f, 1.46066166e+02f, 1.57654979e+02f, 1.70322410e+02f, 1.84182406e+02f, 1.99362306e+02f, 2.16004568e+02f, 2.34268740e+02f, 2.54333703e+02f, 2.76400239e+02f, 3.00693971e+02f, 3.27468728e+02f, 3.57010397e+02f, 3.89641362e+02f, 4.25725590e+02f, 4.65674502e+02f, 5.09953726e+02f, 5.59090900e+02f, 6.13684688e+02f, 6.74415211e+02f, 7.42056139e+02f, 8.17488717e+02f, 9.01718069e+02f, 9.95892168e+02f, 1.10132394e+03f, 1.21951707e+03f, 1.35219615e+03f, 1.50134197e+03f, 1.66923291e+03f, 1.85849349e+03f, 2.07215152e+03f, 2.31370536e+03f, 2.58720328e+03f, 2.89733724e+03f, 3.24955383e+03f, 3.65018587e+03f, 4.10660860e+03f, 4.62742547e+03f, 5.22268956e+03f, 5.90416786e+03f, 6.68565726e+03f, 7.58336313e+03f, 8.61635357e+03f, 9.80710572e+03f, 1.11821637e+04f, 1.27729327e+04f, 1.46166396e+04f, 1.67574960e+04f, 1.92481112e+04f, 2.21512104e+04f, 2.55417295e+04f, 2.95093735e+04f, 3.41617487e+04f, 3.96282043e+04f, 4.60645561e+04f, 5.36589049e+04f, 6.26388223e+04f, 7.32802431e+04f, 8.59184957e+04f, 1.00962017e+05f, 1.18909442e+05f, 1.40370957e+05f, 1.66095034e+05f, 1.97001996e+05f, 2.34226253e+05f, 2.79169596e+05f, 3.33568603e+05f, 3.99580125e+05f, 4.79889989e+05f, 5.77851588e+05f, 6.97663062e+05f, 8.44594440e+05f, 1.02527965e+06f, 1.24809298e+06f, 1.52363581e+06f, 1.86536786e+06f, 2.29042802e+06f, 2.82070529e+06f, 3.48424008e+06f, 4.31706343e+06f, 5.36561882e+06f, 6.68996113e+06f, 8.36799594e+06f, 1.05011160e+07f, 1.32217203e+07f, 1.67032788e+07f, 2.11738506e+07f, 2.69343047e+07f, 3.43829654e+07f, 4.40490690e+07f, 5.66383460e+07f, 7.30953564e+07f, 9.46890531e+07f, 1.23130681e+08f, 1.60736861e+08f, 2.10656057e+08f, 2.77184338e+08f, 3.66207397e+08f, 4.85821891e+08f, 6.47212479e+08f, 8.65895044e+08f, 1.16348659e+09f, 1.57023596e+09f, 2.12865840e+09f, 2.89877917e+09f, 3.96573294e+09f, 5.45082863e+09f, 7.52773593e+09f, 1.04462776e+10f, 1.45675716e+10f, 2.04161928e+10f, 2.87579864e+10f, 4.07167363e+10f, 5.79499965e+10f, 8.29154750e+10f, 1.19276754e+11f, 1.72524570e+11f, 2.50933409e+11f, 3.67042596e+11f, 5.39962441e+11f, 7.98985690e+11f, 1.18927611e+12f, 1.78088199e+12f, 2.68310388e+12f, 4.06753710e+12f, 6.20525592e+12f, 9.52719664e+12f, 1.47228407e+13f, 2.29025392e+13f, 3.58662837e+13f, 5.65517100e+13f, 8.97859411e+13f, 1.43556057e+14f, 2.31171020e+14f, 3.74966777e+14f, 6.12702071e+14f, 1.00868013e+15f, 1.67323268e+15f, 2.79711270e+15f, 4.71267150e+15f, 8.00353033e+15f, 1.37027503e+16f, 2.36538022e+16f, 4.11734705e+16f, 7.22793757e+16f, 1.27982244e+17f, 2.28603237e+17f, 4.11976277e+17f, 7.49169358e+17f, 1.37488861e+18f, 2.54681529e+18f, 4.76248383e+18f, 8.99167123e+18f, 1.71428840e+19f, 3.30088717e+19f, 6.42020070e+19f, 1.26155602e+20f, 2.50480806e+20f, 5.02601059e+20f, 1.01935525e+21f, }, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_weights.size() - 1); + m_committed_refinements = static_cast(m_weights.size() - 1); #else m_committed_refinements = m_weights.size() - 1; #endif @@ -434,7 +579,7 @@ void exp_sinh_detail::init(const std::integral_constant&) { 4.901759085947701448e-159, 1.505832423620814399e-156, 4.231872109262999523e-154, 1.089479701785106001e-151, 2.572922387150651649e-149, 5.581311054334156941e-147, 1.113575900126970040e-144, 2.046165051332286084e-142, 3.466994885004770636e-140, 5.423795404073501922e-138, 7.843833272402847010e-136, 1.049922957933194415e-133, 1.302301071957418603e-131, 1.498659737828393008e-129, 1.601906622414286282e-127, 1.592248618401983561e-125, 1.473375345916436274e-123, 1.270651551394009593e-121, 1.022408263525766209e-119, 7.683762602329562781e-118, 5.399268127233373186e-116, 3.551074274853494676e-114, 2.188235409519121010e-112, 1.264667515430816934e-110, 6.861807566737243712e-109, 3.498691686825209963e-107, 1.678016807398375157e-105, 7.577439431441931490e-104, 3.224703770159386809e-102, 1.294487090677705963e-100, 4.906133250963454139e-99, 1.757121317988153326e-97, 5.952042491454320383e-96, 1.908566653286417264e-94, 5.798224459236429212e-93, 1.670293239978334727e-91, 4.566236673398083038e-90, 1.185617342791547945e-88, 2.926160027801296929e-87, 6.870061134126707137e-86, 1.535565783500379945e-84, 3.270036736778401257e-83, 6.639558007206580362e-82, 1.286319750967398593e-80, 2.379566581139022958e-79, 4.206268231398883425e-78, 7.109719237833379433e-77, 1.149915104115372777e-75, 1.780876201255594220e-74, 2.642703796179329883e-73, 3.760085375941719327e-72, 5.132920951124251993e-71, 6.727100274601427696e-70, 8.469585621347697498e-69, 1.025032382672232848e-67, 1.193219127557863348e-66, 1.336816930381306582e-65, 1.442283479679798385e-64, 1.499374555004793991e-63, 1.502797203133501438e-62, 1.453005969318485303e-61, 1.355980448377862540e-60, 1.222072412212552127e-59, 1.064223180270520159e-58, 8.959667396075636845e-58, 7.296288808079294105e-57, 5.750255296190181158e-56, 4.388011664829013518e-55, 3.243852451291832398e-54, 2.324239357665538806e-53, 1.614869776203026446e-52, 1.088524605545274842e-51, 7.121755574192829045e-51, 4.524647662549067074e-50, 2.792730715818793035e-49, 1.675384879603864227e-48, 9.773114328777676091e-48, 5.545910766847627082e-47, 3.062809705627873645e-46, 1.646862118038266234e-45, 8.625108513887155847e-45, 4.401687663868890701e-44, 2.189755778847646746e-43, 1.062345336449265889e-42, 5.028036663485684049e-42, 2.322524635717249223e-41, 1.047406593898341306e-40, 4.613438388449698168e-40, 1.985397445118162005e-39, 8.351027367454628343e-39, 3.434440903484543389e-38, 1.381489131877196646e-37, 5.437051201310225224e-37, 2.094357548080647717e-36, 7.898676618592006902e-36, 2.917536870947471272e-35, 1.055788886022716597e-34, 3.744333812160330812e-34, 1.301801185251957290e-33, 4.438346216893387768e-33, 1.484348268951816542e-32, 4.871001129849836971e-32, 1.568903000742513942e-31, 4.961295315917935235e-31, 1.540773910027990821e-30, 4.700558022172014910e-30, 1.409115230718949596e-29, 4.151913103955692034e-29, 1.202737613715427748e-28, 3.426327374934496736e-28, 9.601405359397026012e-28, 2.647278642033773301e-27, 7.183442220565147103e-27, 1.918850545981494042e-26, 5.046974779455992494e-26, 1.307394799925911700e-25, 3.336342198236957082e-25, 8.389259581136262194e-25, 2.079051813513548608e-24, 5.079178967243765280e-24, 1.223501794357837278e-23, 2.906654911057549530e-23, 6.811668606095015470e-23, 1.574985938238025303e-22, 3.593796788969348326e-22, 8.094185411205212564e-22, 1.799796183237481721e-21, 3.951758901641017285e-21, 8.569580068050865775e-21, 1.835753486517298696e-20, 3.885414339966022317e-20, 8.126613972895021790e-20, 1.680007182889503141e-19, 3.433369351563962828e-19, 6.937695550399427499e-19, 1.386345631008981755e-18, 2.740087497759230881e-18, 5.357570288683386626e-18, 1.036464933022803784e-17, 1.984249442010084992e-17, 3.759788006060003409e-17, 7.052211261821684795e-17, 1.309635641529546221e-16, 2.408275496109180528e-16, 4.385898809611711552e-16, 7.911758686849121285e-16, 1.413883597877183873e-15, 2.503477536644680210e-15, 4.392637866550705827e-15, 7.638710306960574612e-15, 1.316703360377476041e-14, 2.250031027275448919e-14, 3.812239733412214953e-14, 6.405021660191363479e-14, 1.067250538270319484e-13, 1.763897493784721010e-13, 2.891987565334547756e-13, 4.704242520369958085e-13, 7.592878273512691990e-13, 1.216183338372525172e-12, 1.933388593436624879e-12, 3.050826852442290751e-12, 4.779080020017636657e-12, 7.432734713385425098e-12, 1.147833888125873666e-11, 1.760286160372422754e-11, 2.681071101623953168e-11, 4.056023754295965437e-11, 6.095443492241537222e-11, 9.100550129616064211e-11, 1.349993452136967652e-10, 1.989943912395156051e-10, 2.914996073619059788e-10, 4.243900781412219621e-10, 6.141353162671391082e-10, 8.834365795894798511e-10, 1.263395594025933170e-09, 1.796369250051716047e-09, 2.539704143326480862e-09, 3.570592498287890499e-09, 4.992348403150539107e-09, 6.942471870489931483e-09, 9.602949600164561371e-09, 1.321333712761666777e-08, 1.808727901635346390e-08, 2.463325364767791516e-08, 3.338047870136870496e-08, 4.501108426108505069e-08, 6.039985413333259594e-08, 8.066305374526097834e-08, 1.072181059018892614e-07, 1.418561443795353991e-07, 1.868297699836383305e-07, 2.449586539172972009e-07, 3.197559780442760832e-07, 4.155790690867544334e-07, 5.378079713325544678e-07, 6.930561064776686194e-07, 8.894175852502122454e-07, 1.136756157868726006e-06, 1.447041212534730898e-06, 1.834736645332833504e-06, 2.317248822354253644e-06, 2.915440225825303911e-06, 3.654215709863551870e-06, 4.563188576773760151e-06, 5.677433909482232878e-06, 7.038336747307571784e-06, 8.694542758083067228e-06, 1.070301902702759858e-05, 1.313023243937403750e-05, 1.605345286789073897e-05, 1.956218797728780449e-05, 2.375975591555218862e-05, 2.876500146954361208e-05, 3.471416041263076209e-05, 4.176287576185915239e-05, 5.008836848967403773e-05, 5.989176390181730373e-05, 7.140057340280213227e-05, 8.487132973049760036e-05, 1.005923719620999934e-04, 1.188867746885496973e-04, 1.401154137398069279e-04, 1.646801587388731249e-04, 1.930271805904271778e-04, 2.256503597954330556e-04, 2.630947792533707128e-04, 3.059602829980946180e-04, 3.549050801425155303e-04, 4.106493712131842727e-04, 4.739789720708565436e-04, 5.457489087697051069e-04, 6.268869550379884668e-04, 7.183970825975973673e-04, 8.213627933082928901e-04, 9.369503011517966364e-04, 1.066411531385725184e-03, 1.211086903819095417e-03, 1.372407867107646339e-03, 1.551899151252505624e-03, 1.751180706119547318e-03, 1.971969294784470944e-03, 2.216079711850908971e-03, 2.485425598581779636e-03, 2.782019828718993257e-03, 3.107974441230220176e-03, 3.465500098895993776e-03, 3.856905054613959619e-03, 4.284593610523639393e-03, 4.751064058515097225e-03, 5.258906094345618421e-03, 5.810797701414435799e-03, 6.409501504198915943e-03, 7.057860595396970186e-03, 7.758793844909123446e-03, 8.515290702888369372e-03, 9.330405513145299523e-03, 1.020725135717912572e-02, 1.114899345297222760e-02, 1.215884213639836574e-02, 1.324004545661629463e-02, 1.439588142011718850e-02, 1.562964992113485073e-02, 1.694466439888404584e-02, 1.834424326453982033e-02, 1.983170114298836870e-02, 2.141033997615067889e-02, 2.308344003609062690e-02, 2.485425089716015368e-02, 2.672598241710042669e-02, 2.870179577730820310e-02, 3.078479463239356953e-02, 3.297801641870515720e-02, 3.528442387069167064e-02, 3.770689679281728890e-02, 4.024822413326941635e-02, 4.291109640390936770e-02, 4.569809848884132640e-02, 4.861170288163592155e-02, 5.165426338866744454e-02, 5.482800933323496446e-02, 5.813504029216542680e-02, 6.157732139347005467e-02, 6.515667920037330165e-02, 6.887479820368566403e-02, 7.273321794107712090e-02, 7.673333075835566151e-02, 8.087638022439339824e-02, 8.516346020789830747e-02, 8.959551462082867423e-02, 9.417333782991444898e-02, 9.889757573450802477e-02, 1.037687275058577967e-01, 1.087871479799008567e-01, 1.139530506928239996e-01, 1.192665115459606141e-01, 1.247274730840887416e-01, 1.303357493688843496e-01, 1.360910314271734020e-01, 1.419928932517243620e-01, 1.480407983306351483e-01, 1.542341066798992024e-01, 1.605720823524863565e-01, 1.670539013962460335e-01, 1.736786602321317742e-01, 1.804453844236544912e-01, 1.873530378080931153e-01, 1.944005319598201097e-01, 2.015867359561292115e-01, 2.089104864161762672e-01, 2.163705977840528187e-01, 2.239658728275971045e-01, 2.316951133252986765e-01, 2.395571309145607347e-01, 2.475507580756380088e-01, 2.556748592267567912e-01, 2.639283419072366399e-01, 2.723101680268593668e-01, 2.808193651612593497e-01, 2.894550378747292326e-01, 2.982163790535362503e-01, 3.071026812346166036e-01, 3.161133479163487600e-01, 3.252479048399920142e-01, 3.345060112323053140e-01, 3.438874710018250777e-01, 3.533922438832718793e-01, 3.630204565265675291e-01, 3.727724135289699431e-01, 3.826486084108677024e-01, 3.926497345378144818e-01, 4.027766959934214472e-01, 4.130306184097598756e-01, 4.234128597639539906e-01, 4.339250211516634154e-01, 4.445689575501645526e-01, 4.553467885857401860e-01, 4.662609093220769612e-01, 4.773140010883521767e-01, 4.885090423676662636e-01, 4.998493197684479070e-01, 5.113384391034281429e-01, 5.229803366027518117e-01, 5.347792902897740156e-01, 5.467399315500809553e-01, 5.588672569262846167e-01, 5.711666401731758417e-01, 5.836438446098876156e-01, 5.963050358078278898e-01, 6.091567946552975691e-01, 6.222061308419237716e-01, 6.354604968083211637e-01, 6.489278022087558681e-01, 6.626164289370386795e-01, 6.765352467684294227e-01, 6.906936296730053994e-01, 7.051014728587479919e-01, 7.197692106055475377e-01, 7.347078349544334315e-01, 7.499289153196209421e-01, 7.654446190944464391e-01, 7.812677333259577661e-01, 7.974116875368567865e-01, 8.138905777776784362e-01, 8.307191919965581771e-01, 8.479130368187123741e-01, 8.654883658328603475e-01, 8.834622094872810766e-01, 9.018524067040521621e-01, 9.206776383262963142e-01, 9.399574625199963151e-01, 9.597123522591707284e-01, 9.799637350309700387e-01, 1.000734034905599933e+00, 1.022046717124952010e+00, 1.043926335373472893e+00, 1.066398581905185161e+00, 1.089490340711946628e+00, 1.113229743930062164e+00, 1.137646231695313314e+00, 1.162770615670420260e+00, 1.188635146483979071e+00, 1.215273585336112390e+00, 1.242721280043529050e+00, 1.271015245815510799e+00, 1.300194251072644711e+00, 1.330298908642019971e+00, 1.361371772686240192e+00, 1.393457441749111730e+00, 1.426602668328411758e+00, 1.460856475415888358e+00, 1.496270280476785338e+00, 1.532898027375920169e+00, 1.570796326794896619e+00, 1.610024605725646420e+00, 1.650645266669431435e+00, 1.692723857217988332e+00, 1.736329250744977731e+00, 1.781533838991654903e+00, 1.828413737391087381e+00, 1.877049004040720448e+00, 1.927523873304087635e+00, 1.979927005099477087e+00, 2.034351751016940433e+00, 2.090896438495766214e+00, 2.149664674393090421e+00, 2.210765669381402212e+00, 2.274314584729113927e+00, 2.340432903144970240e+00, 2.409248825504827076e+00, 2.480897695429288043e+00, 2.555522453844001656e+00, 2.633274125832370887e+00, 2.714312342284411608e+00, 2.798805899057066353e+00, 2.886933356592141886e+00, 2.978883683190077867e+00, 3.074856945413050211e+00, 3.175065049391765683e+00, 3.279732537139255280e+00, 3.389097442334834102e+00, 3.503412210435275865e+00, 3.622944688401595705e+00, 3.747979189802462585e+00, 3.878817641573403805e+00, 4.015780819279312670e+00, 4.159209678351536168e+00, 4.309466789455788368e+00, 4.466937886899736897e+00, 4.632033539816493591e+00, 4.805190956770360727e+00, 4.986875935432896972e+00, 5.177584970080537688e+00, 5.377847530880629761e+00, 5.588228530273088035e+00, 5.809330993233640059e+00, 6.041798949837089488e+00, 6.286320570342285919e+00, 6.543631565013652661e+00, 6.814518873098582608e+00, 7.099824667819718682e+00, 7.400450706942931008e+00, 7.717363061475788814e+00, 8.051597258371279584e+00, 8.404263876795383951e+00, 8.776554641607500109e+00, 9.169749062247565207e+00, 9.585221670276993889e+00, 1.002444991444300704e+01, 1.048902277839603856e+01, 1.098065019316492606e+01, 1.150117332427169985e+01, 1.205257582204547280e+01, 1.263699613338454324e+01, 1.325674098404332380e+01, 1.391430015262873368e+01, 1.461236267104086712e+01, 1.535383460126837531e+01, 1.614185855545811846e+01, 1.697983514525758524e+01, 1.787144656784601339e+01, 1.882068256013178484e+01, 1.983186897964764985e+01, 2.090969930111845450e+01, 2.205926935196095527e+01, 2.328611564861881683e+01, 2.459625773922860138e+01, 2.599624500732998276e+01, 2.749320844694889238e+01, 2.909491798228195984e+01, 3.080984597641076715e+01, 3.264723765414180400e+01, 3.461718925554321861e+01, 3.673073484057443067e+01, 3.899994278315456980e+01, 4.143802312713618427e+01, 4.405944712930142330e+01, 4.688008048840357439e+01, 4.991733195758662298e+01, 5.319031926387298369e+01, 5.672005451703465811e+01, 6.052965158594831140e+01, 6.464455825915836491e+01, 6.909281639443131774e+01, 7.390535370725211687e+01, 7.911631135942343489e+01, 8.476341209659472308e+01, 9.088837435982152722e+01, 9.753737857533253823e+01, 1.047615927251647361e+02, 1.126177653386554197e+02, 1.211688952437418817e+02, 1.304849888043593828e+02, 1.406439169773708701e+02, 1.517323863863765989e+02, 1.638470407739824279e+02, 1.770957117100033620e+02, 1.915988403612775885e+02, 2.074910955409497265e+02, 2.249232172361061194e+02, 2.440641194630869936e+02, 2.651032917390266964e+02, 2.882535448280364212e+02, 3.137541538897424513e+02, 3.418744609277612322e+02, 3.729180087461214321e+02, 4.072272907593818790e+02, 4.451892153103389878e+02, 4.872414000388630927e+02, 5.338794318098249932e+02, 5.856652513400113117e+02, 6.432368496766822816e+02, 7.073194969336578611e+02, 7.787387632221277236e+02, 8.584356387770406827e+02, 9.474841163944599543e+02, 1.047111666301969297e+03, 1.158723113719277435e+03, 1.283928525349707755e+03, 1.424575826189363437e+03, 1.582789006393775706e+03, 1.761012944445459235e+03, 1.962066073573121788e+03, 2.189202360708354222e+03, 2.446184360349559652e+03, 2.737369460761187093e+03, 3.067811870808767638e+03, 3.443383419509962754e+03, 3.870916878218207705e+03, 4.358376293464465508e+03, 4.915059769420260559e+03, 5.551841303216967404e+03, 6.281459704453426129e+03, 7.118864385205665710e+03, 8.081629967627799596e+03, 9.190454321738597280e+03, 1.046975794051835702e+04, 1.194840663946247320e+04, 1.366058463062104793e+04, 1.564685131637809273e+04, 1.795542299179967539e+04, 2.064373043744082514e+04, 2.378031563732670807e+04, 2.744714621995650953e+04, 3.174244552480722739e+04, 3.678416050731336226e+04, 4.271422037773508051e+04, 4.970377768100323981e+04, 5.795967273138576164e+04, 6.773242484608792593e+04, 7.932613346949942761e+04, 9.311077397156915450e+04, 1.095375030536372224e+05, 1.291577556735669526e+05, 1.526471301608741586e+05, 1.808353350969648289e+05, 2.147438294770164181e+05, 2.556332515573999948e+05, 3.050633345562097502e+05, 3.649687926665853954e+05, 4.377556866857485380e+05, 5.264241222943208736e+05, 6.347248990108319410e+05, 7.673600526542426466e+05, 9.302403050337502786e+05, 1.130816502666451845e+06, 1.378507531155523742e+06, 1.685254393964162275e+06, 2.066239770168639390e+06, 2.540825270229354918e+06, 3.133775962036416630e+06, 3.876865148275802393e+06, 4.810984054018349430e+06, 5.988924089534678664e+06, 7.479057929608060924e+06, 9.370225698693408867e+06, 1.177824230977510661e+07, 1.485459301432580619e+07, 1.879809270383398104e+07, 2.387057334436346400e+07, 3.041806552258603202e+07, 3.889950046843262151e+07, 4.992574374586696017e+07, 6.431287504495613210e+07, 8.315518519925858136e+07, 1.079255664704117961e+08, 1.406141073390035115e+08, 1.839201785677305607e+08, 2.415197116904975365e+08, 3.184386015381112281e+08, 4.215765018929686736e+08, 5.604446356915114550e+08, 7.482094398046911572e+08, 1.003175129668246151e+09, 1.350898918997482870e+09, 1.827222165053491590e+09, 2.482633480831760933e+09, 3.388577637234919719e+09, 4.646620065299105644e+09, 6.401821801566297122e+09, 8.862352038053251473e+09, 1.232838602859196811e+10, 1.723489297480180023e+10, 2.421530528469447376e+10, 3.419673813208063025e+10, 4.854312364622606540e+10, 6.927149043760342676e+10, 9.938049490186203616e+10, 1.433521424759854145e+11, 2.079221734483088227e+11, 3.032695241820108158e+11, 4.448631503727710431e+11, 6.563458646477901051e+11, 9.740635696398910980e+11, 1.454220520059656158e+12, 2.184250688898627320e+12, 3.300999104757560757e+12, 5.019970485022749012e+12, 7.682676299017607834e+12, 1.183376596003983872e+13, 1.834748853557035315e+13, 2.863639312458363586e+13, 4.499803892715039958e+13, 7.119486876989154498e+13, 1.134307017980122346e+14, 1.820065782363618395e+14, 2.941484500615394037e+14, 4.788707305890930382e+14, 7.854025036928623551e+14, 1.297894304619860251e+15, 2.161279954782425640e+15, 3.627102147035003834e+15, 6.135342933440950378e+15, 1.046170006362244506e+16, 1.798477357839665686e+16, 3.117473412332331475e+16, 5.449445073049184222e+16, 9.607515505017978212e+16, 1.708589224452677852e+17, 3.065429751110228665e+17, 5.549227437451149511e+17, 1.013730232778046314e+18, 1.869059895876405824e+18, 3.478549552381578424e+18, 6.535992245975463763e+18, 1.240019272261066308e+19, 2.375828866910936629e+19, 4.597682433604432625e+19, 8.988106816837128428e+19, 1.775302379393632263e+20, 3.543413304390973486e+20, 7.148061397675525327e+20, 1.457620510577186305e+21, 3.005137124879829797e+21, 6.265024861633250697e+21, 1.320979941090283816e+22, 2.817487535902146221e+22, 6.079933041429805231e+22, 1.327658853647212083e+23, 2.934311759183641318e+23, 6.565087216807130026e+23, 1.487212273437937650e+24, 3.411840196076788128e+24, 7.928189928797018762e+24, 1.866451877029704857e+25, 4.452521859886739549e+25, 1.076545435174977662e+26, 2.638685681190697586e+26, 6.557908470244186498e+26, 1.652952243735585721e+27, 4.226383395914916199e+27, 1.096450394268080148e+28, 2.886822082999286080e+28, 7.715480389344015925e+28, 2.093728789309964846e+29, 5.770275789447655037e+29, 1.615463845391781140e+30, 4.595470055795608691e+30, 1.328629392686523255e+31, 3.905079681530784219e+31, 1.167134024271997252e+32, 3.548058538654277403e+32, 1.097378059358046160e+33, 3.454102978064445595e+33, 1.106745393701652323e+34, 3.610899559139069994e+34, 1.199946999283670567e+35, 4.062687014190878792e+35, 1.401835223893224514e+36, 4.931085527333162173e+36, 1.768812393284919500e+37, 6.472148293945199961e+37, 2.416453721739211922e+38, 9.208944720398123862e+38, 3.583297028622126676e+39, 1.424097482596699440e+40, 5.782627833426411524e+40, 2.399862204084363183e+41, 1.018291572042305460e+42, 4.419105414822034531e+42, 1.962126117680499311e+43, 8.916742424061253707e+43, 4.148882478294757720e+44, 1.977256529558276930e+45, 9.655300233875401080e+45, 4.832878898335598922e+46, 2.480575878223098058e+47, 1.306102809757654706e+48, 7.057565717289569232e+48, 3.915276522229618618e+49, 2.230898980943393318e+50, 1.306141334496309306e+51, 7.861021286656392627e+51, 4.865583758538451107e+52, 3.098487425915704674e+53, 2.031037614862563901e+54, 1.370999647608260200e+55, 9.534736274325001528e+55, 6.834959923166415407e+56, 5.052733546324789020e+57, 3.853810997282159979e+58, 3.034183107853208298e+59, 2.467161926009838899e+60, 2.072901039813580593e+61, 1.800563980579615383e+62, 1.617764027895344257e+63, 1.504283028250688329e+64, 1.448393206525427172e+65, 1.444855510980115799e+66, 1.494120428855029243e+67, 1.602566566107015722e+68, 1.783880504153942988e+69, 2.061999240572760738e+70, 2.476521794698572715e+71, 3.092349914153497358e+72, 4.016927238305985810e+73, 5.431607545226497387e+74, 7.650086824042822759e+75, 1.123017984114349288e+77, 1.719382952966052004e+78, 2.747335718690686674e+79, 4.584545010557684123e+80, 7.995082041539250252e+81, 1.458119909365899044e+83, 2.783001178679600175e+84, 5.562812231966194628e+85, 1.165338768982404578e+87, 2.560399126432838224e+88, 5.904549641859098192e+89, 1.430278474749838710e+91, 3.642046122956932563e+92, 9.756698571206402300e+93, 2.751946044275883051e+95, 8.179164793643197279e+96, 2.563704735086825890e+98, 8.481656496128255880e+99, 2.964260254403981007e+101, 1.095342970031208886e+103, 4.283148547584870628e+104, 1.773954352944319744e+106, 7.788991081894224760e+107, 3.628931721056821352e+109, 1.795729272516020592e+111, 9.446685151482835339e+112, 5.288263179614488101e+114, 3.153311236741401362e+116, 2.004807079683827669e+118, 1.360407192665237716e+120, 9.862825609807810517e+121, 7.647551788591128099e+123, 6.348802224871730088e+125, 5.649062361980019098e+127, 5.393248003523784781e+129, 5.530897191915703916e+131, 6.099598644640894333e+133, 7.242098433491964504e+135, 9.268083053637375570e+137, 1.279942702416040582e+140, 1.909796626960621302e+142, 3.082540300669885040e+144, 5.388809732384179657e+146, 1.021610251056626535e+149, 2.103005440072790650e+151, 4.706753990348725570e+153, 1.146834128125248991e+156, }, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_weights.size() - 1); + m_committed_refinements = static_cast(m_weights.size() - 1); #else m_committed_refinements = m_weights.size() - 1; #endif @@ -474,7 +619,7 @@ void exp_sinh_detail::init(const std::integral_constant&) { 1.58403833597397609272337637131715304e-2474L, 4.01729907956437307269377706375953438e-2436L, 2.58580645701935131155084366864422406e-2398L, 4.31502895023559220093536948165386274e-2361L, 1.90627959218882483095663188951084330e-2324L, 2.27589955667507909301636117518932802e-2288L, 7.49364095876812027654477175001110624e-2253L, 6.94191154236392933887288062436725643e-2218L, 1.84522919671267474043685120983334524e-2183L, 1.43487104640347241520251346864979221e-2149L, 3.32692243646438795745471365264644590e-2116L, 2.34362088307498827836613435573448115e-2083L, 5.10938037262713942693655713913568198e-2051L, 3.51060735754549615330960873223686009e-2019L, 7.73934046950102664330281533900661264e-1988L, 5.57169465236073520583741860201801676e-1957L, 1.33280818206626290524674045358563098e-1926L, 1.07761463878385909143899244627194248e-1896L, 2.99487219016399829947920738111566372e-1867L, 2.90872283894068508271645083240599458e-1838L, 1.00349314519658897817146360011284604e-1809L, 1.24963603019269210233323055704536134e-1781L, 5.70651178926661193581089363715896182e-1754L, 9.70578293043209307574192077696195294e-1727L, 6.24328278846472954410732505740796953e-1700L, 1.54193058035632514209035337344023300e-1673L, 1.48399119945730121895709095048379728e-1647L, 5.64752158032889554103477750567193685e-1622L, 8.62167301557505164690437370018957398e-1597L, 5.35528299764763984143338000418037832e-1572L, 1.37241462764951847155586335894427418e-1547L, 1.47116444020541724843474277134735959e-1523L, 6.68618803692998895772448346916660911e-1500L, 1.30561453192449212967328116730742424e-1476L, 1.10983482751594629837009226116529299e-1453L, 4.16014518377810797736243906294304347e-1431L, 6.96431413050131379947014047903616964e-1409L, 5.27224320695995707920555229340409925e-1387L, 1.82727152085917578757399986780345619e-1365L, 2.93468712490571136931409720092296819e-1344L, 2.21029656493081556265677595112314098e-1323L, 7.89892460822856456312620943162424218e-1303L, 1.35498246922475851477828612647429926e-1282L, 1.12846854910106323887966343965144914e-1262L, 4.61424330893765402182473137993848704e-1243L, 9.36605095127672178405946589653781928e-1224L, 9.54054141854710811663726016692763275e-1205L, 4.92938100391460828476769674596652859e-1186L, 1.30552448174985025504800286655378847e-1167L, 1.79081395504489298673122868237542862e-1149L, 1.28534148947828407343141932678878641e-1131L, 4.87584961151572559819046616829450419e-1114L, 9.87277629967922144952427945151885497e-1097L, 1.07748800964228010206356572218732211e-1079L, 6.39928058051557015650179754550910965e-1063L, 2.08781638937389821580749246439535224e-1046L, 3.77684590339710704264469235045684970e-1030L, 3.82307555361237861173188661605677525e-1014L, 2.18500494285229212661260038960152445e-998L, 7.11371665672211288079530438419393765e-983L, 1.33086590459456967821090511427946680e-967L, 1.44309821421378874919204882407008472e-952L, 9.14647515187060050796469146648366553e-938L, 3.41683020290309632448426799765730462e-923L, 7.58515118221027874504569883083804726e-909L, 1.00874302140725085602226074835782694e-894L, 8.10069400524047548461447004237480370e-881L, 3.95900210017885619699714022194103898e-867L, 1.18662867376446832171113003401601030e-853L, 2.19786739893484213511853337557279548e-840L, 2.53446665772094387684997171428381901e-827L, 1.83299289701163579779687245566728015e-814L, 8.37462324951323786164578010773011160e-802L, 2.43440349985894963165438833576050630e-789L, 4.53405919015746926984345204895280285e-777L, 5.44811780296147933680587250736719556e-765L, 4.25227509910246244055269284525208521e-753L, 2.17028567518979939311612851867355063e-741L, 7.29110293097611082922276966606966112e-730L, 1.62280402409213923291155004693280799e-718L, 2.40828308813354260030814303685712546e-707L, 2.39798644647022706006083856285038692e-696L, 1.61202006993232554271262188260349029e-685L, 7.36078014307223356522361505691981658e-675L, 2.29673595120013740585571409952171287e-664L, 4.92601668045549547120303143586093867e-654L, 7.30469847326532782734592211727680659e-644L, 7.53208483045812497621524949105624661e-634L, 5.43101457218649885434844485451114112e-624L, 2.75364547737132169841544376328974616e-614L, 9.87114363624257039419731807833639141e-605L, 2.51532230246971379761137727536103954e-595L, 4.58020252011364324634687161502454437e-586L, 5.99105224430269595047395967421408836e-577L, 5.65817475729598864582006398104320790e-568L, 3.87790653215945353008449656152626419e-559L, 1.93831767408426944576894121111160849e-550L, 7.10042999124518145073529096418920675e-542L, 1.91544155185588660392537613901890409e-533L, 3.82329460613706944718834058784982843e-525L, 5.67308558344799642959861077485254353e-517L, 6.28651971015047054176370541889652534e-509L, 5.22608309691007325295015732741277330e-501L, 3.27380385796518526996963624688451015e-493L, 1.55218880567110686358214096387337744e-485L, 5.59406715134492552797785887998506288e-478L, 1.53903555561583129370612427064103671e-470L, 3.24582771097869247388161880434215690e-463L, 5.26923908371102477241383694074670819e-456L, 6.61116543964979170247326465662672578e-449L, 6.43651161747399650924315876123367361e-442L, 4.88172530890739153159755873311503383e-435L, 2.89552772291014307121494513337008901e-428L, 1.34824561713159645449381177450374044e-421L, 4.94682830703508395886779775564904786e-415L, 1.43550778574773554814450699757551163e-408L, 3.30662278156545301906789072182270217e-402L, 6.06763076341882342375981845143813941e-396L, 8.90102295078976467641802004915383639e-390L, 1.04750026993369008379812665328207076e-383L, 9.92305977697594285442750520712185343e-378L, 7.59233047709729007268137313555513461e-372L, 4.70739644774061079459196244467224618e-366L, 2.37289471679140773116577190541471766e-360L, 9.75578189470698031776059091702014024e-355L, 3.28173795958592945075990020191630023e-349L, 9.06055778471501819614486253220513415e-344L, 2.05942153439035557149195606898627504e-338L, 3.86530964740245225250791387282901296e-333L, 6.00843270324960642367292431619041056e-328L, 7.75791717613089963209182313649669073e-323L, 8.34421688870272754369905134347321346e-318L, 7.49743392110895125137984446953806518e-313L, 5.64335493091932417079632230402715339e-308L, 3.56822312364224796215751885944182157e-303L, 1.90033575264131712027297219010231489e-298L, 8.54728045366493643486236298588028833e-294L, 3.25523625801393911932111212124054975e-289L, 1.05248047241632062076489482718979111e-284L, 2.89617776712893256185087414745466351e-280L, 6.79988531580997322799099912957691248e-276L, 1.36556351036663137564575797911341140e-271L, 2.35130154856703817933308580165070895e-267L, 3.47957918602140446743207712996488528e-263L, 4.43595246742156897562714682208015764e-259L, 4.88306826050902558584812739817346803e-255L, 4.65192688318894071322199120456680912e-251L, 3.84397217698170104458131412518090261e-247L, 2.76116826189849718252009792299798034e-243L, 1.72788148193695597819524956747708857e-239L, 9.44000021446169518374327174980091189e-236L, 4.51212554821909958969480138145008725e-232L, 1.89078188020015147413152497967774898e-228L, 6.96047357819953940988624584998189879e-225L, 2.25551400000095886908107215813083451e-221L, 6.44644677476230409449870129589571800e-218L, 1.62820413693305623578289570883910133e-214L, 3.64118898140332008867604954881435445e-211L, 7.22342104300488240353501601432620632e-208L, 1.27354621995150979542739771832851778e-204L, 1.99918407175965223164864543465886820e-201L, 2.79923301669228713128194864334595626e-198L, 3.50221902155243103789141550909762023e-195L, 3.92214264392110857739154085058742459e-192L, 3.93845056335503285763060194710496279e-189L, 3.55208932101704820479562248595366349e-186L, 2.88218576501349132033303488025583146e-183L, 2.10742246561673617325867420889217990e-180L, 1.39082883056909297835969428096996258e-177L, 8.29809184041509702782403322046680024e-175L, 4.48275079028324875908925844854947607e-172L, 2.19604664947993546897548946859268970e-169L, 9.77074245531826439290686011595488065e-167L, 3.95412900034836577575737163397063382e-164L, 1.45763752143522946134851229157315125e-161L, 4.90175908594770144816169627656347413e-159L, 1.50583242362081439890282730822964005e-156L, 4.23187210926299952258468916772463829e-154L, 1.08947970178510600143883902241342972e-151L, 2.57292238715065164920970933548863818e-149L, 5.58131105433415694107142145348480095e-147L, 1.11357590012697004029170524556205260e-144L, 2.04616505133228608383036998688279538e-142L, 3.46699488500477063569923373366652510e-140L, 5.42379540407350192206120227447952764e-138L, 7.84383327240284700975116490839187822e-136L, 1.04992295793319441478934809931921214e-133L, 1.30230107195741860304672567525213181e-131L, 1.49865973782839300796909511415792928e-129L, 1.60190662241428628230308870106117967e-127L, 1.59224861840198356125270425396669689e-125L, 1.47337534591643627391632824044256382e-123L, 1.27065155139400959289502878067800521e-121L, 1.02240826352576620907328663762929630e-119L, 7.68376260232956278119400404906698852e-118L, 5.39926812723337318582425048609813182e-116L, 3.55107427485349467569160645183534302e-114L, 2.18823540951912101048500342930263842e-112L, 1.26466751543081693428147968135946762e-110L, 6.86180756673724371219029573988488620e-109L, 3.49869168682520996337772693940273721e-107L, 1.67801680739837515692197356611469711e-105L, 7.57743943144193148982405002124429739e-104L, 3.22470377015938680899710533122019572e-102L, 1.29448709067770596337952427228314258e-100L, 4.90613325096345413914934529363944533e-99L, 1.75712131798815332550332783841135938e-97L, 5.95204249145432038279376449394263726e-96L, 1.90856665328641726356485393831448064e-94L, 5.79822445923642921233565089484060205e-93L, 1.67029323997833472695510332615399040e-91L, 4.56623667339808303761814383193281614e-90L, 1.18561734279154794522720467403607684e-88L, 2.92616002780129692916694825399426567e-87L, 6.87006113412670713749912656047162470e-86L, 1.53556578350037994526862611062995548e-84L, 3.27003673677840125658578850353789865e-83L, 6.63955800720658036202444029681088661e-82L, 1.28631975096739859347518450406626244e-80L, 2.37956658113902295790875474474928153e-79L, 4.20626823139888342521923162463424944e-78L, 7.10971923783337943250783648529172174e-77L, 1.14991510411537277718541841100610582e-75L, 1.78087620125559422021122815240864113e-74L, 2.64270379617932988289762938432353092e-73L, 3.76008537594171932684988546369276565e-72L, 5.13292095112425199264463076393673633e-71L, 6.72710027460142769581137467118289653e-70L, 8.46958562134769749810317782657268756e-69L, 1.02503238267223284787859415412841523e-67L, 1.19321912755786334798650299344282298e-66L, 1.33681693038130658171632078204446788e-65L, 1.44228347967979838541089585366023007e-64L, 1.49937455500479399063651651865716553e-63L, 1.50279720313350143765006477517598013e-62L, 1.45300596931848530329429215240805653e-61L, 1.35598044837786253974814702268132430e-60L, 1.22207241221255212718220407758970979e-59L, 1.06422318027052015901612579353436284e-58L, 8.95966739607563684498250506056071091e-58L, 7.29628880807929410507791279851435148e-57L, 5.75025529619018115782221236649660618e-56L, 4.38801166482901351758297994035262224e-55L, 3.24385245129183239778054564241318804e-54L, 2.32423935766553880551312730791561599e-53L, 1.61486977620302644603098163288002715e-52L, 1.08852460554527484166896264813585652e-51L, 7.12175557419282904469498440847683331e-51L, 4.52464766254906707378983948806266105e-50L, 2.79273071581879303547665803856393705e-49L, 1.67538487960386422664995380528599268e-48L, 9.77311432877767609128920687351148833e-48L, 5.54591076684762708155258243373876422e-47L, 3.06280970562787364526087771025696151e-46L, 1.64686211803826623376300968100335938e-45L, 8.62510851388715584666563483664725226e-45L, 4.40168766386889070104410967553191993e-44L, 2.18975577884764674623829698191429056e-43L, 1.06234533644926588892221744026505121e-42L, 5.02803666348568404922856964957017674e-42L, 2.32252463571724922291588384046952088e-41L, 1.04740659389834130621977678673036650e-40L, 4.61343838844969816849890851044847674e-40L, 1.98539744511816200515536891243051363e-39L, 8.35102736745462834322783293199882340e-39L, 3.43444090348454338873945310910863585e-38L, 1.38148913187719664577281415801326678e-37L, 5.43705120131022522415564030011104834e-37L, 2.09435754808064771674030165617400032e-36L, 7.89867661859200690211003183623252601e-36L, 2.91753687094747127218152557081492503e-35L, 1.05578888602271659701510267800456427e-34L, 3.74433381216033081152946793044225824e-34L, 1.30180118525195729018565371931285108e-33L, 4.43834621689338776826444391843192077e-33L, 1.48434826895181654234585115302567433e-32L, 4.87100112984983697071424260901079389e-32L, 1.56890300074251394167498791840311009e-31L, 4.96129531591793523529868958902224169e-31L, 1.54077391002799082070667599670892752e-30L, 4.70055802217201491012415527477898338e-30L, 1.40911523071894959581827729743208189e-29L, 4.15191310395569203370171887252329295e-29L, 1.20273761371542774812275721780834541e-28L, 3.42632737493449673556641936029297478e-28L, 9.60140535939702601155477307042148556e-28L, 2.64727864203377330130778700812469317e-27L, 7.18344222056514710304108009603342664e-27L, 1.91885054598149404233254994607045127e-26L, 5.04697477945599249407828848720385551e-26L, 1.30739479992591170007499101639277446e-25L, 3.33634219823695708156517864262133521e-25L, 8.38925958113626219399750986165640649e-25L, 2.07905181351354860827899559955891196e-24L, 5.07917896724376528007260946058158296e-24L, 1.22350179435783727784530143589061714e-23L, 2.90665491105754953014975765085018324e-23L, 6.81166860609501546977145188171063268e-23L, 1.57498593823802530267320052674032470e-22L, 3.59379678896934832551131875550134077e-22L, 8.09418541120521256436201968800902213e-22L, 1.79979618323748172103553749785052354e-21L, 3.95175890164101728455789689950582204e-21L, 8.56958006805086577463240518925283894e-21L, 1.83575348651729869648335347322858802e-20L, 3.88541433996602231722399876322981769e-20L, 8.12661397289502178971121801417655470e-20L, 1.68000718288950314093575786904308274e-19L, 3.43336935156396282804714345750464903e-19L, 6.93769555039942749928599832442683686e-19L, 1.38634563100898175510110455954156138e-18L, 2.74008749775923088060873199170519103e-18L, 5.35757028868338662612872498580241047e-18L, 1.03646493302280378406673184005440162e-17L, 1.98424944201008499240310250250687800e-17L, 3.75978800606000340899396301904932318e-17L, 7.05221126182168479511704811938887205e-17L, 1.30963564152954622082996853685780292e-16L, 2.40827549610918052797562865726934570e-16L, 4.38589880961171155211843738902302126e-16L, 7.91175868684912128549216604428547791e-16L, 1.41388359787718387270571947224924145e-15L, 2.50347753664468021020115723250325879e-15L, 4.39263786655070582741822344903139686e-15L, 7.63871030696057461236914444427999640e-15L, 1.31670336037747604093705380830550144e-14L, 2.25003102727544891850217684727399098e-14L, 3.81223973341221495282227985716493129e-14L, 6.40502166019136347918960755019998163e-14L, 1.06725053827031948353711195948826425e-13L, 1.76389749378472101040375240485184047e-13L, 2.89198756533454775599767608849931393e-13L, 4.70424252036995808470327107927435060e-13L, 7.59287827351269198973041796516049688e-13L, 1.21618333837252517178450702971971531e-12L, 1.93338859343662487903047794738683986e-12L, 3.05082685244229075126272877890267121e-12L, 4.77908002001763665704541557372044375e-12L, 7.43273471338542509759247990082208445e-12L, 1.14783388812587366578078714999164060e-11L, 1.76028616037242275427822154657272751e-11L, 2.68107110162395316788540367212924769e-11L, 4.05602375429596543728262134893310443e-11L, 6.09544349224153722159236648112669209e-11L, 9.10055012961606421079182569690846497e-11L, 1.34999345213696765153127846451643325e-10L, 1.98994391239515605127817880646635584e-10L, 2.91499607361905978799020781323598840e-10L, 4.24390078141221962088655373293736779e-10L, 6.14135316267139108184909214050184662e-10L, 8.83436579589479851125156253066831718e-10L, 1.26339559402593316965102282486280599e-09L, 1.79636925005171604673781604814805685e-09L, 2.53970414332648086166213535713251755e-09L, 3.57059249828789049877331667413514712e-09L, 4.99234840315053910682137402914672922e-09L, 6.94247187048993148295924434414634261e-09L, 9.60294960016456137105057353194608309e-09L, 1.32133371276166677672139906194961059e-08L, 1.80872790163534638977965561238944112e-08L, 2.46332536476779151638500763225429049e-08L, 3.33804787013687049574791297244907192e-08L, 4.50110842610850506871431532628603516e-08L, 6.03998541333325959410060827223996830e-08L, 8.06630537452609783391065479881400036e-08L, 1.07218105901889261435737857618298194e-07L, 1.41856144379535399139351236825663488e-07L, 1.86829769983638330491745888879438028e-07L, 2.44958653917297200861483891225150109e-07L, 3.19755978044276083153634882857883309e-07L, 4.15579069086754433405340505039048729e-07L, 5.37807971332554467827633744547482376e-07L, 6.93056106477668619385798002644561466e-07L, 8.89417585250212245375810218669817408e-07L, 1.13675615786872600638029106996132895e-06L, 1.44704121253473089806789252868181132e-06L, 1.83473664533283350419063698449974520e-06L, 2.31724882235425364363184937796552995e-06L, 2.91544022582530391094107183656707013e-06L, 3.65421570986355186992807571629053921e-06L, 4.56318857677376015133362727471956847e-06L, 5.67743390948223287752620793591929613e-06L, 7.03833674730757178417069911600525632e-06L, 8.69454275808306722839276847105496531e-06L, 1.07030190270275985848630609511672890e-05L, 1.31302324393740374972736712543053054e-05L, 1.60534528678907389671161995891497537e-05L, 1.95621879772878044903047444244351033e-05L, 2.37597559155521886172243888058434365e-05L, 2.87650014695436120790473222143336354e-05L, 3.47141604126307620878569429267584729e-05L, 4.17628757618591523872557240511914786e-05L, 5.00883684896740377264076716570754303e-05L, 5.98917639018173037280503906445049523e-05L, 7.14005734028021322676450426011314791e-05L, 8.48713297304976003620620060812799411e-05L, 1.00592371962099993408798498455907607e-04L, 1.18886774688549697317681023800631139e-04L, 1.40115413739806927896468824589692520e-04L, 1.64680158738873124934815777767252928e-04L, 1.93027180590427177790609959505517465e-04L, 2.25650359795433055575151925625868196e-04L, 2.63094779253370712822446127059315509e-04L, 3.05960282998094618038061759727754321e-04L, 3.54905080142515530273890819014315333e-04L, 4.10649371213184272695586730470455583e-04L, 4.73978972070856543596623702324547537e-04L, 5.45748908769705106925744948564871657e-04L, 6.26886955037988466777589811218012335e-04L, 7.18397082597597367255394668144143647e-04L, 8.21362793308292890121036733909194916e-04L, 9.36950301151796636389593916360605611e-04L, 1.06641153138572518429387087881256567e-03L, 1.21108690381909541715522898126065244e-03L, 1.37240786710764633931488483556773354e-03L, 1.55189915125250562428574475103346186e-03L, 1.75118070611954731846143391024982058e-03L, 1.97196929478447094442182021751059029e-03L, 2.21607971185090897097885205424488147e-03L, 2.48542559858177963603431553204765315e-03L, 2.78201982871899325746660736300345366e-03L, 3.10797444123022017600460098808123935e-03L, 3.46550009889599377554207066240202628e-03L, 3.85690505461395961880575720620871256e-03L, 4.28459361052363939313848682793859897e-03L, 4.75106405851509722505038175681427297e-03L, 5.25890609434561842084606413815284753e-03L, 5.81079770141443579933464319447926318e-03L, 6.40950150419891594280210549702450453e-03L, 7.05786059539697018633739598386855559e-03L, 7.75879384490912344645900750924930976e-03L, 8.51529070288836937235862937785994511e-03L, 9.33040551314529952303815524992440065e-03L, 1.02072513571791257196870650265821749e-02L, 1.11489934529722276019901656254303012e-02L, 1.21588421363983657377673415921445027e-02L, 1.32400454566162946339651246079183099e-02L, 1.43958814201171884975897081297216705e-02L, 1.56296499211348507284307663166667625e-02L, 1.69446643988840458394481431193257832e-02L, 1.83442432645398203334614155955590374e-02L, 1.98317011429883687012533532738687781e-02L, 2.14103399761506788853091011534572156e-02L, 2.30834400360906269037251797223442256e-02L, 2.48542508971601536767883257823339293e-02L, 2.67259824171004266947925047187844041e-02L, 2.87017957773082030971446046374914401e-02L, 3.07847946323935695276863138190467659e-02L, 3.29780164187051571955970986393933287e-02L, 3.52844238706916706398930809090405599e-02L, 3.77068967928172889046621767464058045e-02L, 4.02482241332694163505581270228186661e-02L, 4.29110964039093677010619866631701642e-02L, 4.56980984888413264034413616112869595e-02L, 4.86117028816359215545912812117182378e-02L, 5.16542633886674445449455067720287452e-02L, 5.48280093332349644585895096278308003e-02L, 5.81350402921654268021994051667911914e-02L, 6.15773213934700546744487567673172633e-02L, 6.51566792003733016470332458328988615e-02L, 6.88747982036856640340840950741077307e-02L, 7.27332179410771208959941663503595393e-02L, 7.67333307583556615050326531083587939e-02L, 8.08763802243933982425303227000944183e-02L, 8.51634602078983074689360505021182257e-02L, 8.95955146208286742294968393977769930e-02L, 9.41733378299144489750576704343915921e-02L, 9.88975757345080247656478735188449399e-02L, 1.03768727505857796722978821461546404e-01L, 1.08787147979900856678514246787241454e-01L, 1.13953050692823999603416543952272158e-01L, 1.19266511545960614110252460361458099e-01L, 1.24727473084088741556780346524879069e-01L, 1.30335749368884349581460099687500407e-01L, 1.36091031427173401966757170543046798e-01L, 1.41992893251724361991875167825655695e-01L, 1.48040798330635148304426193810368709e-01L, 1.54234106679899202351157467338543629e-01L, 1.60572082352486356465237071613156643e-01L, 1.67053901396246033471214692284653203e-01L, 1.73678660232131774208044201415508905e-01L, 1.80445384423654491197811595430697492e-01L, 1.87353037808093115326776430258837481e-01L, 1.94400531959820109714578533182084599e-01L, 2.01586735956129211498107459964096125e-01L, 2.08910486416176267158329341893267875e-01L, 2.16370597784052818695266702661187610e-01L, 2.23965872827597104489240738884195628e-01L, 2.31695113325298676464455224512869174e-01L, 2.39557130914560734720290079897448420e-01L, 2.47550758075638008786996132954185789e-01L, 2.55674859226756791227887436442350007e-01L, 2.63928341907236639931045094151784107e-01L, 2.72310168026859366788753574972476498e-01L, 2.80819365161259349748148678323641718e-01L, 2.89455037874729232565423711864655899e-01L, 2.98216379053536250342702367445487260e-01L, 3.07102681234616603556790972526892770e-01L, 3.16113347916348760019249138447488231e-01L, 3.25247904839992014226666657864488014e-01L, 3.34506011232305314043635112310304911e-01L, 3.43887471001825077739424147442217492e-01L, 3.53392243883271879333889785572599272e-01L, 3.63020456526567529072712529376719554e-01L, 3.72772413528969943076239230990758849e-01L, 3.82648608410867702369280704118517439e-01L, 3.92649734537814481801171047048544340e-01L, 4.02776695993421447225756159687866121e-01L, 4.13030618409759875566958499890031988e-01L, 4.23412859763953990585030832527434639e-01L, 4.33925021151663415382683548295156320e-01L, 4.44568957550164552554831720660662401e-01L, 4.55346788585740186021655771168112611e-01L, 4.66260909322076961243786064631384911e-01L, 4.77314001088352176735947056292312804e-01L, 4.88509042367666263602229097070513234e-01L, 4.99849319768447906973686731056178972e-01L, 5.11338439103428142948352352152044385e-01L, 5.22980336602751811729499672944460101e-01L, 5.34779290289774015573364455286468490e-01L, 5.46739931550080955287380242064660003e-01L, 5.58867256926284616744877484869191055e-01L, 5.71166640173175841717312971842336611e-01L, 5.83643844609887615578228626088462787e-01L, 5.96305035807827889758567710635182685e-01L, 6.09156794655297569062821736349343099e-01L, 6.22206130841923771587050175584017347e-01L, 6.35460496808321163697317796410781296e-01L, 6.48927802208755868138883757264025330e-01L, 6.62616428937038679525110869491604161e-01L, 6.76535246768429422677267756666823087e-01L, 6.90693629673005399383708050292572666e-01L, 7.05101472858747991895757442966727674e-01L, 7.19769210605547537680146085503476253e-01L, 7.34707834954433431482100014962668745e-01L, 7.49928915319620942104629439591963551e-01L, 7.65444619094446439133009723643838630e-01L, 7.81267733325957766141060146767846541e-01L, 7.97411687536856786535849810135961905e-01L, 8.13890577777678436208431256995493454e-01L, 8.30719191996558177068293937598919209e-01L, 8.47913036818712374055336621201445842e-01L, 8.65488365832860347537655780480228440e-01L, 8.83462209487281076620051655836621909e-01L, 9.01852406704052162112602532863159232e-01L, 9.20677638326296314246112109641174382e-01L, 9.39957462519996315051517977272639457e-01L, 9.59712352259170728365681565566195274e-01L, 9.79963735030970038685207606899372777e-01L, 1.00073403490559993309000835270230984e+00L, 1.02204671712495200986974494164817378e+00L, 1.04392633537347289336664619627296763e+00L, 1.06639858190518516071876464455235265e+00L, 1.08949034071194662751500934725633506e+00L, 1.11322974393006216402411430386892104e+00L, 1.13764623169531331372630723630321340e+00L, 1.16277061567042026013306680494416940e+00L, 1.18863514648397907083703649648730714e+00L, 1.21527358533611238960293477132347556e+00L, 1.24272128004352904999786719958821158e+00L, 1.27101524581551079885511358011134290e+00L, 1.30019425107264471110982901454765895e+00L, 1.33029890864201997125110745686528366e+00L, 1.36137177268624019179654148863686280e+00L, 1.39345744174911173037014751038646328e+00L, 1.42660266832841175766232711333173310e+00L, 1.46085647541588835802048454309412779e+00L, 1.49627028047678533760134362560179034e+00L, 1.53289802737592016874439144914426210e+00L, 1.57079632679489661923132169163975144e+00L, 1.61002460572564642000849608863176067e+00L, 1.65064526666943143532240244567555108e+00L, 1.69272385721798833166204038375277879e+00L, 1.73632925074497773069781144176863796e+00L, 1.78153383899165490255124499430464714e+00L, 1.82841373739108738124596203605065226e+00L, 1.87704900404072044775471792428672248e+00L, 1.92752387330408763463712892863710673e+00L, 1.97992700509947708650365975965257989e+00L, 2.03435175101694043322616088522632134e+00L, 2.09089643849576621383396167595935906e+00L, 2.14966467439309042108153883973067514e+00L, 2.21076566938140221236799358744093376e+00L, 2.27431458472911392711904220601704565e+00L, 2.34043290314497023966214961240421096e+00L, 2.40924882550482707578395780381837657e+00L, 2.48089769542928804270777308901824137e+00L, 2.55552245384400165592583716337259322e+00L, 2.63327412583237088656291310907475315e+00L, 2.71431234228441160768610076838330351e+00L, 2.79880589905706635256578441640292763e+00L, 2.88693335659214188612865513175227518e+00L, 2.97888368319007786718164917079966461e+00L, 3.07485694541305021056656397487876403e+00L, 3.17506504939176568339259231884822943e+00L, 3.27973253713925527986226523992226922e+00L, 3.38909744233483410200034132396842728e+00L, 3.50341221043527586541966899038246748e+00L, 3.62294468840159570502872359754361586e+00L, 3.74797918980246258518386393043115941e+00L, 3.87881764157340380510220562013091253e+00L, 4.01578081927931267029397913978942025e+00L, 4.15920967835153616848634566919310171e+00L, 4.30946678945578836835486232808829311e+00L, 4.46693788689973689723986043138805888e+00L, 4.63203353981649359057533901265089751e+00L, 4.80519095677036072684883899803335247e+00L, 4.98687593543289697160079921623416533e+00L, 5.17758497008053768765855285400689531e+00L, 5.37784753088062976076034128768012631e+00L, 5.58822853027308803485444007033170411e+00L, 5.80933099323364005938466841106588229e+00L, 6.04179894983708948784718604678234941e+00L, 6.28632057034228591922334730387683243e+00L, 6.54363156501365266125399451934329088e+00L, 6.81451887309858260791767579514605499e+00L, 7.09982466781971868191373433617700078e+00L, 7.40045070694293100845796745008949286e+00L, 7.71736306147578881407568826714170705e+00L, 8.05159725837127958401987584151171259e+00L, 8.40426387679538395058384455428283593e+00L, 8.77655464160750010892022612040926275e+00L, 9.16974906224756520705691589269677116e+00L, 9.58522167027699388874228356777329920e+00L, 1.00244499144430070386099274885141050e+01L, 1.04890227783960385614814296197680936e+01L, 1.09806501931649260624015170997236345e+01L, 1.15011733242716998455210622743445835e+01L, 1.20525758220454727952816341992419823e+01L, 1.26369961333845432419384699684768677e+01L, 1.32567409840433238017603739136360460e+01L, 1.39143001526287336814820956823084828e+01L, 1.46123626710408671221171338391349055e+01L, 1.53538346012683753120053442509520620e+01L, 1.61418585554581184591279187098492208e+01L, 1.69798351452575852400510409025135738e+01L, 1.78714465678460133882677098961576727e+01L, 1.88206825601317848442892749807248071e+01L, 1.98318689796476498521560439791262319e+01L, 2.09096993011184544989073368255312499e+01L, 2.20592693519609552724995680207860407e+01L, 2.32861156486188168325833440616926330e+01L, 2.45962577392286013760094208279475314e+01L, 2.59962450073299827601794849672397508e+01L, 2.74932084469488923833030086627802945e+01L, 2.90949179822819598429999086944366938e+01L, 3.08098459764107671506384842333391345e+01L, 3.26472376541418040006352140116179211e+01L, 3.46171892555432186128355184008936311e+01L, 3.67307348405744306653537849794079228e+01L, 3.89999427831545697992227880433189487e+01L, 4.14380231271361842696931290595974334e+01L, 4.40594471293014233018696008435982161e+01L, 4.68800804884035743932352319123055757e+01L, 4.99173319575866229822636583993237381e+01L, 5.31903192638729836914160122380617184e+01L, 5.67200545170346581087003708738282234e+01L, 6.05296515859483113978235132985845589e+01L, 6.46445582591583649124780712968047055e+01L, 6.90928163944313177415529394071665670e+01L, 7.39053537072521168719419511314839173e+01L, 7.91163113594234348927381617490387462e+01L, 8.47634120965947230809397578710282148e+01L, 9.08883743598215272174601093484125344e+01L, 9.75373785753325382322893051705294986e+01L, 1.04761592725164736089639534479074532e+02L, 1.12617765338655419662606911403899284e+02L, 1.21168895243741881709481972315918511e+02L, 1.30484988804359382802013970413388238e+02L, 1.40643916977370870089294791135734370e+02L, 1.51732386386376598946153144686407135e+02L, 1.63847040773982427929709267988083986e+02L, 1.77095711710003361983546853982729852e+02L, 1.91598840361277588527216638598210664e+02L, 2.07491095540949726522855395012839290e+02L, 2.24923217236106119394568010864647153e+02L, 2.44064119463086993590008673999888577e+02L, 2.65103291739026696423162894476095053e+02L, 2.88253544828036421249450783362468048e+02L, 3.13754153889742451327114437895012151e+02L, 3.41874460927761232190324931320648150e+02L, 3.72918008746121432097478949634992228e+02L, 4.07227290759381879033987273956073881e+02L, 4.45189215310338987815842929936219157e+02L, 4.87241400038863092710563840938907565e+02L, 5.33879431809824993154116113611340152e+02L, 5.85665251340011311718653543776253641e+02L, 6.43236849676682281579530292235801252e+02L, 7.07319496933657861116096423723089184e+02L, 7.78738763222127723625961426334336958e+02L, 8.58435638777040682657342340030579928e+02L, 9.47484116394459954294416631122613257e+02L, 1.04711166630196929712820316594777632e+03L, 1.15872311371927743485840786701904690e+03L, 1.28392852534970775486315470390457819e+03L, 1.42457582618936343671625036189352836e+03L, 1.58278900639377570598543689683858411e+03L, 1.76101294444545923486104598108258215e+03L, 1.96206607357312178755673700966218336e+03L, 2.18920236070835422209657734442941355e+03L, 2.44618436034955965177471357752869960e+03L, 2.73736946076118709316717034422700237e+03L, 3.06781187080876763823587584403262657e+03L, 3.44338341950996275353420062305895100e+03L, 3.87091687821820770548262640961099474e+03L, 4.35837629346446550811483742251576785e+03L, 4.91505976942026055884439891778599977e+03L, 5.55184130321696740425893724460092414e+03L, 6.28145970445342612877221303833900020e+03L, 7.11886438520566571043900024525721790e+03L, 8.08162996762779959609851789890726579e+03L, 9.19045432173859727983153055486718404e+03L, 1.04697579405183570171054706781681133e+04L, 1.19484066394624731955974446656465043e+04L, 1.36605846306210479280006137726608390e+04L, 1.56468513163780927299848865296760921e+04L, 1.79554229917996753910020302361418910e+04L, 2.06437304374408251386790990436920728e+04L, 2.37803156373267080705808819875316658e+04L, 2.74471462199565095258711815725505419e+04L, 3.17424455248072273922403695999752070e+04L, 3.67841605073133622632674187774059283e+04L, 4.27142203777350805091608476572382608e+04L, 4.97037776810032398127125994364568099e+04L, 5.79596727313857616360132420453444344e+04L, 6.77324248460879259253530791773167141e+04L, 7.93261334694994276050922426242412735e+04L, 9.31107739715691545023768199956003639e+04L, 1.09537503053637222429417759669716212e+05L, 1.29157755673566952599086463851912376e+05L, 1.52647130160874158565239969760504587e+05L, 1.80835335096964828910095096138515211e+05L, 2.14743829477016418053483721316277484e+05L, 2.55633251557399994754680946686048161e+05L, 3.05063334556209750218324509503461449e+05L, 3.64968792666585395419705030588899790e+05L, 4.37755686685748537981529230100717254e+05L, 5.26424122294320873553623779329790816e+05L, 6.34724899010831940960718793968560727e+05L, 7.67360052654242646579956157559309383e+05L, 9.30240305033750278572545038832724621e+05L, 1.13081650266645184495081585123306969e+06L, 1.37850753115552374245055838415718322e+06L, 1.68525439396416227539607702063253047e+06L, 2.06623977016863939032179814240740936e+06L, 2.54082527022935491763036651163297626e+06L, 3.13377596203641663047341272710642846e+06L, 3.87686514827580239293595658539782774e+06L, 4.81098405401834942973721071475737211e+06L, 5.98892408953467866424875864774796159e+06L, 7.47905792960806092396497010475870265e+06L, 9.37022569869340886743682668142431718e+06L, 1.17782423097751066120254539266241595e+07L, 1.48545930143258061872721569284540776e+07L, 1.87980927038339810411221199415802492e+07L, 2.38705733443634639976678131975655720e+07L, 3.04180655225860320213756009749555241e+07L, 3.88995004684326215069338023547372206e+07L, 4.99257437458669601662091946924574592e+07L, 6.43128750449561321017861557895848463e+07L, 8.31551851992585813643149605060553440e+07L, 1.07925566470411796107305712037505869e+08L, 1.40614107339003511498586442587195365e+08L, 1.83920178567730560673713663331917338e+08L, 2.41519711690497536458569405379734816e+08L, 3.18438601538111228132801183275722771e+08L, 4.21576501892968673592102667497462836e+08L, 5.60444635691511454953230090792878868e+08L, 7.48209439804691157215633476755723997e+08L, 1.00317512966824615144294234414110893e+09L, 1.35089891899748286951692285814894218e+09L, 1.82722216505349159044967968934424570e+09L, 2.48263348083176093300905605774694855e+09L, 3.38857763723491971892999484076543171e+09L, 4.64662006529910564426883234085294096e+09L, 6.40182180156629712154379147661940269e+09L, 8.86235203805325147258573091932997831e+09L, 1.23283860285919681076337828978766266e+10L, 1.72348929748018002343932808836953853e+10L, 2.42153052846944737603768649152219024e+10L, 3.41967381320806302529104945578396652e+10L, 4.85431236462260654032773006433818623e+10L, 6.92714904376034267631798991329824532e+10L, 9.93804949018620361644641133903513098e+10L, 1.43352142475985414523266188918663249e+11L, 2.07922173448308822669953899424734201e+11L, 3.03269524182010815814751345567548609e+11L, 4.44863150372771043146060595057040363e+11L, 6.56345864647790105139454816812312939e+11L, 9.74063569639891097956397109813490533e+11L, 1.45422052005965615789962842879352220e+12L, 2.18425068889862732017431485970855335e+12L, 3.30099910475756075681442440083420253e+12L, 5.01997048502274901150163921982195024e+12L, 7.68267629901760783371009641842522603e+12L, 1.18337659600398387182686793240868246e+13L, 1.83474885355703531496992152648661997e+13L, 2.86363931245836358559523100954017414e+13L, 4.49980389271503995761664922194406313e+13L, 7.11948687698915449751693845544920647e+13L, 1.13430701798012234619458399048221594e+14L, 1.82006578236361839541514524597276231e+14L, 2.94148450061539403705926461420998342e+14L, 4.78870730589093038221910605812495108e+14L, 7.85402503692862355090784993078672085e+14L, 1.29789430461986025113447366376693514e+15L, 2.16127995478242564041665605678872071e+15L, 3.62710214703500383377916061381597850e+15L, 6.13534293344095037788551479051826967e+15L, 1.04617000636224450596060724147477482e+16L, 1.79847735783966568554234927670508824e+16L, 3.11747341233233147536151972501734499e+16L, 5.44944507304918422218082921598846642e+16L, 9.60751550501797821243248841373822216e+16L, 1.70858922445267785163471612163490444e+17L, 3.06542975111022866531582625971692938e+17L, 5.54922743745114951066953816028814728e+17L, 1.01373023277804631428305560194491190e+18L, 1.86905989587640582429259395332686294e+18L, 3.47854955238157842413369108802590798e+18L, 6.53599224597546376326701108631484361e+18L, 1.24001927226106630812645719537154550e+19L, 2.37582886691093662903464587039857427e+19L, 4.59768243360443262528520790447211677e+19L, 8.98810681683712842794124622629411311e+19L, 1.77530237939363226330723906827319437e+20L, 3.54341330439097348610370779591666976e+20L, 7.14806139767552532748817894789979543e+20L, 1.45762051057718630539520752847120279e+21L, 3.00513712487982979744944726506420716e+21L, 6.26502486163325069730377264873611059e+21L, 1.32097994109028381590144585332181800e+22L, 2.81748753590214622077676014001554368e+22L, 6.07993304142980523101356268020373032e+22L, 1.32765885364721208288263553578233241e+23L, 2.93431175918364131820516218129002628e+23L, 6.56508721680713002578214496043109168e+23L, 1.48721227343793765013154051597710086e+24L, 3.41184019607678812819334291291332010e+24L, 7.92818992879701876208212761012395842e+24L, 1.86645187702970485690987148720542546e+25L, 4.45252185988673954885155645168863932e+25L, 1.07654543517497766241465472692681594e+26L, 2.63868568119069758552386276646714408e+26L, 6.55790847024418649820013325410592483e+26L, 1.65295224373558572055534033842757998e+27L, 4.22638339591491619855432610245411904e+27L, 1.09645039426808014848951068590561771e+28L, 2.88682208299928608019375692651426610e+28L, 7.71548038934401592468282155249032740e+28L, 2.09372878930996484632394470400138705e+29L, 5.77027578944765503685743525710220950e+29L, 1.61546384539178114004658391605197219e+30L, 4.59547005579560869055708560274363012e+30L, 1.32862939268652325541488091880021431e+31L, 3.90507968153078421921910800039715306e+31L, 1.16713402427199725201363486127342874e+32L, 3.54805853865427740256789009746696294e+32L, 1.09737805935804615955239963430188272e+33L, 3.45410297806444559459316674852385198e+33L, 1.10674539370165232283645935543266144e+34L, 3.61089955913906999391756229494586894e+34L, 1.19994699928367056689901878605794596e+35L, 4.06268701419087879160332452792716198e+35L, 1.40183522389322451388311239745912475e+36L, 4.93108552733316217324966630695184171e+36L, 1.76881239328491949973951925349674313e+37L, 6.47214829394519996070845864216337266e+37L, 2.41645372173921192231147151489004683e+38L, 9.20894472039812386191245000342688835e+38L, 3.58329702862212667598998865894252598e+39L, 1.42409748259669944005518449916929857e+40L, 5.78262783342641152433806724533524027e+40L, 2.39986220408436318313990705343752378e+41L, 1.01829157204230545960231903208713235e+42L, 4.41910541482203453093956062976933998e+42L, 1.96212611768049931065065590432043620e+43L, 8.91674242406125370712417447773466783e+43L, 4.14888247829475772044491476179936724e+44L, 1.97725652955827692966670149947470575e+45L, 9.65530023387540108044378286001152781e+45L, 4.83287889833559892166961276593618835e+46L, 2.48057587822309805808523773881299449e+47L, 1.30610280975765470571043683527277027e+48L, 7.05756571728956923233902004974509542e+48L, 3.91527652222961861840270351783060925e+49L, 2.23089898094339331762072829615745302e+50L, 1.30614133449630930559423540813368509e+51L, 7.86102128665639262739828585146248224e+51L, 4.86558375853845110678814792824481696e+52L, 3.09848742591570467373735298285106117e+53L, 2.03103761486256390140847277681645261e+54L, 1.37099964760826020030246335833308722e+55L, 9.53473627432500152782873935909970826e+55L, 6.83495992316641540715754654005899263e+56L, 5.05273354632478901960113633106144814e+57L, 3.85381099728215997914445000026608173e+58L, 3.03418310785320829824308157124864982e+59L, 2.46716192600983889917114272951924381e+60L, 2.07290103981358059329932171745274528e+61L, 1.80056398057961538305615630314631614e+62L, 1.61776402789534425695658193709805813e+63L, 1.50428302825068832904492692640561694e+64L, 1.44839320652542717214779500803249160e+65L, 1.44485551098011579855868939330990133e+66L, 1.49412042885502924277326734308483245e+67L, 1.60256656610701572194891345599497651e+68L, 1.78388050415394298763315503064430164e+69L, 2.06199924057276073839995264039101124e+70L, 2.47652179469857271457600275335452230e+71L, 3.09234991415349735847967247784284417e+72L, 4.01692723830598581004567643058591262e+73L, 5.43160754522649738742682321649737815e+74L, 7.65008682404282275932608294522372170e+75L, 1.12301798411434928750045233045701052e+77L, 1.71938295296605200401018803799684912e+78L, 2.74733571869068667385885336550518795e+79L, 4.58454501055768412308971248876333874e+80L, 7.99508204153925025226317876728470146e+81L, 1.45811990936589904392804782726885652e+83L, 2.78300117867960017490532778932474629e+84L, 5.56281223196619462795860275879049153e+85L, 1.16533876898240457849831832137567995e+87L, 2.56039912643283822420817604614012086e+88L, 5.90454964185909819164533268125527979e+89L, 1.43027847474983870988836419822056214e+91L, 3.64204612295693256305339371887263313e+92L, 9.75669857120640229967783787120452211e+93L, 2.75194604427588305129487979774984195e+95L, 8.17916479364319727936284803066665955e+96L, 2.56370473508682589047202009616066313e+98L, 8.48165649612825587957771293185197099e+99L, 2.96426025440398100674466172613133159e+101L, 1.09534297003120888620652471421812455e+103L, 4.28314854758487062838465336068295133e+104L, 1.77395435294431974409395342323139198e+106L, 7.78899108189422475969140390458031321e+107L, 3.62893172105682135159715800277136586e+109L, 1.79572927251602059220958063790243562e+111L, 9.44668515148283533862523011302496150e+112L, 5.28826317961448810089554134850695191e+114L, 3.15331123674140136231493452577546350e+116L, 2.00480707968382766860514611914082879e+118L, 1.36040719266523771611516008331762962e+120L, 9.86282560980781051743602195410395887e+121L, 7.64755178859112809938428139017982021e+123L, 6.34880222487173008841344329862213996e+125L, 5.64906236198001909791959175488227229e+127L, 5.39324800352378478055022039572371179e+129L, 5.53089719191570391565414448432944942e+131L, 6.09959864464089433289271654904908851e+133L, 7.24209843349196450391058906977712497e+135L, 9.26808305363737556950784175210077690e+137L, 1.27994270241604058214925694813276489e+140L, 1.90979662696062130244831484512150929e+142L, 3.08254030066988503957988563764712878e+144L, 5.38880973238417965706179354197373928e+146L, 1.02161025105662653467101460483765248e+149L, 2.10300544007279065014421211807768152e+151L, 4.70675399034872557015773705065650223e+153L, 1.14683412812524899101968167573148610e+156L, 3.04620262376779901134561159740015427e+158L, 8.83255301555740088857655282843830654e+160L, 2.79951315833790052768515917244690507e+163L, 9.71307000884329724595836237775132776e+165L, 3.69425449543187541186652254254454177e+168L, 1.54248755204034481247092284401752383e+171L, 7.08075007659653083674442572183052884e+173L, 3.57888569536270290704774796012385631e+176L, 1.99473765641034107285413476042860568e+179L, 1.22789700989638770500092926180435793e+182L, 8.36095001442791620159284429240141671e+184L, 6.30749438488829733664127973626729614e+187L, 5.28039699582730274851611343025005913e+190L, 4.91356459266260178144685151251583280e+193L, 5.09061556382806163145943155929283695e+196L, 5.88195913486315120755496558081929324e+199L, 7.59272859182451584412681161192886089e+202L, 1.09687154447604565252927157604063023e+206L, 1.77650105264457177914887205035954057e+209L, 3.23153511879574325299022213712900198e+212L, 6.61424415330008555964088497876375007e+215L, 1.52611134962392865764465743843181152e+219L, 3.97691502072254861067816109956158434e+222L, 1.17271592685350180601663411607927347e+226L, 3.92076851079784438154800269803529292e+229L, 1.48915601904650135853122181753421959e+233L, 6.43831323019893638007682069747894997e+236L, 3.17506717851901774760997889290937204e+240L, 1.78970981603629426034165602936202663e+244L, 1.15551435950001094003467361479483663e+248L, 8.56366431033316582912879348191377839e+251L, 7.30093770528170061921940254565023758e+255L, 7.17613138815551609337504025522760569e+259L, 8.15019404042552378087870259624107791e+263L, 1.07201229194901841245742935320285314e+268L, 1.63677814658507005123653360340510968e+272L, 2.90775562270833690431514296460636317e+276L, 6.02476179304325236422526103127046739e+280L, 1.45944561364291559252990517774206937e+285L, 4.14353248208966528107409825739318649e+289L, 1.38220972739972368321976302536673924e+294L, 5.43125471568796436605394023488404770e+298L, 2.52039989595272682474151246524004609e+303L, 1.38490332203279628724542169932072504e+308L, 9.03453415480179250943103381623811201e+312L, 7.01620311300324094081813342355630834e+317L, 6.50430483422567669743617206850738485e+322L, 7.21793562600493199951776097195343971e+327L, 9.61542788471746566451160668498411528e+332L, 1.54211655565340209996546117001243607e+338L, 2.98626205265198316430063943341329432e+343L, 7.00309320577422492544778192980108604e+348L, 1.99486089518136492496460973366880635e+354L, 6.92350663128275446878446973158773950e+359L, 2.93684755383592258491626945473185368e+365L, 1.52739293250863294426010436780725812e+371L, 9.77075509850276765943058812672579852e+376L, 7.71310608088780517993569363011828070e+382L, 7.53863036472313339350939561575995488e+388L, 9.15331385155864163687518059055937567e+394L, 1.38538605697398143363179835422022577e+401L, 2.62287133256068615930266548676255190e+407L, 6.23343982286571042809890547122705804e+413L, 1.86628588041890755929921756251934723e+420L, 7.06492694188791912037300528166794228e+426L, 3.39406886800977749230458579824930803e+433L, 2.07704891812976483907563047536681219e+440L, 1.62532865525590176989706193358042030e+447L, 1.63262112354994112352218911327913750e+454L, 2.11342684365334123128646755974119857e+461L, 3.53982137873383101244091847412793714e+468L, 7.70246700302666062188915359100825615e+475L, 2.18636422788338230254129077405708124e+483L, 8.12975261672049081897166938196495657e+490L, 3.97686557044826916151646962242652853e+498L, 2.57033035969007091507617008526033295e+506L, 2.20458407348036235529376715504150602e+514L, 2.52051509380683369529400145083533353e+522L, 3.85871376898138292734730034828559871e+530L, 7.94663225793828689108907007781152553e+538L, 2.21176541223395827472447113026924253e+547L, 8.35931033048630497134082029598865726e+555L, 4.31091797212556485985662056018893390e+564L, 3.04833317305882254988404372326531988e+573L, 2.97034828681146526635277450855709161e+582L, 4.00864404566992526097179834506253327e+591L, 7.53113144131492631353410204171028663e+600L, 1.97996763586022811207860344830247407e+610L, 7.32300332662100885299893727481183608e+619L, 3.83078680906847773947984890776183687e+629L, 2.84987258373806149506606754536239806e+639L, 3.03186631046306534459943952897407369e+649L, 4.63861318260680959360747724936035922e+659L, 1.02646622253495677529633262335412306e+670L, 3.30448344760519942319105428211388701e+680L, 1.55678514244926540491694986676104766e+691L, 1.07975219247204914347510266773073325e+702L, 1.10926415409608640204268413223928121e+713L, 1.69843188882084389205231670587156933e+724L, 3.90025209215096037836224226547246383e+735L, 1.35188796159061122898267917047667153e+747L, 7.11881895741722013661309086794573765e+758L, 5.73263787962641176699015570741387791e+770L, 7.10698682909851371094390920546530663e+782L, 1.36568905751347705631533710470350932e+795L, 4.09591384091714486453161283605440034e+807L, 1.93075428208975454032168180693618424e+820L, 1.44069783794868490577087909226154603e+833L, 1.71407451380697883211569548277738601e+846L, 3.27557874564463748685767424892341420e+859L, 1.01295195987435253561137255728975319e+873L, 5.10768437019276174029340754351596177e+886L, 4.23191986113702770379280941046346950e+900L, 5.80664714178397794019307157189161329e+914L, 1.32995815980583547946711112525038194e+929L, 5.12600842672542100652183507817331030e+943L, 3.35203762278831767267193293263751763e+958L, 3.75009417204153826893896307870937057e+973L, 7.23855050824188975713471018223024339e+988L, 2.43146178229439003194650931378387467e+1004L, 1.43376736234835679429446577737976919e+1020L, 1.49738681485939897351147361037410278e+1036L, 2.79474808763788045317059787958854766e+1052L, 9.40752795141195895210630116566470676e+1068L, 5.76455681194134988563523968421696548e+1085L, 6.49098750070655215612470119412325218e+1102L, 1.35603677524062211064037225514112165e+1120L, 5.30731596106421482379267500594247426e+1137L, 3.93020043869734370491941322540535807e+1155L, 5.56226722613029149136813618379760709e+1173L, 1.51990408820680241841102181882025951e+1192L, 8.10228003417607034858018290055212984e+1210L, 8.51521180721994744419289716417963237e+1229L, 1.78329495296502824223674285976432097e+1249L, 7.52325725334531880022021234450122858e+1268L, 6.46447702663797449769360764507187142e+1288L, 1.14411796435953528891736478925455547e+1309L, 4.21851818337788742448241659152628519e+1329L, 3.27808619028067308419286053048979085e+1350L, 5.43188779501763188996015031600338462e+1371L, 1.94236185576822902995555282219996135e+1393L, 1.51711647857248503907031482339088565e+1415L, 2.62035716514505778741231466041668281e+1437L, 1.01340333806343444348385264050569250e+1460L, 8.88786410219005270769408353397020687e+1482L, 1.79062851327433476234422894649930707e+1506L, 8.39642792144232596950658702528918677e+1529L, 9.28628794761707451127390451820966789e+1553L, 2.45536895088636462839367313490581387e+1578L, 1.57354562229875356978426356241845302e+1603L, 2.47847583619098850454983740131691503e+1628L, 9.73157119375940175602769413110414643e+1653L, 9.66320447484532719750186034583884499e+1679L, 2.46232109538721189753853963925622165e+1706L, 1.63417596934387293040006746046570718e+1733L, 2.86767794799456586471233013913198039e+1760L, 1.35110548955493375904544893914917995e+1788L, 1.73592152545700077097814839827674920e+1816L, 6.17893831026015926230407301367680801e+1844L, 6.19169576655007716364858612984691562e+1873L, 1.77539961419331109157892833779912252e+1903L, 1.48102931564535770775910220632570312e+1933L, 3.65523833138677287346435504279580939e+1963L, 2.71500576533505130343548298805675281e+1994L, 6.17538661057993294979124427622665421e+2025L, 4.37773911614056336228335278244614535e+2057L, 9.84696637606677900175890481086698860e+2089L, 7.15679932872021171306956409599896671e+2122L, 1.71206538074954819527676482193571839e+2156L, 1.37358203471630226464631105286036694e+2190L, 3.76701670663930120912543386433302245e+2224L, 3.60043887764831236838085599723119708e+2259L, 1.22311399177140229476034440208616729e+2295L, 1.50662485913882109231872682750679813e+2331L, 6.86720031172136555587682118613084257e+2367L, 1.18233110675109495729851537371527994e+2405L, 7.85186218386652904615339091354671418e+2442L, }, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_weights.size() - 1); + m_committed_refinements = static_cast(m_weights.size() - 1); #else m_committed_refinements = m_weights.size() - 1; #endif @@ -515,7 +660,7 @@ void exp_sinh_detail::init(const std::integral_constant&) { 7.967275909080119173260394105433878829225e-2520Q, 1.018328235596330817906641738531405586075e-2480Q, 3.221582354315018745133234535022765889901e-2442Q, 2.577837396125923566854501272739510663846e-2404Q, 5.329692879048212454158155682964916728316e-2367Q, 2.907510479746435248283830679207105484516e-2330Q, 4.272515272958308108570054029079326796036e-2294Q, 1.725920944512128844318784735433112719801e-2258Q, 1.955365288532498067112004500362223834133e-2223Q, 6.33672146224698551106793067421941599521e-2189Q, 5.989055317923577956367893208101537342355e-2155Q, 1.682695935085939711542031154300739978911e-2121Q, 1.432104065344727957976083590066231975447e-2088Q, 3.761027283440035276506274748665174438543e-2056Q, 3.103973882224385163725384328628978101726e-2024Q, 8.196024681248225777873004659982426819745e-1993Q, 7.047501943265264073804265038957515028249e-1962Q, 2.008020122030836044260092764882735792941e-1931Q, 1.928585386478996757051377061536226588734e-1901Q, 6.349936504026115699331271816067930197654e-1872Q, 7.287319738451912662822173117194663954913e-1843Q, 2.962993354437338667093054088027903427137e-1814Q, 4.337549035352199493070093298251396522747e-1786Q, 2.322667953684500393631534979205588114281e-1758Q, 4.620940493203111397883251148877460552652e-1731Q, 3.46849175006702283349982309232738215393e-1704Q, 9.97197469066253825213923346003213563319e-1678Q, 1.114585267326982901794838942479030932334e-1651Q, 4.914714563824319863256125426084037061236e-1626Q, 8.673588082334046069888398076950448507162e-1601Q, 6.214129581324762232775539905301734104147e-1576Q, 1.832790291938882421191920578959728374086e-1551Q, 2.256171136581882657900944651081598896733e-1527Q, 1.175009240711975388097085650021684742673e-1503Q, 2.62368977120029668942611642547157610416e-1480Q, 2.545000194584350068428255601470918881705e-1457Q, 1.086378274323549748723752477385721065205e-1434Q, 2.066897696539443930872351598446447515579e-1412Q, 1.774772157298710208337196463122169403564e-1390Q, 6.963196512155587707171477008714118644169e-1369Q, 1.263545167784085371065018714077427939719e-1347Q, 1.073200483671541400965432755811734945193e-1326Q, 4.317082212314184926835882760831574340329e-1306Q, 8.32053604965395861253463941646191625903e-1286Q, 7.771734618559071081107688528229970310621e-1266Q, 3.557686044605213104209030012940037706499e-1246Q, 8.070528916876981426176871131000861955335e-1227Q, 9.171668926752907939883632747855449181794e-1208Q, 5.277894673647840384307719753102608158502e-1189Q, 1.55425000722110468554188982028632391378e-1170Q, 2.366680555098895290029405613091848674444e-1152Q, 1.882599225459190082401671846340953390019e-1134Q, 7.902192246540000601320781601302423345806e-1117Q, 1.767718149213402068974713376178812787862e-1099Q, 2.128098208048214966164629867555770669406e-1082Q, 1.392051591976656401133824170145523168896e-1065Q, 4.994719960920755555531504146997873320923e-1049Q, 9.922076126548449719468150236395605850173e-1033Q, 1.101311891894924117612397672953984177965e-1016Q, 6.892130837218420956087582351392004213975e-1001Q, 2.453524489921414170305853712838952078459e-985Q, 5.012096823429272595408207301327403858682e-970Q, 5.92625397256846848563576817503982351625e-955Q, 4.090293049633920583650165040912103911016e-940Q, 1.661753006709297398826495491631296133997e-925Q, 4.006680757962520202236462553833604795318e-911Q, 5.779925457403545302890808903391113431044e-897Q, 5.02848909102539886751126002796168835514e-883Q, 2.659105037910872144852205745069380936102e-869Q, 8.613275102396233614296997155697707276489e-856Q, 1.722011941149323047500322262512900155623e-842Q, 2.140858770279205828196814199482763570967e-829Q, 1.66733371240769894937624182878072907988e-816Q, 8.193863812957329774412230281809513275895e-804Q, 2.559097724964727559938640778629276385374e-791Q, 5.11527606584153978380615675677219021198e-779Q, 6.589313932434497001234913531610383100585e-767Q, 5.507550516048129444656311084411711270861e-755Q, 3.007020142650284579022887900120691321832e-743Q, 1.079545570904019147607701162275175357017e-731Q, 2.565046260212020805453775161290492247735e-720Q, 4.059551213679369050731379503131672168122e-709Q, 4.306509253842678754390905922017562669864e-698Q, 3.081277425837841400021155036519520671543e-687Q, 1.496049756497725324561151798326667339225e-676Q, 4.958858781223578709469932084235076593428e-666Q, 1.128776827757009886737844677649633126831e-655Q, 1.774824438031273259221674871341421861954e-645Q, 1.938718628529578614339845914362132261711e-635Q, 1.479580889476868168834482402842115319684e-625Q, 7.933076560959459481932759219061929332943e-616Q, 3.004696447884786585684784182577260233339e-606Q, 8.082686940259012888778153139360914820557e-597Q, 1.552426325390131757062306746548839627663e-587Q, 2.140102119938385745802494123096422882483e-578Q, 2.128429453740900159670547695806420238397e-569Q, 1.534912683226941140367083241016749973227e-560Q, 8.066256819954909759673837062709789215779e-552Q, 3.104238792273031330484452756380286340285e-543Q, 8.790844945644080595293305902463382662207e-535Q, 1.840618291261842948588744341179843557088e-526Q, 2.862777784664184513037699746755593033611e-518Q, 3.32279837181041061553234462323492937839e-510Q, 2.891235095586630121781435408715459157878e-502Q, 1.894375038101531296060137038995059871087e-494Q, 9.387752849968810937579512549662307625661e-487Q, 3.533872224235785186218523407943928105631e-479Q, 1.014810086945078087894935086994004318066e-471Q, 2.2324717569626557013949548912766445982e-464Q, 3.777884776738657261205533855337240737918e-457Q, 4.93786751664639347798897645870074547883e-450Q, 5.004920895479663677446497643024618520578e-443Q, 3.949427686727102477250133390725874321876e-436Q, 2.435767559087040930634684216214147613966e-429Q, 1.178587076580330886964544022890917953058e-422Q, 4.491023912606049854427428106653051102875e-416Q, 1.352680705533714285427651131064219006969e-409Q, 3.232175229700192859974514601701313013174e-403Q, 6.148979779244951167078060501065764873822e-397Q, 9.346618557699555690197507374939990133164e-391Q, 1.139095638725565354570660165510495028107e-384Q, 1.116882736988512594287339256913954444686e-378Q, 8.840180431626061992850152992185607078407e-373Q, 5.667122232091659511764331764542937857446e-367Q, 2.95210171074869287556924947738750388968e-361Q, 1.253616557485983210249402924206741962015e-355Q, 4.353499566130717956144486781651064963442e-350Q, 1.240243792752263780952771158279701378416e-344Q, 2.907393260879684488880153095982345233788e-339Q, 5.625244131026162975882364543895958678556e-334Q, 9.009739108786675273276970385188647555895e-329Q, 1.198087756353396256356294131034463223006e-323Q, 1.326548775108682048756687665666583870046e-318Q, 1.226448111135483120974035454571292238148e-313Q, 9.49468504349439811133142768178704940847e-309Q, 6.17181101323002240744175397407031718684e-304Q, 3.377707669589353604487497237523332765898e-299Q, 1.560512872109863571844393575758792286036e-294Q, 6.102236208573128122093888164692727956235e-290Q, 2.024929301988449522883491544065893159998e-285Q, 5.716567372402404783728122475078537540453e-281Q, 1.376428575092612476633988432370532525456e-276Q, 2.833585596240407856348272111949931080586e-272Q, 4.999632626016703452297995188196308401074e-268Q, 7.578746796653130874873290482021210756378e-264Q, 9.893195588497945068609978048738483752363e-260Q, 1.114710731734833240955445714249086995456e-255Q, 1.086588366772543409228146502433142567442e-251Q, 9.183764349360752966385023754968415218934e-248Q, 6.745119200393479925712383108023813390928e-244Q, 4.314368731526732239250885070923775496171e-240Q, 2.408432510386531771142800736481978254764e-236Q, 1.175865689260863816680634119022166918193e-232Q, 5.031403985679824041735142472001594305874e-229Q, 1.890676059338627176469623532390876131616e-225Q, 6.251957030364086922481747023515455758277e-222Q, 1.822832110299319014901260869272013670981e-218Q, 4.695228558883599546359502992313929137066e-215Q, 1.070485041990253205844787613056619988479e-211Q, 2.164411061170786494289133504038746022617e-208Q, 3.888149057834327052303287962939662414968e-205Q, 6.217077650284409358885672093877174576393e-202Q, 8.864490176680272259518995033084329107486e-199Q, 1.129060018025413968826902845797468943636e-195Q, 1.286873424792917053839022851662100381367e-192Q, 1.314795291417549889849051617164565642141e-189Q, 1.206202769586152888447188064879769552541e-186Q, 9.952847031230403569515431731634107940163e-184Q, 7.398656727363347668880677233416039563592e-181Q, 4.962946760441355726269312188537195172159e-178Q, 3.008841426137019577290269695130774172341e-175Q, 1.651250489636657038514219704463078872032e-172Q, 8.215822870116426810896344350411473632426e-170Q, 3.711707137271423160180212748621691502977e-167Q, 1.524862581521331587673406461025625884709e-164Q, 5.70508150602545345515626627261166302806e-162Q, 1.946690864521063015447882642259593648046e-159Q, 6.066751495971832907946605731816433411601e-157Q, 1.729218890749008111955745508052309562408e-154Q, 4.514184397107540977965003426103559880641e-152Q, 1.080776439193461578737828802075769030367e-149Q, 2.37630514513441024032933923861341092174e-147Q, 4.804539863300466911851715067980750771531e-145Q, 8.944359411396089882336022433298240800498e-143Q, 1.535148433653602528126818304598839769627e-140Q, 2.432217566861172517425147458255035408531e-138Q, 3.56159164851978783755994271005743068325e-136Q, 4.826206194592030239608964808604974782439e-134Q, 6.059123883793098626317651235341860311477e-132Q, 7.056186855737804734056421101084240937306e-130Q, 7.631197540594714170535291222444902661627e-128Q, 7.673190056935230923349040383785807876549e-126Q, 7.181420901238450533979697028062603205731e-124Q, 6.262949340804115487531782118695348240253e-122Q, 5.095149668836320992407738242504181244468e-120Q, 3.870905682539942846661487470875055347721e-118Q, 2.749201932883450268151961331830477076878e-116Q, 1.827228100144142861000456602099118570404e-114Q, 1.137673382674035107250733931604905546067e-112Q, 6.642336072005941146361966661287119272804e-111Q, 3.64028512339331626869107380312786986349e-109Q, 1.87450863444735780747041756540496602537e-107Q, 9.078133222842635422121285050940964351573e-106Q, 4.138812855052761279043494154268599225563e-104Q, 1.778000270650318764431469309976610087858e-102Q, 7.203855822800213289973969862777328396312e-101Q, 2.755303928538917650732532471686512499588e-99Q, 9.957111327196065437803034062710072445763e-98Q, 3.402816997218076148572057943527130789008e-96Q, 1.100680588716144971407937016574430544574e-94Q, 3.372653914433340593300308221192502433386e-93Q, 9.79793465921741389410002031066177808616e-92Q, 2.70089978913542155792813430020605674429e-90Q, 7.070447343835118744270507416522429771431e-89Q, 1.759128817422289300267493076673104253506e-87Q, 4.162968945574391702034525851121326185222e-86Q, 9.37779241810731989238679712769217329023e-85Q, 2.01243511678120567645753438316089357156e-83Q, 4.117122160765049554856907584525124497579e-82Q, 8.03596273765328793581294339359042233865e-81Q, 1.497514661862748564043414139894766607224e-79Q, 2.66627575240526913684138994676860937559e-78Q, 4.538860378486968408830116582994751799953e-77Q, 7.392623260932249293359287648677921377725e-76Q, 1.152810282079105430900943269743976641052e-74Q, 1.722334641963998877538919046212108072676e-73Q, 2.466982294003650362347496250523874402798e-72Q, 3.389902673647822893523319180268544603664e-71Q, 4.471576114525864494621630170567724674708e-70Q, 5.665802004349935660857687324817574414575e-69Q, 6.900180136205711399260007796162289923614e-68Q, 8.082103978670433565158160112244695539644e-67Q, 9.109949614051296700342120658333526754299e-66Q, 9.887660566787155914957022540708377404886e-65Q, 1.033978824499191800266695652953562102366e-63Q, 1.042367363142603472683903942222927019223e-62Q, 1.01360253850642711420235182625207856357e-61Q, 9.512510161747350299580075950049163390633e-61Q, 8.620693578866897400350402598749549001733e-60Q, 7.548215286708061079286950592874024396203e-59Q, 6.389002522263073684828225781548498851979e-58Q, 5.2304213467999807285495233989909068078e-57Q, 4.143618029730144849471458722659316057844e-56Q, 3.178215053889138479032361583006970626875e-55Q, 2.361375497747090350319603916992762005858e-54Q, 1.700353947901992650870275190000853698062e-53Q, 1.187181461482834292235814755757571995841e-52Q, 8.040926262915060358135936625876559056833e-52Q, 5.285800219918840044239185423363506533173e-51Q, 3.373901677142706872070242716798262993283e-50Q, 2.092036760993143554287714553393156854658e-49Q, 1.26071389736459024550376938832573535614e-48Q, 7.386967875256930161617715368501896621111e-48Q, 4.210245750567381301823721041940686239094e-47Q, 2.335212680852443576888813564758399301987e-46Q, 1.260975065550456669584777965304501230694e-45Q, 6.63174909295324620401889662345375243662e-45Q, 3.398355988046612747841700088585271753564e-44Q, 1.697476472841236183609850797662451898689e-43Q, 8.268085659326493130435461342952520749743e-43Q, 3.928638007500358866351367670626935931854e-42Q, 1.821720759355284457527987958132111168364e-41Q, 8.246860808847354549111270503081351496818e-41Q, 3.646064568177825762669789860457940857642e-40Q, 1.574882443754619623541008196995070064258e-39Q, 6.648395042005376085395386282489705285924e-39Q, 2.744004024875076628507083135601534661763e-38Q, 1.107653420681031633888214018454568434403e-37Q, 4.374454244420129201505123651246128890729e-37Q, 1.690799049659970724466269924181801546001e-36Q, 6.398132877939130220610010163346102651855e-36Q, 2.371103019047426350497793704573373960345e-35Q, 8.608431951088272831647481050248077098396e-35Q, 3.062756779443238602319536870269819051555e-34Q, 1.068198659583210038973746806524748536317e-33Q, 3.653227544700454531305797630670503225392e-33Q, 1.225515001519945073404871285296100665347e-32Q, 4.033738539559432392661992185921035446855e-32Q, 1.303082875824869971414005942159261214305e-31Q, 4.132734479820748852758173795520437853314e-31Q, 1.287147098350869770886623826581464367999e-30Q, 3.937913659653477883694284311172054333025e-30Q, 1.183782052799315485733017592458599891775e-29Q, 3.497544328892517187831545842100287032186e-29Q, 1.015914466727185220837422441064387754207e-28Q, 2.901804990894522420127448030270270503252e-28Q, 8.152849127534845411362622488936266274172e-28Q, 2.25367809417179806852681105934818375896e-27Q, 6.130912603089867849064196318283416796732e-27Q, 1.64178734291463510902060102240353937311e-26Q, 4.328857792089817047005743679842334899927e-26Q, 1.124084164810469092376383461223505192932e-25Q, 2.875386797856971912981506559923184846915e-25Q, 7.247144107627277984808094958723307043434e-25Q, 1.800156961022553615025218914199947112878e-24Q, 4.407829997906358459896106459287958053e-24Q, 1.064159909656974016807111538128709340566e-23Q, 2.533679394987778730189472745065558452445e-23Q, 5.950490597088776019748683578472561818409e-23Q, 1.378803645178565675477663430920122567538e-22Q, 3.152763311863490040779656649906049613957e-22Q, 7.11555798463800555819351867739855080496e-22Q, 1.585415769087416794558428166428232224083e-21Q, 3.488033184094363861639854904349888742437e-21Q, 7.578906150306100545423157126174164576149e-21Q, 1.626690309979793927151914765130208588376e-20Q, 3.449517091693030714666710333959651136005e-20Q, 7.228499497618258130899446599161547874565e-20Q, 1.497112865860816048764094432862181982629e-19Q, 3.065182400463867687382144796026279060458e-19Q, 6.204847831174082599165287964674983928818e-19Q, 1.242096716667761537684098553412968423806e-18Q, 2.4592597959525768067059363490903017727e-18Q, 4.81672896226015964045793790028985306539e-18Q, 9.334084950562834068284127795290557105276e-18Q, 1.789925014943490672474409292990156919458e-17Q, 3.397130025636848212544218713465822505885e-17Q, 6.382243159919550687632232044625421720437e-17Q, 1.187098865362206582279245836506254018227e-16Q, 2.186352889657557664550744789902758712378e-16Q, 3.987859744831167732326236478627157162656e-16Q, 7.204620697873539912480086209051030823416e-16Q, 1.289431790155955917841351554233503242944e-15Q, 2.286467374882308613486205332118436402814e-15Q, 4.017662252161183047836187284910855861237e-15Q, 6.99656785784342408232633767751107637346e-15Q, 1.207703613093171430146873960414485693713e-14Q, 2.066611834161126240026963698131523479667e-14Q, 3.506221191208017396780249818547308545177e-14Q, 5.89874025912113410833559535930664457693e-14Q, 9.841824583826900982294185470382304100122e-14Q, 1.628711979356644195640673557575737399349e-13Q, 2.673747297244544464041144412989940524217e-13Q, 4.354698030762685456146522867684472784597e-13Q, 7.037375613470243013811036742819534450189e-13Q, 1.128576426207602409839136130428624894649e-12Q, 1.796265444979361204491866760276216506487e-12Q, 2.837790274411961929167645624257533119362e-12Q, 4.450517051624898219124643410702559319937e-12Q, 6.92963583879943637167224732796899185484e-12Q, 1.071343498653279805152831768444006526848e-11Q, 1.644800798713549170982066141603139794962e-11Q, 2.507905928632347374338630836942320447304e-11Q, 3.798122183988670139277644917971882044735e-11Q, 5.713892308950583341199546461179201773938e-11Q, 8.539758065003606420501230564062147832472e-11Q, 1.268100729620471661902817410073941033457e-10Q, 1.871113767059724245386976661776370778825e-10Q, 2.743644295142664772759283079615343882946e-10Q, 3.99833185555888171640293913723530982506e-10Q, 5.791550996315273321902088121824651906299e-10Q, 8.33905623640836900250032445405370043217e-10Q, 1.193672562105227931589388299289134785728e-09Q, 1.698789266026923550073522461535190652611e-09Q, 2.403913727893853297080383302536080724682e-09Q, 3.382686884515520208065080745279262391703e-09Q, 4.733759174712641803740945710631487071936e-09Q, 6.588541092193685952258947629496486846735e-09Q, 9.121112685152380583998835576941094529702e-09Q, 1.256082033795070258308096624958598291786e-08Q, 1.720819844523096099720474511434503885155e-08Q, 2.345498050299132447846326603361136043516e-08Q, 3.180911042916052139309955352436778506108e-08Q, 4.292583225702628201046231718407734046636e-08Q, 5.764612626060727958623931970026984259394e-08Q, 7.704397341666848653267095123338097208871e-08Q, 1.02484168952891991947754465547361714047e-07Q, 1.356926702837583879755051597078815730847e-07Q, 1.788417551503950471950015064517069882061e-07Q, 2.346525819658947020385582160747980704228e-07Q, 3.065180852876392019694236336586654765768e-07Q, 3.986495033191807496354173430939013698484e-07Q, 5.162502188850122540844684197019554711165e-07Q, 6.65720997012649014040997771515440610649e-07Q, 8.549011167117627077144919459539055163198e-07Q, 1.093350316344842739482570460075507090481e-06Q, 1.392676894662565462032126480798341973487e-06Q, 1.766917725585667241992898344161547873865e-06Q, 2.232976345560288036947373699573375726808e-06Q, 2.811125648202381706895272765136403841401e-06Q, 3.525582061468103068665653163476736687771e-06Q, 4.405158376428709913646029278948069283329e-06Q, 5.484002631927202129384801097079834656695e-06Q, 6.802430623520435693108355760476215953221e-06Q, 8.407859685487256287710959317409001943954e-06Q, 1.03558513786321915073962476007182566071e-05Q, 1.27112705917308531277560249413305391114e-05Q, 1.554956831891198412168337708959965747403e-05Q, 1.895819499809689983959597375272763044769e-05Q, 2.303815077706507768668930312189393944145e-05Q, 2.790567840555153504276820390388733949771e-05Q, 3.369410362760997145481708684122315699185e-05Q, 4.055582696403286559517626972868029344242e-05Q, 4.866446962805309592997024360400453753624e-05Q, 5.821717500966089824845365574649413158772e-05Q, 6.943706569830923930053447899093868098698e-05Q, 8.257585439721267879079897718480289417549e-05Q, 9.7916605324640385949085647909368095273e-05Q, 0.0001157766408114819489026696755064685711663Q, 0.0001365105858059673951916433332558940095964Q, 0.0001605135409048256559138258125495353142543Q, 0.0001882243723673180815859848425981422149923Q, 0.000220129105359083888832193195380277964631Q, 0.0002567644044435395558985376934615952746774Q, 0.0002987211231186489549516252551089359495587Q, 0.0003466479020167920218943287065081041086883Q, 0.0004012547932769214992784035333438157199896Q, 0.0004633168865935784338501681041310863439442Q, 0.0005336779105791366983905761533437676567429Q, 0.0006132537813759504708063524124765235945565Q, 0.0007030360689550059158765139669182449713927Q, 0.0008040953502668325012890028878715651258039Q, 0.0009175844173963607454679355479874424263829Q, 0.001044741308141107407038707367942396160755Q, 0.001186892126003470975743583081981798214652Q, 0.001345453616481502859286364987039915779821Q, 0.001521935466772907586110083455839761654915Q, 0.001717942296584680418941635241375263314963Q, 0.001935175308671765557581701564207351830222Q, 0.002175433569013882948578843986006403688485Q, 0.00244061488817701827933962177717454590009Q, 0.002732716277387093760523031790972800227035Q, 0.003053833955155494667190955668647144637077Q, 0.003406162882922376111090737904328858634942Q, 0.003791995811102684339694547552585507990223Q, 0.004213721820106255238520670138395000924438Q, 0.004673824344328191012589440091579259760752Q, 0.005174878670736688316509780570084920182513Q, 0.005719548907487502446481303679623316137136Q, 0.00631058442192985698627201889000303700039Q, 0.006950815751398609527548621000197550798988Q, 0.007643149994271354192801093440865419580856Q, 0.008390565692865655199126566293274333642062Q, 0.009196107223819374276889186313994843390353Q, 0.01006287871559507536535044833068973909294Q, 0.0109940375166376773728040945023712313313Q, 0.01199278724145422091671644293048154728942Q, 0.01306237042543906222476060243442814308369Q, 0.01420606082260259352562017237936801265042Q, 0.01542715538344503858931888643358628745717Q, 0.0167289659530203930831754338734874664053Q, 0.01811481073173395916859919022391664972282Q, 0.01958800554358856744019143892683179847952Q, 0.02115185495842169316583797633449771810677Q, 0.0228096433161443911301425779096357227542Q, 0.02456462570209342382627799804527821306298Q, 0.02642001892333428109789892692937509533337Q, 0.02837899253610309628758625557724591354616Q, 0.03044465997455174638840433200930338711507Q, 0.0326200698305684182561478766940614844802Q, 0.03490819733369493186523156261607315466053Q, 0.03731193607906478545336713244881109055547Q, 0.03983409004985797457339959837144377122436Q, 0.04247736597902870508264605012848775314015Q, 0.04524436609303125412480485866465061775906Q, 0.04813758127797071695188343575966783160027Q, 0.05115938470606436195469305247887685131832Q, 0.05431202595754248111789162569375577872956Q, 0.0575976256701728356651407164727388580805Q, 0.0610181707454887735519286127955001295239Q, 0.06457551013756707073912038813096685540493Q, 0.06827135124686695200131838960274498733873Q, 0.07210725693823589850320643270045776879156Q, 0.0760846431987396666107037402041258283206Q, 0.08020477744751167235556685358836323731335Q, 0.08446877750636786639701687175860442218662Q, 0.08887761123652361947156590658579628794683Q, 0.09343209684340379971159263353331405267565Q, 0.09813290384827947634314597377864550592762Q, 0.1029805547223161917217849662754146410394Q, 0.107975427175599384648800929258392588213Q, 0.1131177570908303240224652780558492398361Q, 0.1184076420886768784022524072852628267607Q, 0.1238450457092316689652810284506150029169Q, 0.1294298021916876848049165341926394261599Q, 0.1351616218321983257068963021357149291953Q, 0.1410400968979531369261616983876599890975Q, 0.1470647080737783262838611415820062681671Q, 0.153234831416066732619412144570512369546Q, 0.1595497457875576600290825257800962557912Q, 0.1660086407454235928297088004549011805831Q, 0.1726106248542773238830740951304465857529Q, 0.1793547343950870081915214248666534071515Q, 0.1862399424405742377120762392711272315017Q, 0.1932651682674662866336549954877868791502Q, 0.2004292870759719115746122524278836114001Q, 0.2077311399870431986348998739442376385985Q, 0.2151695442883657277414314663960325511106Q, 0.2227433039005768119334724476408616510273Q, 0.2304512200359371707379802858704110927547Q, 0.238292102022565012438636869295500477757Q, 0.2462647782683726466471199486866921649987Q, 0.254368107340013678004869448238984448963Q, 0.2626009891334426438055153641042268648289Q, 0.2709623761140977072718583929657258698507Q, 0.2794512846062298136893226330853142403707Q, 0.2880668061125078167787824382718038889734Q, 0.296808118646717980840005593177875755319Q, 0.3056744980641377677579036909396937192142Q, 0.3146653293759881203313235805942140830196Q, 0.3237801180362461983090820270519599818301Q, 0.3330185011910228622657311928027273913756Q, 0.3423802588826678418804113983776109433992Q, 0.3518653252027527789924367138981015674402Q, 0.3614737993900911492268336792036467644866Q, 0.3712059568719780542735256003769499002505Q, 0.3810622602488663480435171795984767091639Q, 0.3910433702247335339010502511824521314023Q, 0.4011501564874320933236375501478126225841Q, 0.4113837085453508612370763030338926460708Q, 0.4217453465287439745740029610957751723861Q, 0.4322366319661047574509906269685113863411Q, 0.4428593785479733817386890110895733244681Q, 0.4536156628925687094231449505202515619854Q, 0.464507835329626572328505104590646627441Q, 0.4755385307208097937482079206198446406668Q, 0.4867106793370311448540891233670977920386Q, 0.4980275178150015090250825860923349908605Q, 0.5094926002172848568191354394503605415964Q, 0.5211098092221129673730069757438879031618Q, 0.5328833674711906123911808005586354523419Q, 0.5448178491057112741679836363725011074712Q, 0.5569181915228102063547315863613788776984Q, 0.5691897073867122497869745706167773132242Q, 0.5816380969308934474793883532843665800915Q, 0.594269460589676005299802716361632023448Q, 0.6070903119998240471222356070870425052955Q, 0.6201075914149121414331976341764137620912Q, 0.6333286795775096670077450936959654630057Q, 0.6467614120965724037497804104943555382337Q, 0.6604140943798696982054270851497081511967Q, 0.6742955171738133585239271173870307816064Q, 0.6884149727657060911128222112013278833933Q, 0.7027822719062066643044698811599154029693Q, 0.7174077615127308354587586170401139201738Q, 0.7323023432175871214633425313512827364943Q, 0.7474774928279014552006592596985716213354Q, 0.7629452807678324593654003954321067804243Q, 0.7787183935772384484317206900527945313626Q, 0.794810156544848547172767589390981649492Q, 0.8112345575581350364947114757891812390685Q, 0.8280062722565051964220310805112035656865Q, 0.8451406905791530670663872308556803104808Q, 0.862653944803960940002105223911111611703Q, 0.8805629391792451103891710796280884448635Q, 0.8988853812559305452871967488187545907845Q, 0.9176398150339469056412351899494533187875Q, 0.9368456560432984078524666287687994133458Q, 0.9565232284874095042002045886475279507954Q, 0.9766938045840272767944337301321751065917Q, 0.9973796462472128045133642631801931333523Q, 1.01860404926282392956317946592394034531Q, 1.040391390119430800501306096390484332391Q, 1.062767175666867240516297891529939479756Q, 1.085758095785663642281105802222348812045Q, 1.10939207926249369916261716500126785443Q, 1.133698353079565973147506826247703249701Q, 1.158707505339675825255735779161136390472Q, 1.184451552063483495095045621317392891301Q, 1.210964008111586732614521606850934884333Q, 1.238279962501205323185680973891105950334Q, 1.266436158405892106534863447479802864076Q, 1.295471078146741458304256385907446823312Q, 1.325425033505202083685015684659959438256Q, 1.356340261710947294764081629105735343643Q, 1.388261027483455161025774293888757855687Q, 1.421233731533158113469992887140017312801Q, 1.455307025957405656451286211771500914052Q, 1.490531936998228868219023421638164269274Q, 1.526961995663202046567211183531908173458Q, 1.564653376747784111876581362830437011253Q, 1.603665046837629160778144804262475653057Q, 1.644058921912742785217971171041985143034Q, 1.685900035222313480214992667532713310022Q, 1.729256716149878219924242767000386187611Q, 1.774200780843528793008066259722862522388Q, 1.820807735445503515984476325588028533978Q, 1.869156992820145515977178445445390578286Q, 1.919332103749290742415019782061183726939Q, 1.971421003640165834597778573110233965466Q, 2.025516275873364649088115856648097485223Q, 2.081715433008021275938209590135990804757Q, 2.140121217158552655052438896015999577182Q, 2.200841920963014547929530531274604977917Q, 2.263991730677979497484300076901683513364Q, 2.32969109305976045411657347024763207472Q, 2.398067107827710058779643401999432795631Q, 2.469253947653258420191531652724380454066Q, 2.543393307779451047507153399185346597841Q, 2.620634887551268158229579783397916906989Q, 2.701136906328329337203785565785074072196Q, 2.785066656460237449889254046340672661742Q, 2.872601096232473677614318257460754228219Q, 2.963927485939276452660257201800769243529Q, 3.059244070511369011437875195340374346818Q, 3.158760812423005873912952719525474220384Q, 3.262700178927088806749953484425989249023Q, 3.371297988021823798897713011575447983367Q, 3.484804317940613202084006553747118493489Q, 3.603484485381990625764882737049172673747Q, 3.727620098162165171514708146288863084124Q, 3.857510188483308323724907886381561506691Q, 3.993472433570707806928526443290607188682Q, 4.135844471046451472454246597080688613615Q, 4.284985317082080327173205151052609770788Q, 4.441276896113985089457451399096067523765Q, 4.605125691720244026764370781104263535342Q, 4.776964529153930976873581660867167367634Q, 4.95725450101436623824090639311762907648Q, 5.146487048624035738339801115424373145069Q, 5.345186212875773055646526104283213166619Q, 5.553911069634338220218711432966624812946Q, 5.77325836623218909927059759764589584879Q, 6.003865377206048605761449274343927216903Q, 6.246412999195612054604668256261603981218Q, 6.501629106887186763618395996193518237451Q, 6.770292194054217171968109306745209606844Q, 7.053235326147045417971320097171996692265Q, 7.35135043354224614666015033130666518755Q, 7.665592977507008524711768710447822251596Q, 7.99698702419947858650763841033117635338Q, 8.346630765648955546734771430943712584567Q, 8.715702530682195108316710736134856148585Q, 9.105467333230856750332784441560793915267Q, 9.517284010423279804954247067378435207565Q, 9.952613008390899735914523387635646169422Q, 10.41302487987290341264917855291653594177Q, 10.90020956455793654418731784931574442836Q, 11.41598653074432960761644356555484658751Q, 11.96231586542698517926431253288706983627Q, 12.54131040943894482491352029147685616503Q, 13.15524904491223096736253493917986547645Q, 13.80659125421566013309472641076367137531Q, 14.49799308283537068733806522611592929918Q, 15.23232465356644138323597883223098213734Q, 16.01268939608506359051333506048449232573Q, 16.8424451747018194731026127671712692775Q, 17.72522751812091969571786639162509975806Q, 18.66497517864721511431497872041775884551Q, 19.66595827483338098446967472260739788953Q, 20.73280930143244666471574442281522903193Q, 21.87055732415900772060659367071969224017Q, 23.08466571467196402575438824917868654178Q, 24.38107382395057915687200907586246892126Q, 25.7662430405051812966499914509625384785Q, 27.24720773440068300935745005728667380869Q, 28.83163164974229758945104220936171273136Q, 30.52787037807261230893713949085699006405Q, 32.3450406241987409077896619933344018561Q, 34.29309706561872681849669817137072613286Q, 36.38291770845545162245476827741032427239Q, 38.62639875836956225627789882526940946526Q, 41.03656015631005798746236445920699096398Q, 43.62766307847848111679875785712898620598Q, 46.41534087019270662202361582551787873513Q, 49.41674507751608025548331094469808937291Q, 52.65070846212654381646552716106077643221Q, 56.13792713806019302031335914182740881889Q, 59.90116425845236114237707095933490569938Q, 63.96547801176112688533109691101640809997Q, 68.35847706663356290654056305516520187869Q, 73.1106070400535228943010840853771922367Q, 78.2554720634100436673165461770242295508Q, 83.83019609580841382274286001915828318548Q, 89.87582929516635773217532104021295646478Q, 96.43780551924200423365120382987901990037Q, 103.5664579069193585087895746723625879788Q, 111.3176005037851754525798266671368531998Q, 119.7531850674833499641095701349550588967Q, 128.9420435435961078207576974725019132169Q, 138.9607282724984871708695514001995649591Q, 149.8944638077825781408536567743182992156Q, 161.8382263398671525938367526689287312097Q, 174.8979691743083696073045128037176486302Q, 189.1920155721483495460012542161168057521Q, 204.8526435891665175913537920041964014778Q, 222.027891434725956190837338565467777867Q, 240.88361640690763753526746528298183629Q, 261.6058457649334272046319924765364648261Q, 284.403464110476071641090421744246851318Q, 309.51128913049882030120008084966685685Q, 337.1935961013210043006610512490274375597Q, 367.7481615999600937711438359582960700752Q, 401.5109086931381617979355424315925378221Q, 438.8612498100309866908178648997732329971Q, 480.2282399512316532893085494373602185103Q, 526.0976723225701163012986065722476344299Q, 577.0202714839153277613560365269689534811Q, 633.6211663623286914660652375227156227858Q, 696.6108578302568399031998061512477922416Q, 766.7979339996213953902457962279823199983Q, 845.1038321483961377544033152655484401883Q, 932.5800007502418686784878634625973295461Q, 1030.427880205268371607863481564260421702Q, 1140.022198738619409531305753764053160504Q, 1262.938173179340126267770568255475671177Q, 1400.983316165672812706630096023677023453Q, 1556.234685661799166419834076272895832667Q, 1731.082574302171248664168847453614878774Q, 1928.281830862719311465180216556548647829Q, 2151.012241278362996194541735020086674113Q, 2402.949680908323672668281479483735120957Q, 2688.35009405274898539046388166782344203Q, 3012.148774428996002817780038366771869698Q, 3380.077927947738665430980404057153553452Q, 3798.8061171273287816025804901302085407Q, 4276.103940178038843575493542846970132437Q, 4821.041218620766468858314278886473414916Q, 5444.222094388470795213327524033646097556Q, 6158.065819431147727245029087643341223611Q, 6977.142718757731621969847227843666046181Q, 7918.57689772303460428259761072791249996Q, 9002.529841616973008609731087967074460965Q, 10252.78224006547697358532192963572223849Q, 11697.43531120386115196874312407799521273Q, 13369.75779118806422297716318991439523796Q, 15309.21083364664327603498100930983535561Q, 17562.690635400711230682290340971331153Q, 20186.03805526835731073576014831323115031Q, 23245.87631298432720823386094470123690508Q, 26821.8526708964660159886933177732467881Q, 31009.37861130203017968748996249105326523Q, 35922.98645004505473991896385042800280479Q, 41700.44988478085183088793644390235506667Q, 48507.85335185738720597387629792697758441Q, 56545.84243439263590453434852169343975209Q, 66057.34773622772120970119305119425356007Q, 77337.15125150264720189777207255380428642Q, 90743.76204222132276487959174812557638943Q, 106714.1931345439161543996792387468025379Q, 125782.3919792783606644548980631212452294Q, 148602.28308268868913284386494314759249Q, 175976.6472537126831529901228629810350888Q, 208893.4054123648023151893924130651509251Q, 248571.3198896581872265252528072315261787Q, 296517.7041099588785074932688713451965026Q, 354601.4842046107884858345245389612826445Q, 425145.9388942126878002415502363163400429Q, 511046.7307492540007761231679727362111046Q, 615922.5313638820825468503152050330940154Q, 744307.7672522774013301855992769478990101Q, 901899.9500280627208570829224628231273515Q, 1095877.943017809647466283294609129783732Q, 1335312.680400192900473900972313608959584Q, 1631698.732799417297778849111829227960256Q, 1999644.301287932721508706558730228833034Q, 2457769.533243204063209231606836355450074Q, 3029879.601126654923164320051829081011141Q, 3746501.296107716197697994644755801894388Q, 4646902.065144207843314545735079873944726Q, 5781751.367051714701608613666500464883081Q, 7216639.965420261461783043861588641172554Q, 9036748.91103818439407145784950842727797Q, 11353064.30295396674362518583710002098171Q, 14310677.38848294383826734043939982225179Q, 18099907.52814647757667209831825354212464Q, 22971259.6668891917836879617589957239566Q, 29255608.85808781354322251315088609515549Q, 37391535.59237359316460832559373862826806Q, 47962479.20390166985661378587634109109441Q, 61747421.18114908020763006555364067577321Q, 79790283.20014303517364767024983720002342Q, 103495309.7818322791392225142306514842407Q, 134758668.4335062392784062691770869168908Q, 176150727.1167647396710291203195515696546Q, 231169523.1730998536214569360302706436015Q, 304594644.4399651635506297387509567217169Q, 402983315.5328752866261842165179493486228Q, 535368712.0454349728436136721216726833139Q, 714247070.3053378406139506672831438081902Q, 956978978.7740373778892004432884152696425Q, 1287787251.056266365052170195833743740423Q, 1740617888.192125045084695206325485163025Q, 2363255270.596386879033770262261785331955Q, 3223268243.013810967426011910089526282321Q, 4416641191.505012065410596295491828581351Q, 6080361037.679268493630106361893438552833Q, 8410860300.522297192863904820721664748136Q, 11691170810.23185446900657258020662184426Q, 16331097466.34382519842012415317299709164Q, 22926949953.32506221058163368461899055449Q, 32350801251.34441900313971832417983264306Q, 45884550887.87373756921169916820389200205Q, 65422328991.26591065899030653729434101914Q, 93777690083.05024525805287034041120136343Q, 135152344877.9312446339111822592163115366Q, 195855262619.5102394227400235042902030497Q, 285411966950.5744584463492472652528305332Q, 418285339123.4088687905886483684441030554Q, 616560216997.1507015559128477210327029614Q, 914155798247.046721897379660004085140681Q, 1363474103153.313475332332520737128454563Q, 2045955806530.38080332307163606468874395Q, 3088941238912.347778181637746413811180547Q, 4692768203830.229326011299203618570047404Q, 7174593389222.668179510729483054183954121Q, 11039707421424.7535285760553205782673006Q, 17098339814642.30883189402376214028857248Q, 26658220492645.27096615518476281285140601Q, 41844137833284.34059723603044347303078534Q, 66131822092212.56260433143407179128676762Q, 105246004103885.8447522437221674794658493Q, 168681559938365.0716704855055188081332796Q, 272298230587943.4228747819094080068890302Q, 442778332914208.8581203935475801325800709Q, 725340820090340.5850347950296827399214103Q, 1197189129009285.106993300968997149725738Q, 1991130686955199.032617972879924186900084Q, 3337378010666735.506952950406469988115707Q, 5638099922749490.406581662527138521678621Q, 9601427499741881.211823807926750198760527Q, 16484254092349348.98845372947631486314024Q, 28535723974924115.84032543376000631602713Q, 49813965452361994.64837345276433255672811Q, 87702782408500507.02084267463945306822658Q, 155752125029829556.4155463030004333389455Q, 279043670263039211.1950144058463979753731Q, 504415149791330774.373714179037049083309Q, 920116740121384961.3827433654664139990454Q, 1693942563317466607.969360487779734224803Q, 3147881813588503606.949687187530927219109Q, 5905629394327348620.964750033118718606609Q, 11186830170429972683.90503304219913230732Q, 21399669223814878252.89102214192683014818Q, 41345985808186444702.65217417004483350894Q, 80696386697395085475.26410049325816995634Q, 159125037274329006606.8786857330403125667Q, 317071329836898082746.6238825600530512982Q, 638529399076067500974.9466574352370019617Q, 1299818924097534326158.990461297267263975Q, 2675078654074978206518.637506117225931Q, 5566944189022631213362.099038457498976086Q, 11716552341597990248990.5171435566483995Q, 24943805360858062472816.00063661308666544Q, 53725930189976218263874.47358413133583937Q, 117096316957750403564988.56304888156271Q, 258298292038703721390495.8236396936501247Q, 576767877261231270067849.8484954071029679Q, 1303963227039250295013435.358818079135299Q, 2985377159576379451118689.073633893728235Q, 6922912113704827260367186.083906017707785Q, 16263788067632228522850044.30274061276946Q, 38715669422591640446273220.48107692525781Q, 93405902326795746218849693.41808866100623Q, 228442062263956655676707457.4277829780059Q, 566480802429004551807161785.525553048924Q, 1424611114198876208195667756.664348169039Q, 3634172949857829218775326055.022683993536Q, 9406122364586675152583301141.322786625963Q, 24706464444758897130981477914.48038397415Q, 65872820457540932835165401933.67205736797Q, 178319944111489749419279438635.2410294258Q, 490225068350940521098480834251.6808904126Q, 1368984772740533848004072374113.409441503Q, 3884333014472347772834359801746.655971535Q, 11201029764013440779432129805270.58958674Q, 32834751787829632611461325466661.61440042Q, 97871488077698794764611261629326.14611831Q, 296714970484721897998030463296972.3588181Q, 915165168173240309272518702527005.381633Q, 2872460267173498910803623624768017.743058Q, 9177464747767130953083654377275067.095958Q, 29855687257363621764846076009157648.30726Q, 98921454300453615088000828632641016.23094Q, 333916858936387164243193277343677648.8645Q, 1148677119756490680705739927834502644.262Q, 4028085735873633572809913571370067079.051Q, 14403629095536081310122394964760721828.66Q, 52535284391711770924959341342130057524.83Q, 195511238702341217234148056362961569426.5Q, 742628359135587348679681010616409214772.4Q, 2879985786290129359256278011916116854096.0Q, 1.140696796840996797711738648003995766426e+40Q, 4.615889998203199535641248805067886524741e+40Q, 1.908941368569039653622830158192604926747e+41Q, 8.071058712835471546948188653318290734289e+41Q, 3.489959706112432919449108947044335064462e+42Q, 1.543888386814652700671726911000678239128e+43Q, 6.989932474233277622942141615547447627292e+43Q, 3.240038117762964872837102805973332306521e+44Q, 1.538183968209712484725068871595387907532e+45Q, 7.481883824192840270769874827358924746817e+45Q, 3.73013225339343201187931343434453690825e+46Q, 1.906851076505672829935280449453775492013e+47Q, 9.999077656071522270351775782972854776915e+47Q, 5.380563552050893470837576599671463394205e+48Q, 2.972330032282961488357047932157273938273e+49Q, 1.686348374699422063673300554972483611095e+50Q, 9.830168535442368803758339268296974599245e+50Q, 5.890108429190751064006128529315046824849e+51Q, 3.629296561939369243399179077578354993584e+52Q, 2.300645004501572067249374084078975050572e+53Q, 1.50106294849063099901010627951209585913e+54Q, 1.008480606717589095366587976999767304221e+55Q, 6.980007119035887928080977649978198675152e+55Q, 4.979288841677991603006522250488653330001e+56Q, 3.66276106448839180486992300970231614026e+57Q, 2.779646718727500962719473248533230654228e+58Q, 2.177326686395961419408952027332377399652e+59Q, 1.761274961525829532053705828024510976734e+60Q, 1.472042344123250900757337524678434441804e+61Q, 1.271822455421028839508598095571294694327e+62Q, 1.136508544602098866393539277964124525428e+63Q, 1.050968050635916077523427282417608640335e+64Q, 1.00626207712914662753370159827651041146e+65Q, 9.981030000833852218070495344493841448017e+65Q, 1.026180847075813778541059391701842979761e+67Q, 1.09421374737140946315988080967962942332e+68Q, 1.210763841397564590646317030645949174098e+69Q, 1.391069896832891097224590572614426931551e+70Q, 1.66045803643638884585898488848404012021e+71Q, 2.060428539953847004622281786713096894814e+72Q, 2.659520130664924331541795505319434146906e+73Q, 3.573013284264659144117143659354260264313e+74Q, 4.999486492804923952719809970672723582345e+75Q, 7.290439237429593217623599777130532573045e+76Q, 1.108669253112891672863961714590332883419e+78Q, 1.759370316250180690332753515259259156688e+79Q, 2.915485723182837008934603124966328270354e+80Q, 5.048461194348245760902730455814691168198e+81Q, 9.14118029796915194428405620075256632899e+82Q, 1.731992937477462342845227375134295284526e+84Q, 3.436376953072005833211777807213125461832e+85Q, 7.144658133694111972876923978928526300053e+86Q, 1.55778737763103944888409221887807238926e+88Q, 3.564561555743844052143091887908206876342e+89Q, 8.566541566276859225670891601341438867685e+90Q, 2.163923297209145308730010116371450613445e+92Q, 5.74984144627868535047457089036754294733e+93Q, 1.60839847723572274756032280074086871365e+95Q, 4.740310317452400773817968906768308847938e+96Q, 1.473168155068744631692643356229607264882e+98Q, 4.831622757046275226639687085840067067887e+99Q, 1.673775819766076748422178976772154137065e+101Q, 6.129702080773580414198288240232221663836e+102Q, 2.375195572649536955856341846366320025447e+104Q, 9.746830708765397472546215846003382904173e+105Q, 4.239588455190572482069216933841673146039e+107Q, 1.956494245370687105054870244894992250777e+109Q, 9.588102853447409054394849979650825404339e+110Q, 4.994557760892807128927411547962380678913e+112Q, 2.768146852290885169241442660307412799022e+114Q, 1.633928319786263704798907980813701003631e+116Q, 1.028156908727469064515118226996254551401e+118Q, 6.904080374041585885024483266963686212709e+119Q, 4.952411576392766271393256067965393360727e+121Q, 3.798774197493427340709475899043548697485e+123Q, 3.119209910408000389677151746883852508364e+125Q, 2.74464281329371919028887605085237578063e+127Q, 2.590837914912684682640131392851692377728e+129Q, 2.626566210336074467392696546232535266827e+131Q, 2.862979557234280901204803416309101850378e+133Q, 3.359121393671599351439597581159266025716e+135Q, 4.247313211033286464137443445775235101828e+137Q, 5.7942272714265457019323508964771867228e+139Q, 8.538645358004657015182819424098214783173e+141Q, 1.360888004282941018668670601150276254469e+144Q, 2.348723067724485698744588128779913095071e+146Q, 4.395029120308788033535362463288942558768e+148Q, 8.928228383284871526851861594213174257963e+150Q, 1.971533670422240464246243093548157857339e+153Q, 4.738589737247294610658233560831235896082e+155Q, 1.241308244941580876284153148872321788032e+158Q, 3.548824589134106728881153020185390663367e+160Q, 1.108821925774839482718156058757565092921e+163Q, 3.791568324747532283399755029435267152261e+165Q, 1.420930300659947104773952851462106093989e+168Q, 5.84453799109152853361078444336558106409e+170Q, 2.642333927756119541622130789938393830472e+173Q, 1.315018700128967486521348415446442009019e+176Q, 7.215055214056115599570975509522351983024e+178Q, 4.370972004835405599501947122396095759213e+181Q, 2.9283613461041822425605630116860831466e+184Q, 2.173040852495516111888092260762700043093e+187Q, 1.788985622982511228211473383825580284642e+190Q, 1.636634504773987713192039651921165926626e+193Q, 1.666570888998858107369856444049108728955e+196Q, 1.892151113181535234424384795106566625139e+199Q, 2.399341256020760750689416036737132433809e+202Q, 3.403990692562377717224530571668026437231e+205Q, 5.412684450566753125713167924326746292328e+208Q, 9.663735052574312957366051717393887459725e+211Q, 1.940785411690247394647362413292066051113e+215Q, 4.392532041151062373685805234839718468544e+218Q, 1.122469784801228315610393382333655697996e+222Q, 3.244792593820658963686565461190260558268e+225Q, 1.063151412606654581889047233605046614442e+229Q, 3.955995687476636211061457789343143304844e+232Q, 1.675093730347128892220647880504964819835e+236Q, 8.087770848773335454281892374161575798369e+239Q, 4.461929541005863065785797298033896045328e+243Q, 2.818594400456011731351928477247466992727e+247Q, 2.043076786152914736967629947070114858535e+251Q, 1.703020313436824993942113027133546248076e+255Q, 1.636038893251936899296016502545612941115e+259Q, 1.815418460356235422023246399959725267478e+263Q, 2.332142886850178672234463486793710072382e+267Q, 3.476404726198879520090342868431980509165e+271Q, 6.02725450669274575708398710171785543849e+275Q, 1.218304996377836253272518577114790751006e+280Q, 2.877990538823511127754633031010804415019e+284Q, 7.964996943223120262348859076890157988359e+288Q, 2.588973716628916728047311617227986411804e+293Q, 9.908669888497828069120771232809956622636e+297Q, 4.476782590934448698631648708447218305023e+302Q, 2.393946289872904750991457301609667478573e+307Q, 1.519194065472150234303611944283693040837e+312Q, 1.147184880467145335990085347869884772013e+317Q, 1.033627774385061887195237160951315788932e+322Q, 1.114329281092576402692439832629726866969e+327Q, 1.441479839401683621084678999839363913781e+332Q, 2.243859327319511203437262571615345659758e+337Q, 4.215418497025923051098094558302194889077e+342Q, 9.585829785115038185661111425389321480842e+347Q, 2.646481452232988267470696963344934626712e+353Q, 8.89784570848809579740737460434820021581e+358Q, 3.654478434391815119731593878923994274866e+364Q, 1.839328571998191153309682048643039357777e+370Q, 1.138091115297408561689593979279964151166e+376Q, 8.685420860596502744558689502785399264335e+381Q, 8.202294873735399393185427253762485343561e+387Q, 9.617622211012637558143840626406701008311e+393Q, 1.404972969423732814470812460457324672731e+400Q, 2.565898938978703228107858106775855677516e+406Q, 5.879082125410122180654821992667679428038e+412Q, 1.696012443986232559131127974976016333649e+419Q, 6.182635207061036709662140763355431230729e+425Q, 2.858535933001077693342990841750579771279e+432Q, 1.682537298081273384688483838923408088448e+439Q, 1.265575099379113494236586140787099830899e+446Q, 1.221210377447344985626110580846200012905e+453Q, 1.517665191579856561612622774652863045029e+460Q, 2.438792156389105075630091184035735481592e+467Q, 5.087970569512535749002437068314762668605e+474Q, 1.383791668577664156393179945731681404331e+482Q, 4.926818942421142280481071642006166530446e+489Q, 2.306079479408307605132901861123305364681e+497Q, 1.425163636904652491964810204050170654619e+505Q, 1.167988230033416008655199893436256564186e+513Q, 1.275046076993048598825372293330373578487e+521Q, 1.86246353592536022566810742828968418859e+529Q, 3.656923281780862954333590022998862124388e+537Q, 9.696905002869973525940370399688193605905e+545Q, 3.488948519517137250033917388900863677716e+554Q, 1.711541280860496566193503287636236147624e+563Q, 1.150354590150357338329469526604301396277e+572Q, 1.064586955227472600644681500814476378383e+581Q, 1.363399241303394867639622834102250083249e+590Q, 2.428730562379263868477135617904841079855e+599Q, 6.049324540156405309997840862794643030452e+608Q, 2.117864171596828953446343836759090767393e+618Q, 1.047807516700166731633507555828693597684e+628Q, 7.365840114672675880252522494113514523595e+637Q, 7.398145492560429927900357801839811327058e+647Q, 1.067636747584131414468100025618283209301e+658Q, 2.22639858034098687306401094797599805894e+668Q, 6.748057923046794570772294496845240165064e+678Q, 2.990257191488723121175096872976103128614e+689Q, 1.948901043872427503145006863820911627038e+700Q, 1.879581186786894369816802738913105922879e+711Q, 2.698997931735600125081085882104105417964e+722Q, 5.806794882741622880474886909554775109619e+733Q, 1.883770843607193027100793847871062947288e+745Q, 9.274404492358642603751756778289018245069e+756Q, 6.975307042717716858281521605314873677261e+768Q, 8.067850522456048441251197638882843500221e+780Q, 1.444817834210597780118974729779559393721e+793Q, 4.033842652061704730692481744304620504234e+805Q, 1.768122616586398867633690641669676999188e+818Q, 1.225400779279196264005900309164283624649e+831Q, 1.352538486275098128663407391866246559851e+844Q, 2.395022076176373866310260662550018260889e+857Q, 6.85473457159274328678409145257099377572e+870Q, 3.195043165613256224203167145283241373075e+884Q, 2.444011394541681034079796623093288489705e+898Q, 3.092132542900569483086826127272209424616e+912Q, 6.52202827899369001274608906112336954129e+926Q, 2.311918230803327273869816369617489055755e+941Q, 1.388602808524064591680879431092854078226e+956Q, 1.424970459220504800074970047827419053133e+971Q, 2.519528084028136647765117343629838887978e+986Q, 7.741747865648544410946053665346929221769e+1001Q, 4.170084664493231900748918523968910566173e+1017Q, 3.972609017709578843063743585633222829841e+1033Q, 6.753538916409713709617458845853916542168e+1049Q, 2.067628729105681113174425295794554011159e+1066Q, 1.150595286862592019698043377859855347102e+1083Q, 1.174811465056168119582538764054374610771e+1100Q, 2.222083328904688772385369058449897242601e+1117Q, 7.861682153952467469302910158034016013007e+1134Q, 5.254318461012202675141984565028119771927e+1152Q, 6.700594094583685233271878665147881576963e+1170Q, 1.647119020685994883163368465161853068246e+1189Q, 7.885690686668208640526803176415414652937e+1207Q, 7.4304751845758892706961097079985818407e+1226Q, 1.392792237173373732943845763489796692971e+1246Q, 5.249920365660960360703118769306589305549e+1265Q, 4.023402905801975410548914995317394511897e+1285Q, 6.339599284962247390595019787493325156388e+1305Q, 2.077241686093845039324765598314087816491e+1326Q, 1.431779975481430956320443955567912020619e+1347Q, 2.100465323416655119498460724075198611756e+1368Q, 6.636983859221341948458642440032983398444e+1389Q, 4.571823013121701821960348272081362696364e+1411Q, 6.950266919826043719478213435615389027377e+1433Q, 2.361135677422321798996803825169777731761e+1456Q, 1.81529414070336188314937395066678659112e+1479Q, 3.199377508347820763307843188560103423205e+1502Q, 1.309634685394754467330604052024343046006e+1526Q, 1.261723464022528810857575246242118215115e+1550Q, 2.899755666233745652203077582611886981277e+1574Q, 1.611713776270703974807271588562419300726e+1599Q, 2.19676411063602902712587963185490636918e+1624Q, 7.447023857089897627918973727754688355819e+1649Q, 6.369675504111348389431884118799197436233e+1675Q, 1.394815207171927514566140884379200385497e+1702Q, 7.936153825171883059251330198006999518483e+1728Q, 1.1910445325646918131560389884140321995e+1756Q, 4.787444622805551600670119808904041332089e+1783Q, 5.234499335419787802823707399035765773041e+1811Q, 1.581561346401448146226935104237919854933e+1840Q, 1.341800978646655211480455388688595380576e+1869Q, 3.248945821168265660658282098925159913182e+1898Q, 2.282556137907219990369095437167406320923e+1928Q, 4.731625652419454163270049779439076104421e+1958Q, 2.943806123841568264632623519839271578756e+1989Q, 5.592866921504286485703902089288874207169e+2020Q, 3.302335002048689098318554609779249829828e+2052Q, 6.169134926587465224122713900861282080699e+2084Q, 3.712967718086223830358857404823946563008e+2117Q, 7.333531367839546065849712040185078455141e+2150Q, 4.843145606030966902891830748397061937228e+2184Q, 1.089982666110516514588223374299888929834e+2219Q, 8.522650010812465527516484755846137052377e+2253Q, 2.3610765478146005801436450249132797273e+2289Q, 2.364162440159704628905098100196710729676e+2325Q, 8.731002547249769088070048025315387840088e+2361Q, 1.213938210671504830248830740465072981967e+2399Q, 6.488456377484030822273896401425291289227e+2436Q, }, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_weights.size() - 1); + m_committed_refinements = static_cast(m_weights.size() - 1); #else m_committed_refinements = m_weights.size() - 1; #endif @@ -543,8 +688,7 @@ void exp_sinh_detail::init(const std::integral_constant&) } } -} -} +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC @@ -556,8 +700,7 @@ void exp_sinh_detail::init(const std::integral_constant&) #include #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail { @@ -1822,9 +1965,9 @@ __constant__ double* m_weights_double[8] = { m_weights_double_8 }; -__constant__ boost::math::size_t float_coefficients_size[8] = {9, 8, 16, 33, 66, 132, 263, 527}; +__constant__ BOOST_MATH_NAMESPACE::size_t float_coefficients_size[8] = {9, 8, 16, 33, 66, 132, 263, 527}; -__constant__ boost::math::size_t double_coefficients_size[8] = {13, 12, 25, 49, 98, 196, 393, 786}; +__constant__ BOOST_MATH_NAMESPACE::size_t double_coefficients_size[8] = {13, 12, 25, 49, 98, 196, 393, 786}; template struct coefficients_selector; @@ -1847,11 +1990,11 @@ struct coefficients_selector template > -__device__ auto exp_sinh_integrate_impl(const F& f, Real tolerance, Real* error, Real* L1, boost::math::size_t* levels) +__device__ auto exp_sinh_integrate_impl(const F& f, Real tolerance, Real* error, Real* L1, BOOST_MATH_NAMESPACE::size_t* levels) { using K = decltype(f(static_cast(0))); - using boost::math::constants::half; - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::constants::half_pi; // This provided a nice error message for real valued integrals, but it's super awkward for complex-valued integrals: /*K y_max = f(tools::max_value()); @@ -1868,10 +2011,10 @@ __device__ auto exp_sinh_integrate_impl(const F& f, Real tolerance, Real* error, const auto m_weights = coefficients_selector::weights(); const auto m_size = coefficients_selector::size(); - Real min_abscissa{ 0 }, max_abscissa{ boost::math::tools::max_value() }; + Real min_abscissa{ 0 }, max_abscissa{ BOOST_MATH_NAMESPACE::tools::max_value() }; K I0 = 0; Real L1_I0 = 0; - for(boost::math::size_t i = 0; i < m_size[0]; ++i) + for(BOOST_MATH_NAMESPACE::size_t i = 0; i < m_size[0]; ++i) { K y = f(m_abscissas[0][i]); K I0_last = I0; @@ -1888,8 +2031,8 @@ __device__ auto exp_sinh_integrate_impl(const F& f, Real tolerance, Real* error, K I1 = I0; Real L1_I1 = L1_I0; bool have_first_j = false; - boost::math::size_t first_j = 0; - for (boost::math::size_t i = 0; (i < m_size[1]) && (m_abscissas[1][i] < max_abscissa); ++i) + BOOST_MATH_NAMESPACE::size_t first_j = 0; + for (BOOST_MATH_NAMESPACE::size_t i = 0; (i < m_size[1]) && (m_abscissas[1][i] < max_abscissa); ++i) { K y = f(m_abscissas[1][i]); K I1_last = I1; @@ -1920,7 +2063,7 @@ __device__ auto exp_sinh_integrate_impl(const F& f, Real tolerance, Real* error, // We failed to find anything, is the integral zero, or have we just not found it yet? // We'll try one more level, if that still finds nothing then it'll terminate. min_abscissa = 0; - max_abscissa = boost::math::tools::max_value(); + max_abscissa = BOOST_MATH_NAMESPACE::tools::max_value(); } I1 *= half(); @@ -1928,7 +2071,7 @@ __device__ auto exp_sinh_integrate_impl(const F& f, Real tolerance, Real* error, Real err = abs(I0 - I1); //std::cout << "Second estimate: " << I1 << " Error estimate at level " << 1 << " = " << err << std::endl; - boost::math::size_t i = 2; + BOOST_MATH_NAMESPACE::size_t i = 2; for(; i < 8U; ++i) // Magic number 8 is the number of precomputed levels { I0 = I1; @@ -1946,7 +2089,7 @@ __device__ auto exp_sinh_integrate_impl(const F& f, Real tolerance, Real* error, // appoximate location to start looking for lowest meaningful abscissa value first_j = first_j == 0 ? 0 : 2 * first_j - 1; - boost::math::size_t j = first_j; + BOOST_MATH_NAMESPACE::size_t j = first_j; while (abscissas_row[j] < min_abscissa) { ++j; @@ -1964,7 +2107,7 @@ __device__ auto exp_sinh_integrate_impl(const F& f, Real tolerance, Real* error, I1 += sum*h; L1_I1 += absum*h; err = abs(I0 - I1); - if (!(boost::math::isfinite)(L1_I1)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(L1_I1)) { return static_cast(policies::raise_evaluation_error("exp_sinh_integrate", "The exp_sinh quadrature evaluated your function at a singular point and returned %1%. Please ensure your function evaluates to a finite number over its entire domain.", I1, Policy())); } @@ -1994,8 +2137,7 @@ __device__ auto exp_sinh_integrate_impl(const F& f, Real tolerance, Real* error, } // namespace detail } // namespace quadrature -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ENABLE_CUDA diff --git a/include/boost/math/quadrature/detail/norm_quadrature_error.hpp b/include/boost/math/quadrature/detail/norm_quadrature_error.hpp new file mode 100644 index 0000000000..1190d1675f --- /dev/null +++ b/include/boost/math/quadrature/detail/norm_quadrature_error.hpp @@ -0,0 +1,22 @@ +// Copyright Nick Thompson, 2026 +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +#ifndef BOOST_MATH_QUADRATURE_DETAIL_NORM_QUADRATURE_ERROR_HPP +#define BOOST_MATH_QUADRATURE_DETAIL_NORM_QUADRATURE_ERROR_HPP +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail { +template +K norm_quadrature_error(const K& zero, Real invalid, Real* error, Real* l1, std::size_t* levels = nullptr) +{ + if (error) *error = invalid; + if (l1) *l1 = invalid; + if (levels) *levels = 0; + K result = zero * invalid; + return result; +} +}} BOOST_MATH_NAMESPACE_END +#endif diff --git a/include/boost/math/quadrature/detail/ooura_fourier_integrals_detail.hpp b/include/boost/math/quadrature/detail/ooura_fourier_integrals_detail.hpp index c677852da4..e3f68b87bc 100644 --- a/include/boost/math/quadrature/detail/ooura_fourier_integrals_detail.hpp +++ b/include/boost/math/quadrature/detail/ooura_fourier_integrals_detail.hpp @@ -5,9 +5,11 @@ // or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_QUADRATURE_DETAIL_OOURA_FOURIER_INTEGRALS_DETAIL_HPP #define BOOST_MATH_QUADRATURE_DETAIL_OOURA_FOURIER_INTEGRALS_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include // for std::pair. #include #include +#endif #include #include #include @@ -15,11 +17,13 @@ #include #ifdef BOOST_MATH_HAS_THREADS +#ifndef BOOST_MATH_BUILD_MODULE #include #include #endif +#endif -namespace boost { namespace math { namespace quadrature { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail { // Ooura and Mori, A robust double exponential formula for Fourier-type integrals, // eta is the argument to the exponential in equation 3.3: @@ -46,7 +50,7 @@ std::pair ooura_eta(Real x, Real alpha) { template Real calculate_ooura_alpha(Real h) { - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; using std::log1p; using std::sqrt; Real x = sqrt(16 + 4*log1p(pi()/h)/h); @@ -59,7 +63,7 @@ std::pair ooura_sin_node_and_weight(long n, Real h, Real alpha) using std::expm1; using std::exp; using std::abs; - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; using std::isnan; if (n == 0) { @@ -73,7 +77,7 @@ std::pair ooura_sin_node_and_weight(long n, Real h, Real alpha) Real eta_prime_0 = Real(2) + alpha + Real(1)/Real(4); Real node = pi()/(eta_prime_0*h); - Real weight = pi()*boost::math::sin_pi(1/(eta_prime_0*h)); + Real weight = pi()*BOOST_MATH_NAMESPACE::sin_pi(1/(eta_prime_0*h)); Real eta_dbl_prime = -alpha + Real(1)/Real(4); Real phi_prime_0 = (1 - eta_dbl_prime/(eta_prime_0*eta_prime_0))/2; weight *= phi_prime_0; @@ -98,18 +102,18 @@ std::pair ooura_sin_node_and_weight(long n, Real h, Real alpha) Real arg; if(eta > 1) { arg = n/( 1/exp_meta - 1 ); - s *= boost::math::sin_pi(arg); + s *= BOOST_MATH_NAMESPACE::sin_pi(arg); if (n&1) { s *= -1; } } else if (eta < -1) { arg = n/(1-exp_meta); - s *= boost::math::sin_pi(arg); + s *= BOOST_MATH_NAMESPACE::sin_pi(arg); } else { arg = -n*exp_meta/expm1_meta; - s *= boost::math::sin_pi(arg); + s *= BOOST_MATH_NAMESPACE::sin_pi(arg); if (n&1) { s *= -1; } @@ -139,7 +143,7 @@ std::pair ooura_cos_node_and_weight(long n, Real h, Real alpha) using std::expm1; using std::exp; using std::abs; - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; Real x = h*(n-Real(1)/Real(2)); auto p = ooura_eta(x, alpha); @@ -159,11 +163,11 @@ std::pair ooura_cos_node_and_weight(long n, Real h, Real alpha) Real arg; if (eta < -1) { arg = -(n-Real(1)/Real(2))/expm1_meta; - s *= boost::math::cos_pi(arg); + s *= BOOST_MATH_NAMESPACE::cos_pi(arg); } else { arg = -(n-Real(1)/Real(2))*exp_meta/expm1_meta; - s *= boost::math::sin_pi(arg); + s *= BOOST_MATH_NAMESPACE::sin_pi(arg); if (n&1) { s *= -1; } @@ -231,7 +235,7 @@ class ooura_fourier_sin_detail { std::pair integrate(F const & f, Real omega) { using std::abs; using std::max; - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; if (omega == 0) { return {Real(0), Real(0)}; @@ -493,7 +497,7 @@ class ooura_fourier_cos_detail { std::pair integrate(F const & f, Real omega) { using std::abs; using std::max; - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; if (omega == 0) { throw std::domain_error("At omega = 0, the integral is not oscillatory. The user must choose an appropriate method for this case.\n"); @@ -688,5 +692,5 @@ class ooura_fourier_cos_detail { }; -}}}} +}} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/quadrature/detail/quadrature_constant.hpp b/include/boost/math/quadrature/detail/quadrature_constant.hpp new file mode 100644 index 0000000000..ea09288a9d --- /dev/null +++ b/include/boost/math/quadrature/detail/quadrature_constant.hpp @@ -0,0 +1,61 @@ +// Copyright John Maddock 2015. +// 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) + + +#ifndef BOOST_MATH_QUADRATURE_DETAIL_QUADRATURE_CONSTANT_HPP +#define BOOST_MATH_QUADRATURE_DETAIL_QUADRATURE_CONSTANT_HPP + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature{ namespace detail { + +template +struct quadrature_constant_category +{ + static const unsigned value = + (std::numeric_limits::is_specialized == 0) ? 999 : + (std::numeric_limits::radix == 2) ? + ( +#ifdef BOOST_HAS_FLOAT128 + (std::numeric_limits::digits <= 113) && std::is_constructible::value ? 0 : +#else + (std::numeric_limits::digits <= std::numeric_limits::digits) && std::is_constructible::value ? 0 : +#endif + (std::numeric_limits::digits10 <= 110) && std::is_constructible::value ? 4 : 999 + ) : (std::numeric_limits::digits10 <= 110) && std::is_constructible::value ? 4 : 999; + + using storage_type = + std::conditional_t<(std::numeric_limits::is_specialized == 0), T, + std::conditional_t<(std::numeric_limits::radix == 2), + std::conditional_t< ((std::numeric_limits::digits <= std::numeric_limits::digits) && std::is_constructible::value), + float, + std::conditional_t<((std::numeric_limits::digits <= std::numeric_limits::digits) && std::is_constructible::value), + double, + std::conditional_t<((std::numeric_limits::digits <= std::numeric_limits::digits) && std::is_constructible::value), + long double, +#ifdef BOOST_HAS_FLOAT128 + std::conditional_t<((std::numeric_limits::digits <= 113) && std::is_constructible::value), + __float128, + T + > + > +#else + T + > +#endif + > + >, T + > + >; +}; + +} // namespace detail +} // namespace quadrature +BOOST_MATH_NAMESPACE_END + +#endif // BOOST_MATH_QUADRATURE_DETAIL_QUADRATURE_CONSTANT_HPP \ No newline at end of file diff --git a/include/boost/math/quadrature/detail/sinh_sinh_detail.hpp b/include/boost/math/quadrature/detail/sinh_sinh_detail.hpp index 7f7477a6e6..abd3a7c06b 100644 --- a/include/boost/math/quadrature/detail/sinh_sinh_detail.hpp +++ b/include/boost/math/quadrature/detail/sinh_sinh_detail.hpp @@ -11,21 +11,26 @@ #include #ifndef BOOST_MATH_HAS_NVRTC +#include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #include #include #include #include #ifdef BOOST_MATH_HAS_THREADS +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif -namespace boost{ namespace math{ namespace quadrature { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail{ // Returns the sinh-sinh quadrature of a function f over the entire real line @@ -52,6 +57,8 @@ class sinh_sinh_detail template auto integrate(const F f, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(std::declval()(std::declval())); + template + auto integrate(const F f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(std::declval()(std::declval())); private: @@ -115,7 +122,7 @@ class sinh_sinh_detail std::size_t row = ++m_committed_refinements; Real h = ldexp(Real(1), -static_cast(row)); - size_t k = static_cast(boost::math::lltrunc(ceil(m_t_max / (2 * h)))); + size_t k = static_cast(BOOST_MATH_NAMESPACE::lltrunc(ceil(m_t_max / (2 * h)))); m_abscissas[row].reserve(k); m_weights[row].reserve(k); Real arg = h; @@ -136,7 +143,7 @@ class sinh_sinh_detail mutable std::vector> m_weights; std::size_t m_max_refinements; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - mutable boost::math::detail::atomic_unsigned_type m_committed_refinements{}; + mutable BOOST_MATH_NAMESPACE::detail::atomic_unsigned_type m_committed_refinements{}; mutable std::mutex m_mutex; #else mutable unsigned m_committed_refinements; @@ -156,23 +163,23 @@ auto sinh_sinh_detail::integrate(const F f, Real tolerance, Real* { using std::abs; using std::sqrt; - using boost::math::constants::half; - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::constants::half_pi; static const char* function = "boost::math::quadrature::sinh_sinh<%1%>::integrate"; typedef decltype(f(static_cast(0))) K; static_assert(!std::is_integral::value, "The return type cannot be integral, it must be either a real or complex floating point type."); - K y_max = f(boost::math::tools::max_value()); - if(abs(y_max) > boost::math::tools::epsilon()) + K y_max = f(BOOST_MATH_NAMESPACE::tools::max_value()); + if(abs(y_max) > BOOST_MATH_NAMESPACE::tools::epsilon()) { return static_cast(policies::raise_domain_error(function, "The function you are trying to integrate does not go to zero at infinity, and instead evaluates to %1%", y_max, Policy())); } - K y_min = f(-boost::math::tools::max_value()); - if(abs(y_min) > boost::math::tools::epsilon()) + K y_min = f(-BOOST_MATH_NAMESPACE::tools::max_value()); + if(abs(y_min) > BOOST_MATH_NAMESPACE::tools::epsilon()) { return static_cast(policies::raise_domain_error(function, "The function you are trying to integrate does not go to zero at -infinity, and instead evaluates to %1%", y_max, Policy())); @@ -222,7 +229,7 @@ auto sinh_sinh_detail::integrate(const F f, Real tolerance, Real* Real absum = 0; Real abterm1 = 1; - Real eps = boost::math::tools::epsilon()*L1_I1; + Real eps = BOOST_MATH_NAMESPACE::tools::epsilon()*L1_I1; auto abscissa_row = get_abscissa_row(i); auto weight_row = get_weight_row(i); @@ -248,7 +255,7 @@ auto sinh_sinh_detail::integrate(const F f, Real tolerance, Real* L1_I1 += absum*h; err = abs(I0 - I1); // std::cout << "Estimate: " << I1 << " Error estimate at level " << i << " = " << err << std::endl; - if (!(boost::math::isfinite)(L1_I1)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(L1_I1)) { const char* err_msg = "The sinh_sinh quadrature evaluated your function at a singular point, leading to the value %1%.\n" "sinh_sinh quadrature cannot handle singularities in the domain.\n" @@ -279,6 +286,137 @@ auto sinh_sinh_detail::integrate(const F f, Real tolerance, Real* return I1; } +template +template +auto sinh_sinh_detail::integrate(const F f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(std::declval()(std::declval())) +{ + const auto magnitude = [&](const decltype(std::declval()(std::declval()))& value) -> Real { return static_cast(norm(value)); }; + using std::abs; + using std::sqrt; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::constants::half_pi; + + static const char* function = "boost::math::quadrature::sinh_sinh<%1%>::integrate"; + + typedef decltype(f(static_cast(0))) K; + static_assert(!std::is_integral::value, + "The return type cannot be integral."); + K y_max = f(BOOST_MATH_NAMESPACE::tools::max_value()); + if(magnitude(y_max) > BOOST_MATH_NAMESPACE::tools::epsilon()) + { + return norm_quadrature_error(zero, policies::raise_domain_error(function, + "The function you are trying to integrate does not go to zero at infinity, and instead evaluates to %1%", magnitude(y_max), Policy()), error, L1, levels); + } + + K y_min = f(-BOOST_MATH_NAMESPACE::tools::max_value()); + if(magnitude(y_min) > BOOST_MATH_NAMESPACE::tools::epsilon()) + { + return norm_quadrature_error(zero, policies::raise_domain_error(function, + "The function you are trying to integrate does not go to zero at -infinity, and instead evaluates to %1%", magnitude(y_min), Policy()), error, L1, levels); + } + + // Get the party started with two estimates of the integral: + K I0 = f(0)*half_pi(); + Real L1_I0 = magnitude(I0); + for(size_t i = 0; i < m_abscissas[0].size(); ++i) + { + Real x = m_abscissas[0][i]; + K yp = f(x); + K ym = f(-x); + I0 += (yp + ym)*m_weights[0][i]; + L1_I0 += (magnitude(yp)+magnitude(ym))*m_weights[0][i]; + } + + // Uncomment the estimates to work the convergence on the command line. + // std::cout << std::setprecision(std::numeric_limits::digits10); + // std::cout << "First estimate : " << I0 << std::endl; + K I1 = I0; + Real L1_I1 = L1_I0; + for (size_t i = 0; i < m_abscissas[1].size(); ++i) + { + Real x= m_abscissas[1][i]; + K yp = f(x); + K ym = f(-x); + I1 += (yp + ym)*m_weights[1][i]; + L1_I1 += (magnitude(yp) + magnitude(ym))*m_weights[1][i]; + } + + I1 *= half(); + L1_I1 *= half(); + Real err = magnitude(I0 - I1); + // std::cout << "Second estimate: " << I1 << " Error estimate at level " << 1 << " = " << err << std::endl; + + size_t i = 2; + for(; i <= m_max_refinements; ++i) + { + I0 = I1; + L1_I0 = L1_I1; + + I1 = half()*I0; + L1_I1 = half()*L1_I0; + Real h = static_cast(1) / static_cast(1 << i); + K sum = zero; + Real absum = 0; + + Real abterm1 = 1; + Real eps = BOOST_MATH_NAMESPACE::tools::epsilon()*L1_I1; + + auto abscissa_row = get_abscissa_row(i); + auto weight_row = get_weight_row(i); + + for(size_t j = 0; j < abscissa_row.size(); ++j) + { + Real x = abscissa_row[j]; + K yp = f(x); + K ym = f(-x); + sum += (yp + ym)*weight_row[j]; + Real abterm0 = (magnitude(yp) + magnitude(ym))*weight_row[j]; + absum += abterm0; + + // We require two consecutive terms to be < eps in case we hit a zero of f. + if (x > static_cast(100) && abterm0 < eps && abterm1 < eps) + { + break; + } + abterm1 = abterm0; + } + + I1 += sum*h; + L1_I1 += absum*h; + err = magnitude(I0 - I1); + // std::cout << "Estimate: " << I1 << " Error estimate at level " << i << " = " << err << std::endl; + if (!(BOOST_MATH_NAMESPACE::isfinite)(L1_I1)) + { + const char* err_msg = "The sinh_sinh quadrature evaluated your function at a singular point, leading to the value %1%.\n" + "sinh_sinh quadrature cannot handle singularities in the domain.\n" + "If you are sure your function has no singularities, please submit a bug against boost.math\n"; + policies::raise_evaluation_error(function, err_msg, magnitude(I1), Policy()); + return I1; + } + if (err <= tolerance*L1_I1) + { + break; + } + } + + if (error) + { + *error = err; + } + + if (L1) + { + *L1 = L1_I1; + } + + if (levels) + { + *levels = i; + } + + return I1; +} + template void sinh_sinh_detail::init(const std::integral_constant&) { @@ -287,8 +425,8 @@ void sinh_sinh_detail::init(const std::integral_constant&) using std::cosh; using std::sinh; using std::ceil; - using boost::math::constants::two_div_pi; - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::two_div_pi; + using BOOST_MATH_NAMESPACE::constants::half_pi; m_committed_refinements = 4; @@ -300,7 +438,7 @@ void sinh_sinh_detail::init(const std::integral_constant&) for (size_t i = 0; i <= 4; ++i) { Real h = static_cast(1) / static_cast(1 << i); - size_t k = static_cast(boost::math::lltrunc(ceil(m_t_max / (2 * h)))); + size_t k = static_cast(BOOST_MATH_NAMESPACE::lltrunc(ceil(m_t_max / (2 * h)))); m_abscissas[i].reserve(k); m_weights[i].reserve(k); // We don't add 0 to the abscissas; that's treated as a special case. @@ -349,7 +487,7 @@ void sinh_sinh_detail::init(const std::integral_constant&) { 1.57096255e+00f, 1.57229290e+00f, 1.57495658e+00f, 1.57895955e+00f, 1.58431079e+00f, 1.59102230e+00f, 1.59910918e+00f, 1.60858966e+00f, 1.61948515e+00f, 1.63182037e+00f, 1.64562338e+00f, 1.66092569e+00f, 1.67776241e+00f, 1.69617233e+00f, 1.71619809e+00f, 1.73788633e+00f, 1.76128784e+00f, 1.78645779e+00f, 1.81345587e+00f, 1.84234658e+00f, 1.87319943e+00f, 1.90608922e+00f, 1.94109632e+00f, 1.97830698e+00f, 2.01781368e+00f, 2.05971547e+00f, 2.10411838e+00f, 2.15113585e+00f, 2.20088916e+00f, 2.25350798e+00f, 2.30913084e+00f, 2.36790578e+00f, 2.42999091e+00f, 2.49555516e+00f, 2.56477893e+00f, 2.63785496e+00f, 2.71498915e+00f, 2.79640147e+00f, 2.88232702e+00f, 2.97301705e+00f, 3.06874019e+00f, 3.16978367e+00f, 3.27645477e+00f, 3.38908227e+00f, 3.50801806e+00f, 3.63363896e+00f, 3.76634859e+00f, 3.90657947e+00f, 4.05479525e+00f, 4.21149322e+00f, 4.37720695e+00f, 4.55250922e+00f, 4.73801517e+00f, 4.93438579e+00f, 5.14233166e+00f, 5.36261713e+00f, 5.59606472e+00f, 5.84356014e+00f, 6.10605759e+00f, 6.38458564e+00f, 6.68025373e+00f, 6.99425915e+00f, 7.32789480e+00f, 7.68255767e+00f, 8.05975815e+00f, 8.46113023e+00f, 8.88844279e+00f, 9.34361190e+00f, 9.82871448e+00f, 1.03460033e+01f, 1.08979234e+01f, 1.14871305e+01f, 1.21165112e+01f, 1.27892047e+01f, 1.35086281e+01f, 1.42785033e+01f, 1.51028871e+01f, 1.59862046e+01f, 1.69332867e+01f, 1.79494108e+01f, 1.90403465e+01f, 2.02124072e+01f, 2.14725057e+01f, 2.28282181e+01f, 2.42878539e+01f, 2.58605342e+01f, 2.75562800e+01f, 2.93861096e+01f, 3.13621485e+01f, 3.34977526e+01f, 3.58076454e+01f, 3.83080730e+01f, 4.10169773e+01f, 4.39541917e+01f, 4.71416602e+01f, 5.06036855e+01f, 5.43672075e+01f, 5.84621188e+01f, 6.29216205e+01f, 6.77826252e+01f, 7.30862125e+01f, 7.88781469e+01f, 8.52094636e+01f, 9.21371360e+01f, 9.97248336e+01f, 1.08043785e+02f, 1.17173764e+02f, 1.27204209e+02f, 1.38235512e+02f, 1.50380485e+02f, 1.63766039e+02f, 1.78535118e+02f, 1.94848913e+02f, 2.12889407e+02f, 2.32862309e+02f, 2.55000432e+02f, 2.79567594e+02f, 3.06863126e+02f, 3.37227087e+02f, 3.71046310e+02f, 4.08761417e+02f, 4.50874968e+02f, 4.97960949e+02f, 5.50675821e+02f, 6.09771424e+02f, 6.76110054e+02f, 7.50682104e+02f, 8.34626760e+02f, 9.29256285e+02f, 1.03608458e+03f, 1.15686082e+03f, 1.29360914e+03f, 1.44867552e+03f, 1.62478326e+03f, 1.82509876e+03f, 2.05330964e+03f, 2.31371761e+03f, 2.61134924e+03f, 2.95208799e+03f, 3.34283233e+03f, 3.79168493e+03f, 4.30817984e+03f, 4.90355562e+03f, 5.59108434e+03f, 6.38646863e+03f, 7.30832183e+03f, 8.37874981e+03f, 9.62405722e+03f, 1.10756067e+04f, 1.27708661e+04f, 1.47546879e+04f, 1.70808754e+04f, 1.98141031e+04f, 2.30322789e+04f, 2.68294532e+04f, 3.13194118e+04f, 3.66401221e+04f, 4.29592484e+04f, 5.04810088e+04f, 5.94547213e+04f, 7.01854788e+04f, 8.30475173e+04f, 9.85009981e+04f, 1.17113127e+05f, 1.39584798e+05f, 1.66784302e+05f, 1.99790063e+05f, 2.39944995e+05f, 2.88925794e+05f, 3.48831531e+05f, 4.22297220e+05f, 5.12639825e+05f, 6.24046488e+05f, 7.61817907e+05f, 9.32683930e+05f, 1.14521401e+06f, 1.41035265e+06f, 1.74212004e+06f, 2.15853172e+06f, 2.68280941e+06f, 3.34498056e+06f, 4.18399797e+06f, 5.25055801e+06f, 6.61086017e+06f, 8.35163942e+06f, 1.05869253e+07f, 1.34671524e+07f, 1.71914827e+07f, 2.20245345e+07f, 2.83191730e+07f, 3.65476782e+07f, 4.73445266e+07f, 6.15653406e+07f, 8.03684303e+07f, 1.05328028e+08f, 1.38592169e+08f, 1.83103699e+08f, 2.42910946e+08f, 3.23606239e+08f, 4.32947522e+08f, 5.81743297e+08f, 7.85117979e+08f, 1.06432920e+09f, 1.44938958e+09f, 1.98286647e+09f, 2.72541431e+09f, 3.76386796e+09f, 5.22313881e+09f, 7.28378581e+09f, 1.02080964e+10f, 1.43789932e+10f, 2.03583681e+10f, 2.89749983e+10f, 4.14577375e+10f, 5.96383768e+10f, 8.62622848e+10f, 1.25466705e+11f, 1.83521298e+11f, 2.69981221e+11f, 3.99492845e+11f, 5.94638056e+11f, 8.90440997e+11f, 1.34155194e+12f, 2.03376855e+12f, 3.10262796e+12f, 4.76359832e+12f, 7.36142036e+12f, 1.14512696e+13f, 1.79331419e+13f, 2.82758550e+13f, 4.48929705e+13f, 7.17780287e+13f, 1.15585510e+14f, 1.87483389e+14f, 3.06351036e+14f, 5.04340065e+14f, 8.36616340e+14f, 1.39855635e+15f, 2.35633575e+15f, 4.00176517e+15f, 6.85137513e+15f, 1.18269011e+16f, 2.05867353e+16f, 3.61396878e+16f, 6.39911218e+16f, 1.14301619e+17f, 2.05988138e+17f, 3.74584679e+17f, 6.87444303e+17f, 1.27340764e+18f, 2.38124192e+18f, 4.49583562e+18f, 8.57144202e+18f, 1.65044358e+19f, 3.21010035e+19f, 6.30778012e+19f, 1.25240403e+20f, 2.51300530e+20f, 5.09677626e+20f, }, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_weights.size() - 1); + m_committed_refinements = static_cast(m_weights.size() - 1); #else m_committed_refinements = m_weights.size() - 1; #endif @@ -389,7 +527,7 @@ void sinh_sinh_detail::init(const std::integral_constant&) { 1.570962550997832611e+00, 1.572292902367211961e+00, 1.574956581912666755e+00, 1.578959553636163985e+00, 1.584310789563614305e+00, 1.591022301117035107e+00, 1.599109181186160337e+00, 1.608589657109067468e+00, 1.619485154826419743e+00, 1.631820374530739318e+00, 1.645623378191125679e+00, 1.660925689395424109e+00, 1.677762406016463717e+00, 1.696172326277082973e+00, 1.716198088860732467e+00, 1.737886327791014562e+00, 1.761287842885152410e+00, 1.786457786673686420e+00, 1.813455868772335587e+00, 1.842346578792652542e+00, 1.873199428986627521e+00, 1.906089217937612619e+00, 1.941096316736779451e+00, 1.978306979221816566e+00, 2.017813678003844337e+00, 2.059715468170813895e+00, 2.104118380732327493e+00, 2.151135848063375554e+00, 2.200889163814591418e+00, 2.253507979986114202e+00, 2.309130844113053375e+00, 2.367905779785113334e+00, 2.429990914023652954e+00, 2.495555155369085590e+00, 2.564778926893134514e+00, 2.637854958747451684e+00, 2.714989145296268067e+00, 2.796401472360280536e+00, 2.882327020626578700e+00, 2.973017051860293803e+00, 3.068740185193628238e+00, 3.169783671473487386e+00, 3.276454774427328601e+00, 3.389082268266156098e+00, 3.508018062292869136e+00, 3.633638964133530274e+00, 3.766348594369884204e+00, 3.906579466636309289e+00, 4.054795248667541120e+00, 4.211493221360917802e+00, 4.377206954666462219e+00, 4.552509221059946388e+00, 4.738015169510782826e+00, 4.934385785253587887e+00, 5.142331663338191074e+00, 5.362617126899976224e+00, 5.596064724397100194e+00, 5.843560143744373307e+00, 6.106057585381734693e+00, 6.384585640900671436e+00, 6.680253728973824449e+00, 6.994259146058412709e+00, 7.327894795748901060e+00, 7.682557667824588764e+00, 8.059758146071137270e+00, 8.461130232962342889e+00, 8.888442789395671080e+00, 9.343611899025485155e+00, 9.828714479494622022e+00, 1.034600327721380625e+01, 1.089792339849122916e+01, 1.148713054801325790e+01, 1.211651116619788555e+01, 1.278920468010096321e+01, 1.350862810871281096e+01, 1.427850329305334421e+01, 1.510288705493181327e+01, 1.598620462612703196e+01, 1.693328673269081128e+01, 1.794941076780000506e+01, 1.904034654190823159e+01, 2.021240716182964334e+01, 2.147250566192247370e+01, 2.282821809199713505e+01, 2.428785385941680425e+01, 2.586053422878117785e+01, 2.755628000354674426e+01, 2.938610955221109564e+01, 3.136214849990951329e+01, 3.349775258749912582e+01, 3.580764540799625468e+01, 3.830807296872530167e+01, 4.101697730155473447e+01, 4.395419165876113623e+01, 4.714166019494196927e+01, 5.060368545366659226e+01, 5.436720746019445252e+01, 5.846211877912138439e+01, 6.292162054058128784e+01, 6.778262518512416663e+01, 7.308621254265223015e+01, 7.887814686488147292e+01, 8.520946359734658334e+01, 9.213713603387774717e+01, 9.972483357670754649e+01, 1.080437851679046426e+02, 1.171737636088621692e+02, 1.272042089988687372e+02, 1.382355124664102373e+02, 1.503804848151483311e+02, 1.637660387526102742e+02, 1.785351181233383403e+02, 1.948489131607280604e+02, 2.128894073598352670e+02, 2.328623093447990790e+02, 2.550004322843281994e+02, 2.795675942672445782e+02, 3.068631259124280934e+02, 3.372270867451200874e+02, 3.710463099965576255e+02, 4.087614170466174911e+02, 4.508749684194593670e+02, 4.979609488959773491e+02, 5.506758209385785877e+02, 6.097714244663179092e+02, 6.761100535726473685e+02, 7.506821038741422446e+02, 8.346267600518081192e+02, 9.292562845315541998e+02, 1.036084578498234728e+03, 1.156860819661897657e+03, 1.293609142453808600e+03, 1.448675521854205144e+03, 1.624783259532197615e+03, 1.825098759915318560e+03, 2.053309635972617554e+03, 2.313717614494777200e+03, 2.611349236640186999e+03, 2.952087994093624299e+03, 3.342832332560548180e+03, 3.791684927756595099e+03, 4.308179838716318955e+03, 4.903555624570201673e+03, 5.591084343634811452e+03, 6.386468625571246341e+03, 7.308321829412979440e+03, 8.378749812799703561e+03, 9.624057218749638059e+03, 1.107560666191146008e+04, 1.277086605445904388e+04, 1.475468792019489452e+04, 1.708087537417066343e+04, 1.981410309695485051e+04, 2.303227888204754908e+04, 2.682945317928632535e+04, 3.131941178398428200e+04, 3.664012209706997997e+04, 4.295924836668690170e+04, 5.048100882639843572e+04, 5.945472133180055290e+04, 7.018547875172689579e+04, 8.304751726175694003e+04, 9.850099805053575446e+04, 1.171131266261766060e+05, 1.395847982160589845e+05, 1.667843016393077556e+05, 1.997900626520524686e+05, 2.399449946032992187e+05, 2.889257939838013232e+05, 3.488315309194304548e+05, 4.222972201496778447e+05, 5.126398246369253619e+05, 6.240464876221989792e+05, 7.618179073233615941e+05, 9.326839300224119257e+05, 1.145214007774297539e+06, 1.410352646274233119e+06, 1.742120041875863385e+06, 2.158531716934287014e+06, 2.682809410126426731e+06, 3.344980563595418861e+06, 4.183997972337706048e+06, 5.250558008165501752e+06, 6.610860174141680988e+06, 8.351639423967558693e+06, 1.058692532393929900e+07, 1.346715235106239409e+07, 1.719148271024263021e+07, 2.202453449027701694e+07, 2.831917301724337797e+07, 3.654767820268344932e+07, 4.734452657230626106e+07, 6.156534063509513873e+07, 8.036843026897869248e+07, 1.053280284359690289e+08, 1.385921689084126286e+08, 1.831036985925683524e+08, 2.429109457458640820e+08, 3.236062393759667463e+08, 4.329475218599986663e+08, 5.817432967962929479e+08, 7.851179789388191786e+08, 1.064329197627075307e+09, 1.449389582912945485e+09, 1.982866469377991849e+09, 2.725414314698094324e+09, 3.763867964111621444e+09, 5.223138814950990937e+09, 7.283785810644397704e+09, 1.020809642381158743e+10, 1.437899318470510521e+10, 2.035836812543633578e+10, 2.897499827080027444e+10, 4.145773751645494878e+10, 5.963837683872426287e+10, 8.626228483915530800e+10, 1.254667045389825180e+11, 1.835212982264913186e+11, 2.699812207400151604e+11, 3.994928452151922954e+11, 5.946380558701434550e+11, 8.904409967424091107e+11, 1.341551941677775838e+12, 2.033768550332151892e+12, 3.102627959875753214e+12, 4.763598321705862063e+12, 7.361420360560813584e+12, 1.145126961456557423e+13, 1.793314186996273926e+13, 2.827585501285792232e+13, 4.489297053678444669e+13, 7.177802872658499571e+13, 1.155855098545820625e+14, 1.874833886367883093e+14, 3.063510356402174454e+14, 5.043400653005970242e+14, 8.366163396892429890e+14, 1.398556351640947289e+15, 2.356335749516164682e+15, 4.001765167382637456e+15, 6.851375128404941445e+15, 1.182690111761543990e+16, 2.058673527013806443e+16, 3.613968784314904633e+16, 6.399112184394213551e+16, 1.143016185628376923e+17, 2.059881383915666443e+17, 3.745846788353680914e+17, 6.874443034683149068e+17, 1.273407643613485314e+18, 2.381241916829895366e+18, 4.495835617307108399e+18, 8.571442024901952701e+18, 1.650443584181656965e+19, 3.210100352421317851e+19, 6.307780124442703091e+19, 1.252404031157661279e+20, 2.513005295649985394e+20, 5.096776255690838436e+20, 1.045019200016673046e+21, 2.166476479260878466e+21, 4.542138145678395463e+21, 9.632082324449137128e+21, 2.066386536688254528e+22, 4.485529785554428251e+22, 9.853879573610977508e+22, 2.191158874464374408e+23, 4.932835964390971668e+23, 1.124501529971774363e+24, 2.596269136156756008e+24, 6.072292938313625501e+24, 1.438989066308003836e+25, 3.455841956406570469e+25, 8.412655191713576490e+25, 2.076289061650816510e+26, 5.196515024640220322e+26, 1.319173194089644043e+27, 3.397455895980380794e+27, 8.879057454438503591e+27, 2.355272361492064126e+28, 6.342762007722624824e+28, 1.734531093990859705e+29, 4.817893170606830871e+29, 1.359597346490148232e+30, 3.898969689906500392e+30, 1.136542986529989936e+31, 3.368450043991780017e+31, 1.015304084709817260e+32, 3.113144376221918237e+32, 9.713072739730140403e+32, 3.084517643581725946e+33, 9.972682139820497284e+33, 3.283625052288491586e+34, 1.101378785390827536e+35, 3.764333367592714297e+35, 1.311403465938242926e+36, 4.658135710682813672e+36, 1.687517347470511392e+37, 6.237053685018323490e+37, 2.352571314427744869e+38, 9.058938240219699936e+38, 3.562249097611136071e+39, 1.430959291578558210e+40, 5.873974584984375049e+40, 2.464828549811283787e+41, 1.057649203090855628e+42, 4.642475639281078035e+42, 2.085287118272421779e+43, 9.588439985186632177e+43, 4.514982011246092280e+44, 2.177974048341973204e+45, 1.076720976822900458e+46, 5.457267432929085589e+46, 2.836869270455781134e+47, 1.513103201392011626e+48, 8.283974667225617075e+48, 4.657239491995971344e+49, 2.689796370712836937e+50, 1.596597846911970388e+51, 9.744154538256586629e+51, 6.117238394843313065e+52, 3.952049650585241827e+53, 2.628701592074258213e+54, 1.800990196502679393e+55, 1.271554462563068383e+56, 9.255880104477760711e+56, 6.949737920133919393e+57, 5.385167200769965621e+58, 4.308493668102978774e+59, 3.560951557542178371e+60, 3.041888528384649992e+61, 2.687094441930837189e+62, 2.455920538900000855e+63, 2.323648254168641537e+64, 2.277129741584892331e+65, 2.312633552913224734e+66, 2.435407592981291129e+67, 2.660910388822465246e+68, 3.018105943423533920e+69, 3.555823489510192503e+70, 4.354188877793849013e+71, 5.544975795511813315e+72, 7.348276481909886336e+73, 1.013998025722423261e+75, 1.457911462244607943e+76, 2.185488876819505295e+77, 3.418022153286623008e+78, 5.580843920601835728e+79, 9.519586502799733908e+80, 1.697573578247197786e+82, 3.166906670990180014e+83, 6.185099106418675430e+84, 1.265541134386934377e+86, 2.714828965877756899e+87, 6.110386802964494082e+88, 1.444054086171083239e+90, 3.586083726638388165e+91, 9.365231868063239600e+92, 2.574080116205122449e+94, 7.452134689862302719e+95, 2.274309903836169819e+97, 7.323011134121164749e+98, 2.489816421737932462e+100, 8.946533386359281588e+101, 3.400401372391165979e+103, 1.368288186208928217e+105, 5.834277489829591931e+106, 2.638486937672383424e+108, 1.266728882767139521e+110, 6.462225178314182803e+111, 3.506432320607573604e+113, 2.025608933943268165e+115, 1.247041677084784707e+117, 8.189865188405279038e+118, 5.743610894406099965e+120, 4.305808934084489763e+122, 3.454156966079496755e+124, 2.968316601530352737e+126, 2.735456242372183592e+128, 2.706317176690077847e+130, 2.877679916342060385e+132, 3.292412878268106390e+134, 4.057840961953725969e+136, 5.393783049105737324e+138, 7.741523901672235406e+140, 1.201209962310668456e+143, 2.017456079556807301e+145, 3.672176623483062526e+147, 7.253163798058577630e+149, 1.556591535302570570e+152, 3.634399832790394885e+154, }, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_weights.size() - 1); + m_committed_refinements = static_cast(m_weights.size() - 1); #else m_committed_refinements = m_weights.size() - 1; #endif @@ -430,7 +568,7 @@ void sinh_sinh_detail::init(const std::integral_constant&) { 1.57096255099783261137673508918980377e+00L, 1.57229290236721196082451564636254803e+00L, 1.57495658191266675503402671533627186e+00L, 1.57895955363616398471678434379990522e+00L, 1.58431078956361430514416599492388597e+00L, 1.59102230111703510742216272394562613e+00L, 1.59910918118616033722590556649394763e+00L, 1.60858965710906746764504456185444654e+00L, 1.61948515482641974319339137784305225e+00L, 1.63182037453073931785527493516038124e+00L, 1.64562337819112567903033806653906069e+00L, 1.66092568939542410935608828998468834e+00L, 1.67776240601646371733138779357535047e+00L, 1.69617232627708297296989766202480515e+00L, 1.71619808886073246730768842066355199e+00L, 1.73788632779101456236627555096372654e+00L, 1.76128784288515241044102589887617560e+00L, 1.78645778667368642025315725404601102e+00L, 1.81345586877233558659749539967614045e+00L, 1.84234657879265254187280543490489739e+00L, 1.87319942898662752121993510591579920e+00L, 1.90608921793761261888076943857856180e+00L, 1.94109631673677945144587926354356120e+00L, 1.97830697922181656566949720098719647e+00L, 2.01781367800384433737712026561151498e+00L, 2.05971546817081389507270282494773392e+00L, 2.10411838073232749275747224342524909e+00L, 2.15113584806337555354918618566085438e+00L, 2.20088916381459141771044083611555369e+00L, 2.25350797998611420231160903572594743e+00L, 2.30913084411305337537709048855358397e+00L, 2.36790577978511333384857209921738492e+00L, 2.42999091402365295350102767412517845e+00L, 2.49555515536908558968587982458158759e+00L, 2.56477892689313451429557802920827974e+00L, 2.63785495874745168415081659796280588e+00L, 2.71498914529626806741705564771250802e+00L, 2.79640147236028053619149909690973720e+00L, 2.88232702062657870038560203490158574e+00L, 2.97301705186029380311201985278736098e+00L, 3.06874018519362823755119514588303156e+00L, 3.16978367147348738564623946178566521e+00L, 3.27645477442732860056345607892739085e+00L, 3.38908226826615609816107421136979984e+00L, 3.50801806229286913554992299494422526e+00L, 3.63363896413353027399263692498221540e+00L, 3.76634859436988420367634452674074607e+00L, 3.90657946663630928939225987850575005e+00L, 4.05479524866754112035397645627643742e+00L, 4.21149322136091780158052739625729631e+00L, 4.37720695466646221916071477112304019e+00L, 4.55250922105994638849140210916632132e+00L, 4.73801516951078282566987752649050466e+00L, 4.93438578525358788671420711795537458e+00L, 5.14233166333819107447595069798421539e+00L, 5.36261712689997622445803908396748884e+00L, 5.59606472439710019418213140693069575e+00L, 5.84356014374437330661446789126222075e+00L, 6.10605758538173469317727364122669467e+00L, 6.38458564090067143612732202429488542e+00L, 6.68025372897382444864907987044889317e+00L, 6.99425914605841270881961646990609410e+00L, 7.32789479574890106033548644768353338e+00L, 7.68255766782458876413667730681699443e+00L, 8.05975814607113727007240055318338450e+00L, 8.46113023296234288939356989479671723e+00L, 8.88844278939567108027044653070693778e+00L, 9.34361189902548515485066576358196470e+00L, 9.82871447949462202212030994384949241e+00L, 1.03460032772138062549383568058709409e+01L, 1.08979233984912291622835480030167114e+01L, 1.14871305480132578973614919602781370e+01L, 1.21165111661978855517781913327317255e+01L, 1.27892046801009632078942555615288463e+01L, 1.35086281087128109623831457304510920e+01L, 1.42785032930533442126932924888187804e+01L, 1.51028870549318132669071327511660921e+01L, 1.59862046261270319640752848374642080e+01L, 1.69332867326908112807352382039426796e+01L, 1.79494107678000050622926329104204826e+01L, 1.90403465419082315888820165929975494e+01L, 2.02124071618296433363312214170232623e+01L, 2.14725056619224736964251610816575600e+01L, 2.28282180919971350546248653847563966e+01L, 2.42878538594168042463845071817020910e+01L, 2.58605342287811778487151334440784950e+01L, 2.75562800035467442565131080245429614e+01L, 2.93861095522110956389210768876799587e+01L, 3.13621484999095132865600012683857137e+01L, 3.34977525874991258153646142408367963e+01L, 3.58076454079962546803810835720597110e+01L, 3.83080729687253016658377309622401176e+01L, 4.10169773015547344709659456503154667e+01L, 4.39541916587611362308342994483809472e+01L, 4.71416601949419692729062784327679986e+01L, 5.06036854536665922553724504470269960e+01L, 5.43672074601944525232284101611170030e+01L, 5.84621187791213843904071404608607478e+01L, 6.29216205405812878410372213510070276e+01L, 6.77826251851241666263837617897404532e+01L, 7.30862125426522301461255132629846162e+01L, 7.88781468648814729209715096907821639e+01L, 8.52094635973465833426799692679733796e+01L, 9.21371360338777471668559829773781201e+01L, 9.97248335767075464896305315099053068e+01L, 1.08043785167904642576949987865910954e+02L, 1.17173763608862169247776700625586421e+02L, 1.27204208998868737227575356110541727e+02L, 1.38235512466410237338282474486031692e+02L, 1.50380484815148331050381123359927804e+02L, 1.63766038752610274212021042234298836e+02L, 1.78535118123338340289613569013808793e+02L, 1.94848913160728060357302969254459805e+02L, 2.12889407359835266977366307026062112e+02L, 2.32862309344799079018746113493039633e+02L, 2.55000432284328199435640048881527463e+02L, 2.79567594267244578195192766207761694e+02L, 3.06863125912428093434496643114651412e+02L, 3.37227086745120087399301385427960651e+02L, 3.71046309996557625549265358225650347e+02L, 4.08761417046617491055856040237506316e+02L, 4.50874968419459367009632339064163929e+02L, 4.97960948895977349122916983180817637e+02L, 5.50675820938578587679472462796822793e+02L, 6.09771424466317909206822143572649707e+02L, 6.76110053572647368547479902312230309e+02L, 7.50682103874142244645724064576848341e+02L, 8.34626760051808119187547981730818179e+02L, 9.29256284531554199823656475151338963e+02L, 1.03608457849823472804207172846963877e+03L, 1.15686081966189765730466332807313547e+03L, 1.29360914245380859999201252074469995e+03L, 1.44867552185420514387789438088656434e+03L, 1.62478325953219761549580736728832563e+03L, 1.82509875991531856022535679631713756e+03L, 2.05330963597261755441688599655848892e+03L, 2.31371761449477720025881552764731872e+03L, 2.61134923664018699944734187657483567e+03L, 2.95208799409362429898911389656789101e+03L, 3.34283233256054817982471990245472659e+03L, 3.79168492775659509883214798303432158e+03L, 4.30817983871631895490690508451026040e+03L, 4.90355562457020167332670064217006554e+03L, 5.59108434363481145162671079876733528e+03L, 6.38646862557124634146730890858054275e+03L, 7.30832182941297944038809179971510199e+03L, 8.37874981279970356111509048453001571e+03L, 9.62405721874963805881171453111047092e+03L, 1.10756066619114600841076275282388063e+04L, 1.27708660544590438787794590107117849e+04L, 1.47546879201948945213025955616435132e+04L, 1.70808753741706634268551294101897318e+04L, 1.98141030969548505096681178137364270e+04L, 2.30322788820475490754732581365999861e+04L, 2.68294531792863253502182123460963590e+04L, 3.13194117839842820030641964449539820e+04L, 3.66401220970699799668192565829190288e+04L, 4.29592483666869017028607105165763804e+04L, 5.04810088263984357248209974578040223e+04L, 5.94547213318005529011388227962133751e+04L, 7.01854787517268957919092596317475529e+04L, 8.30475172617569400265716546608431303e+04L, 9.85009980505357544638949542794405193e+04L, 1.17113126626176606026864191754698095e+05L, 1.39584798216058984483938678946454092e+05L, 1.66784301639307755633312351999980104e+05L, 1.99790062652052468605951710457597772e+05L, 2.39944994603299218686253514351518948e+05L, 2.88925793983801323167992289814829493e+05L, 3.48831530919430454806103930858415528e+05L, 4.22297220149677844682618484564386312e+05L, 5.12639824636925361908056913471196846e+05L, 6.24046487622198979196137566922551170e+05L, 7.61817907323361594136262168936978923e+05L, 9.32683930022411925704630601110030182e+05L, 1.14521400777429753902355978052778602e+06L, 1.41035264627423311876298925540665884e+06L, 1.74212004187586338510201667214170577e+06L, 2.15853171693428701405141183541166264e+06L, 2.68280941012642673073659887232388938e+06L, 3.34498056359541886091597912499527306e+06L, 4.18399797233770604788689812330719069e+06L, 5.25055800816550175243256559083639418e+06L, 6.61086017414168098803951872291131863e+06L, 8.35163942396755869310534556270941378e+06L, 1.05869253239392990034806970327887878e+07L, 1.34671523510623940861241599892229316e+07L, 1.71914827102426302145958883698307763e+07L, 2.20245344902770169422620623417295079e+07L, 2.83191730172433779681268016861978467e+07L, 3.65476782026834493187990343694010282e+07L, 4.73445265723062610640363034466641760e+07L, 6.15653406350951387288804933390908042e+07L, 8.03684302689786924828741611740519293e+07L, 1.05328028435969028854761469747289545e+08L, 1.38592168908412628618546923035162247e+08L, 1.83103698592568352374304770508191971e+08L, 2.42910945745864082034287213456845086e+08L, 3.23606239375966746282831194186614169e+08L, 4.32947521859998666323053129499091577e+08L, 5.81743296796292947920442886775592966e+08L, 7.85117978938819178602650773642870262e+08L, 1.06432919762707530726575966438229782e+09L, 1.44938958291294548467516226794019366e+09L, 1.98286646937799184909776706883985509e+09L, 2.72541431469809432350206616813747393e+09L, 3.76386796411162144400474070771015333e+09L, 5.22313881495099093715899688078276720e+09L, 7.28378581064439770444275729738468286e+09L, 1.02080964238115874250636198090464363e+10L, 1.43789931847051052135186583023967432e+10L, 2.03583681254363357780032810961889254e+10L, 2.89749982708002744366825785538936402e+10L, 4.14577375164549487752492409798515416e+10L, 5.96383768387242628650336526594122215e+10L, 8.62622848391553079951805623395652598e+10L, 1.25466704538982518000690409655705216e+11L, 1.83521298226491318558080545133554232e+11L, 2.69981220740015160361114268684563366e+11L, 3.99492845215192295441294253418780644e+11L, 5.94638055870143455023933020703444642e+11L, 8.90440996742409110650533033931653292e+11L, 1.34155194167777583831947241717631506e+12L, 2.03376855033215189170105222958089604e+12L, 3.10262795987575321360135087196684567e+12L, 4.76359832170586206290082815387968037e+12L, 7.36142036056081358397678626842794083e+12L, 1.14512696145655742338758840735549183e+13L, 1.79331418699627392634462052642542749e+13L, 2.82758550128579223200239017529280909e+13L, 4.48929705367844466861372765075631687e+13L, 7.17780287265849957064212371548037347e+13L, 1.15585509854582062520354852997620279e+14L, 1.87483388636788309288478433629583664e+14L, 3.06351035640217445409310567498133847e+14L, 5.04340065300597024230361727189343426e+14L, 8.36616339689242989007881200440488764e+14L, 1.39855635164094728875364679627485304e+15L, 2.35633574951616468243164849507855064e+15L, 4.00176516738263745645278590345795707e+15L, 6.85137512840494144543571512545601884e+15L, 1.18269011176154399046326619510431010e+16L, 2.05867352701380644281110910622942185e+16L, 3.61396878431490463311666873476678412e+16L, 6.39911218439421355095519025524482256e+16L, 1.14301618562837692261569180960886276e+17L, 2.05988138391566644299797673070467922e+17L, 3.74584678835368091393630059068193045e+17L, 6.87444303468314906803024757565005462e+17L, 1.27340764361348531366853034790770231e+18L, 2.38124191682989536626992792404294190e+18L, 4.49583561730710839927340662784958898e+18L, 8.57144202490195270096830399067728169e+18L, 1.65044358418165696532477771893166700e+19L, 3.21010035242131785085169993033188229e+19L, 6.30778012444270309076492866733769742e+19L, 1.25240403115766127899628450500249765e+20L, 2.51300529564998539443832117224536420e+20L, 5.09677625569083843571268035202853929e+20L, 1.04501920001667304566512216455267827e+21L, 2.16647647926087846601520265828431353e+21L, 4.54213814567839546278770815494416868e+21L, 9.63208232444913712819259248595549405e+21L, 2.06638653668825452816630915727527426e+22L, 4.48552978555442825059406438230470388e+22L, 9.85387957361097750825498509227133701e+22L, 2.19115887446437440814640517501285189e+23L, 4.93283596439097166796547625560314132e+23L, 1.12450152997177436346173556893175508e+24L, 2.59626913615675600812300017445220112e+24L, 6.07229293831362550112108555687653017e+24L, 1.43898906630800383562329122001513450e+25L, 3.45584195640657046905140678735606870e+25L, 8.41265519171357648977229820858109463e+25L, 2.07628906165081651016090959669418757e+26L, 5.19651502464022032237151119613068945e+26L, 1.31917319408964404296057699402007921e+27L, 3.39745589598038079361346075350889747e+27L, 8.87905745443850359109225209251728000e+27L, 2.35527236149206412607849676379867126e+28L, 6.34276200772262482389475687836384423e+28L, 1.73453109399085970484897533524593455e+29L, 4.81789317060683087119323058524624972e+29L, 1.35959734649014823198654051259347560e+30L, 3.89896968990650039174705544740914822e+30L, 1.13654298652998993600898528562905634e+31L, 3.36845004399178001650511659074612092e+31L, 1.01530408470981725989945294876828360e+32L, 3.11314437622191823730222798219255685e+32L, 9.71307273973014040273869048577801862e+32L, 3.08451764358172594571945077912559223e+33L, 9.97268213982049728423469082288644341e+33L, 3.28362505228849158612675319471610094e+34L, 1.10137878539082753552686700652535380e+35L, 3.76433336759271429732220889611944227e+35L, 1.31140346593824292621577115225698644e+36L, 4.65813571068281367213354863266427946e+36L, 1.68751734747051139203189162215633629e+37L, 6.23705368501832349017363870039959902e+37L, 2.35257131442774486893301429598817553e+38L, 9.05893824021969993626817980294413695e+38L, 3.56224909761113607077591549609142868e+39L, 1.43095929157855820977839447284784020e+40L, 5.87397458498437504922632656680942932e+40L, 2.46482854981128378684502286098690220e+41L, 1.05764920309085562822396787743332401e+42L, 4.64247563928107803530506772359734012e+42L, 2.08528711827242177927156523287132065e+43L, 9.58843998518663217709277358040461543e+43L, 4.51498201124609227956079072858258677e+44L, 2.17797404834197320411588567916752909e+45L, 1.07672097682290045825361349736107198e+46L, 5.45726743292908558875367244655615249e+46L, 2.83686927045578113375020568154351117e+47L, 1.51310320139201162564313806536303971e+48L, 8.28397466722561707458255405781541923e+48L, 4.65723949199597134403065145457979764e+49L, 2.68979637071283693718739500357715726e+50L, 1.59659784691197038762901224386099403e+51L, 9.74415453825658662874112107295166701e+51L, 6.11723839484331306452493250946377612e+52L, 3.95204965058524182677586041680204451e+53L, 2.62870159207425821306145211826683375e+54L, 1.80099019650267939321809025642439880e+55L, 1.27155446256306838318997486480890087e+56L, 9.25588010447776071059464920928086632e+56L, 6.94973792013391939342588109222317053e+57L, 5.38516720076996562080859176422021036e+58L, 4.30849366810297877444039522534393308e+59L, 3.56095155754217837059656555899190815e+60L, 3.04188852838464999204043663335571874e+61L, 2.68709444193083718922293037351168007e+62L, 2.45592053890000085507656649738841713e+63L, 2.32364825416864153745578539849845717e+64L, 2.27712974158489233058096874867974690e+65L, 2.31263355291322473374027008502422191e+66L, 2.43540759298129112939388619780518297e+67L, 2.66091038882246524570905302589811279e+68L, 3.01810594342353392025458974267831671e+69L, 3.55582348951019250289525994888733340e+70L, 4.35418887779384901315251041444022899e+71L, 5.54497579551181331524599144834616000e+72L, 7.34827648190988633565298908145357523e+73L, 1.01399802572242326074394064208241565e+75L, 1.45791146224460794340779409761344050e+76L, 2.18548887681950529537081926891986328e+77L, 3.41802215328662300798456454917771592e+78L, 5.58084392060183572830239216435019125e+79L, 9.51958650279973390758331753317257950e+80L, 1.69757357824719778562747265505252946e+82L, 3.16690667099018001388115076193097403e+83L, 6.18509910641867543038652223056425804e+84L, 1.26554113438693437654962757714903554e+86L, 2.71482896587775689871692274985919286e+87L, 6.11038680296449408162222719197467046e+88L, 1.44405408617108323852658132530082074e+90L, 3.58608372663838816495703910754396082e+91L, 9.36523186806323959966772742491929522e+92L, 2.57408011620512244881601880029319908e+94L, 7.45213468986230271920125476429174422e+95L, 2.27430990383616981910627355587444817e+97L, 7.32301113412116474943463116371095103e+98L, 2.48981642173793246167799170730006141e+100L, 8.94653338635928158843209476986997508e+101L, 3.40040137239116597862336436061445989e+103L, 1.36828818620892821730981225660157834e+105L, 5.83427748982959193060571787534606697e+106L, 2.63848693767238342424340754241860221e+108L, 1.26672888276713952132156406152434700e+110L, 6.46222517831418280306046165038174027e+111L, 3.50643232060757360375065377104810475e+113L, 2.02560893394326816509670349356333828e+115L, 1.24704167708478470702273287091045609e+117L, 8.18986518840527903795498196049278255e+118L, 5.74361089440609996487936977642920132e+120L, 4.30580893408448976261136511421423734e+122L, 3.45415696607949675499703108821962730e+124L, 2.96831660153035273688363706593385374e+126L, 2.73545624237218359223636851390580041e+128L, 2.70631717669007784745026117275242499e+130L, 2.87767991634206038473084413615742294e+132L, 3.29241287826810639047033778585737812e+134L, 4.05784096195372596931902665934287382e+136L, 5.39378304910573732382585500687737807e+138L, 7.74152390167223540621293648465491842e+140L, 1.20120996231066845642412985516875175e+143L, 2.01745607955680730064740044686640147e+145L, 3.67217662348306252636962893865111425e+147L, 7.25316379805857762968710347450256630e+149L, 1.55659153530257056999948366173645285e+152L, 3.63439983279039488510674235872123571e+154L, 9.24438760046827764031744167566698413e+156L, 2.56505460126015154661078513762260065e+159L, 7.77468767447849521051212939671796074e+161L, 2.57775340952739965069105894604883404e+164L, 9.36236559200171990439286451934391539e+166L, 3.73025928974609135812613567068392186e+169L, 1.63280699411172483017448754437467171e+172L, 7.86350685466830069681739337700194312e+174L, 4.17288659053103260909421860789088638e+177L, 2.44376468354452976432259429734905692e+180L, 1.58182604983516221850901239956537929e+183L, 1.13349408906485996833819126879692168e+186L, 9.00609317867158059779746161516574861e+188L, 7.94724581006520631483760616875503191e+191L, 7.80148734070770210787180909072341250e+194L, 8.53389980133319877537947288273508168e+197L, 1.04199907704816359699116619452657846e+201L, 1.42261945983107616739713958471131412e+204L, 2.17558254343347922345039318825837040e+207L, 3.73339221107050141050095672544726852e+210L, 7.20212971416878494124587287789857735e+213L, 1.56476087980246841023430707631510252e+217L, 3.83599289170088247519036274601375492e+220L, 1.06310518934360483187879118646180568e+224L, 3.33719954606082150504485397744546787e+227L, 1.18890644129926367056386614030943443e+231L, 4.81657405194041613555936914144916344e+234L, 2.22347874123114616622582251703709887e+238L, 1.17199258523361213934517364652872480e+242L, 7.06839671131322838482398929154588609e+245L, 4.88812662946732326430886472870070228e+249L, 3.88441192207630934518298772235960268e+253L, 3.55483921979499015020713995580889030e+257L, 3.75484510816250928148708038190395303e+261L, 4.58798720933643387311573482445886110e+265L, 6.49989966050568126079524541048529496e+269L, 1.07018103272413666142402906179157598e+274L, 2.05258799808849457042833394124187317e+278L, 4.59710306190259625117029822247574448e+282L, 1.20521640888055636836192268959955157e+287L, 3.70784262206985650361726040790594581e+291L, 1.34198324051735290325452259089861845e+296L, 5.72866922601176092550850127280325304e+300L, 2.89181208605318627652310091586335359e+305L, 1.73078309894901278503683645288680165e+310L, 1.23150483936231719457381379774516673e+315L, 1.04456022524616506171048138618772005e+320L, 1.05909848234544418123752752792015094e+325L, 1.28725694153849592436889057738754649e+330L, 1.88087499295689639308903342601320607e+335L, 3.31344446614783992260480183208324732e+340L, 7.05835740270200829603933852702222207e+345L, 1.82360609116987101874149506325271866e+351L, 5.73167527316999715111499624522524490e+356L, 2.19834460849656433024448179756162490e+362L, 1.03213196012299389398122351217909554e+368L, 5.95090459142945173642877532664315820e+373L, 4.22711326689560391486862730288730260e+379L, 3.71146073815998244096864189178283440e+385L, 4.04143285030597516778349567433491877e+391L, 5.47630493200706306950643242188138639e+397L, 9.26610183846830899934754118194991047e+403L, 1.96463867218278875638951764233831097e+410L, 5.23826401399289488725708314794013273e+416L, 1.76269979359229195206462702562496087e+423L, 7.51358974574222029659643352716721030e+429L, 4.07203690042780566335825621191079282e+436L, 2.81652392485993763998682010256080428e+443L, 2.49586432083962995754217338958145192e+450L, 2.84464997550187838898841424132533307e+457L, 4.18656911271834268911740204159815337e+464L, 7.98835944729121866190974499356597568e+471L, 1.98427885725374523364086923738598523e+479L, 6.44313780728812316513345459942694301e+486L, 2.74646447436726496994650106679472135e+494L, 1.54345331097536381511922890966406624e+502L, 1.14854061177091306735355343708426610e+510L, 1.13671799925771100929831048483235430e+518L, 1.50301408173820906903238314130252343e+526L, 2.66721742401349021977265127553699936e+534L, 6.38191727827371990119668697526910696e+542L, 2.06864189323929509313332139375745418e+551L, 9.12718925758572793769909253655546363e+559L, 5.50827087084343716443556503345322384e+568L, 4.56943096951975523591483538202467049e+577L, 5.23664812769936727945516120554813767e+586L, 8.33295831969513770916127078276468196e+595L, 1.85073603040006635508770638738735213e+605L, 5.76725912854578779706265298662279369e+614L, 2.53507221317613667093309510235117825e+624L, 1.58037348241924263546145926074674624e+634L, 1.40497098317887844492262106048698980e+644L, 1.79118532756424559114150403858023467e+654L, 3.29340233091271285034548969456076701e+664L, 8.78384225704905897945003526718634352e+674L, 3.41824790512159692619674889187554870e+685L, 1.95247619547378795632466874007982924e+696L, 1.64685615123975037569921507294781182e+707L, 2.06385512057306929298128483493412318e+718L, 3.86691162964076111860523245198584961e+729L, 1.09008736553561747232882422664193409e+741L, 4.65333391196364819411904308657257877e+752L, 3.02768585771015415481330091322447912e+764L, 3.02262040534180824988954474846992913e+776L, 4.66133722640174567906974646266839244e+788L, 1.11806119156969171229108916233644999e+801L, 4.20019655376202192049844032418033555e+813L, 2.48880615873773868126893696694455625e+826L, 2.34286193142054643224145247339492426e+839L, 3.52941162196327496812531706159176164e+852L, 8.57183106082165907783781027353105401e+865L, 3.38163627323872188047900717079347979e+879L, 2.18363447282104345585022834572887531e+893L, 2.32596275137292895223293068081362090e+907L, 4.11925247272574761366980289309686003e+921L, 1.22265489460258041690738897372130823e+936L, 6.13184165651799059701146847592463464e+950L, 5.23922303275545560334122760478493484e+965L, 7.69087233862553980667730597006685190e+980L, 1.95622275953749870274795206909257068e+996L, 8.69670052895401378378113763338699958e+1011L, 6.81715148318539616903616353647181598e+1027L, 9.50697711954141544724599553989093262e+1043L, 2.38019733682587370869498352841844428e+1060L, 1.07973324919847346937291516197684901e+1077L, 8.95814284819025403820872820042945790e+1093L, 1.37229192661307043018958002675397831e+1111L, 3.91918794622242371528673544888524419e+1128L, 2.10730218913863433412315532873510194e+1146L, 2.15459607934366008026324206138837528e+1164L, 4.23163839295623007237154131840451677e+1182L, 1.61294441956204958952970453918741185e+1201L, 1.20568335528354973250479511763057854e+1220L, 1.78630819666459637235669417819650103e+1239L, 5.30233997012953850434143324467683139e+1258L, 3.18800705045665419646272046839479382e+1278L, 3.92589619613994835597705628928304867e+1298L, 1.00145056975313260959947278741812233e+1319L, 5.35268808912615454171856125906228237e+1339L, 6.06491960606218539467705074145131193e+1360L, 1.47410187506507259371724909079906759e+1382L, 7.77855372825975976779550291054389078e+1403L, 9.02071339187528665617085297107535931e+1425L, 2.32776342394968427168699373890370933e+1448L, 1.35351409374730203846799381939288903e+1471L, 1.79625881886715571166142200348072039e+1494L, 5.51189494978629938318487744451579809e+1517L, 3.96270198063441303687686251379779681e+1541L, 6.76492837567767494547614386605795924e+1565L, 2.77991073110506719318274536923711255e+1590L, 2.78805951202715437087943440518839779e+1615L, 6.92116280606414755524296394791409952e+1640L, 4.31380309053366092943951122004431463e+1666L, 6.84923073262139995438889690748178280e+1692L, 2.81137418164430829179092468240459910e+1719L, 3.02821524237655652451836921974619657e+1746L, 8.69048903533522694231765189726868666e+1773L, 6.74828063313306417588175763238310325e+1801L, 1.44026065844141159256872926595644247e+1830L, 8.58426091495439408178371839859019039e+1858L, 1.45211919400936944187225846047638548e+1888L, 7.08718013380970011842483247147601395e+1917L, 1.01475962220405902523641440040104610e+1948L, 4.33542978691578087509838132034723750e+1978L, 5.62285772227295495777726116212032065e+2009L, 2.25285072921565445630031609130087435e+2041L, 2.83839050906274298341210206309759282e+2073L, 1.14501659579022194588844609345877849e+2106L, 1.50629562239998305958408533546634030e+2139L, 6.58342161306998815751663631350733541e+2172L, 9.74198999952210922892973281379349494e+2206L, 4.97552704772088889228035264268694867e+2241L, 8.94330619882842342247706838649878784e+2276L, 5.77072420156026800834371478648673792e+2312L, 1.36388225285320494361282201451878478e+2349L, 1.20508189950290985406298094670730466e+2386L, 4.06413362486490272506766749982212198e+2423L, 5.34308092015215251528601382597439463e+2461L, }, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_weights.size() - 1); + m_committed_refinements = static_cast(m_weights.size() - 1); #else m_committed_refinements = m_weights.size() - 1; #endif @@ -471,7 +609,7 @@ void sinh_sinh_detail::init(const std::integral_constant&) { 1.57096255099783261137673508918980377e+00Q, 1.57229290236721196082451564636254803e+00Q, 1.57495658191266675503402671533627186e+00Q, 1.57895955363616398471678434379990522e+00Q, 1.58431078956361430514416599492388597e+00Q, 1.59102230111703510742216272394562613e+00Q, 1.59910918118616033722590556649394763e+00Q, 1.60858965710906746764504456185444654e+00Q, 1.61948515482641974319339137784305225e+00Q, 1.63182037453073931785527493516038124e+00Q, 1.64562337819112567903033806653906069e+00Q, 1.66092568939542410935608828998468834e+00Q, 1.67776240601646371733138779357535047e+00Q, 1.69617232627708297296989766202480515e+00Q, 1.71619808886073246730768842066355199e+00Q, 1.73788632779101456236627555096372654e+00Q, 1.76128784288515241044102589887617560e+00Q, 1.78645778667368642025315725404601102e+00Q, 1.81345586877233558659749539967614045e+00Q, 1.84234657879265254187280543490489739e+00Q, 1.87319942898662752121993510591579920e+00Q, 1.90608921793761261888076943857856180e+00Q, 1.94109631673677945144587926354356120e+00Q, 1.97830697922181656566949720098719647e+00Q, 2.01781367800384433737712026561151498e+00Q, 2.05971546817081389507270282494773392e+00Q, 2.10411838073232749275747224342524909e+00Q, 2.15113584806337555354918618566085438e+00Q, 2.20088916381459141771044083611555369e+00Q, 2.25350797998611420231160903572594743e+00Q, 2.30913084411305337537709048855358397e+00Q, 2.36790577978511333384857209921738492e+00Q, 2.42999091402365295350102767412517845e+00Q, 2.49555515536908558968587982458158759e+00Q, 2.56477892689313451429557802920827974e+00Q, 2.63785495874745168415081659796280588e+00Q, 2.71498914529626806741705564771250802e+00Q, 2.79640147236028053619149909690973720e+00Q, 2.88232702062657870038560203490158574e+00Q, 2.97301705186029380311201985278736098e+00Q, 3.06874018519362823755119514588303156e+00Q, 3.16978367147348738564623946178566521e+00Q, 3.27645477442732860056345607892739085e+00Q, 3.38908226826615609816107421136979984e+00Q, 3.50801806229286913554992299494422526e+00Q, 3.63363896413353027399263692498221540e+00Q, 3.76634859436988420367634452674074607e+00Q, 3.90657946663630928939225987850575005e+00Q, 4.05479524866754112035397645627643742e+00Q, 4.21149322136091780158052739625729631e+00Q, 4.37720695466646221916071477112304019e+00Q, 4.55250922105994638849140210916632132e+00Q, 4.73801516951078282566987752649050466e+00Q, 4.93438578525358788671420711795537458e+00Q, 5.14233166333819107447595069798421539e+00Q, 5.36261712689997622445803908396748884e+00Q, 5.59606472439710019418213140693069575e+00Q, 5.84356014374437330661446789126222075e+00Q, 6.10605758538173469317727364122669467e+00Q, 6.38458564090067143612732202429488542e+00Q, 6.68025372897382444864907987044889317e+00Q, 6.99425914605841270881961646990609410e+00Q, 7.32789479574890106033548644768353338e+00Q, 7.68255766782458876413667730681699443e+00Q, 8.05975814607113727007240055318338450e+00Q, 8.46113023296234288939356989479671723e+00Q, 8.88844278939567108027044653070693778e+00Q, 9.34361189902548515485066576358196470e+00Q, 9.82871447949462202212030994384949241e+00Q, 1.03460032772138062549383568058709409e+01Q, 1.08979233984912291622835480030167114e+01Q, 1.14871305480132578973614919602781370e+01Q, 1.21165111661978855517781913327317255e+01Q, 1.27892046801009632078942555615288463e+01Q, 1.35086281087128109623831457304510920e+01Q, 1.42785032930533442126932924888187804e+01Q, 1.51028870549318132669071327511660921e+01Q, 1.59862046261270319640752848374642080e+01Q, 1.69332867326908112807352382039426796e+01Q, 1.79494107678000050622926329104204826e+01Q, 1.90403465419082315888820165929975494e+01Q, 2.02124071618296433363312214170232623e+01Q, 2.14725056619224736964251610816575600e+01Q, 2.28282180919971350546248653847563966e+01Q, 2.42878538594168042463845071817020910e+01Q, 2.58605342287811778487151334440784950e+01Q, 2.75562800035467442565131080245429614e+01Q, 2.93861095522110956389210768876799587e+01Q, 3.13621484999095132865600012683857137e+01Q, 3.34977525874991258153646142408367963e+01Q, 3.58076454079962546803810835720597110e+01Q, 3.83080729687253016658377309622401176e+01Q, 4.10169773015547344709659456503154667e+01Q, 4.39541916587611362308342994483809472e+01Q, 4.71416601949419692729062784327679986e+01Q, 5.06036854536665922553724504470269960e+01Q, 5.43672074601944525232284101611170030e+01Q, 5.84621187791213843904071404608607478e+01Q, 6.29216205405812878410372213510070276e+01Q, 6.77826251851241666263837617897404532e+01Q, 7.30862125426522301461255132629846162e+01Q, 7.88781468648814729209715096907821639e+01Q, 8.52094635973465833426799692679733796e+01Q, 9.21371360338777471668559829773781201e+01Q, 9.97248335767075464896305315099053068e+01Q, 1.08043785167904642576949987865910954e+02Q, 1.17173763608862169247776700625586421e+02Q, 1.27204208998868737227575356110541727e+02Q, 1.38235512466410237338282474486031692e+02Q, 1.50380484815148331050381123359927804e+02Q, 1.63766038752610274212021042234298836e+02Q, 1.78535118123338340289613569013808793e+02Q, 1.94848913160728060357302969254459805e+02Q, 2.12889407359835266977366307026062112e+02Q, 2.32862309344799079018746113493039633e+02Q, 2.55000432284328199435640048881527463e+02Q, 2.79567594267244578195192766207761694e+02Q, 3.06863125912428093434496643114651412e+02Q, 3.37227086745120087399301385427960651e+02Q, 3.71046309996557625549265358225650347e+02Q, 4.08761417046617491055856040237506316e+02Q, 4.50874968419459367009632339064163929e+02Q, 4.97960948895977349122916983180817637e+02Q, 5.50675820938578587679472462796822793e+02Q, 6.09771424466317909206822143572649707e+02Q, 6.76110053572647368547479902312230309e+02Q, 7.50682103874142244645724064576848341e+02Q, 8.34626760051808119187547981730818179e+02Q, 9.29256284531554199823656475151338963e+02Q, 1.03608457849823472804207172846963877e+03Q, 1.15686081966189765730466332807313547e+03Q, 1.29360914245380859999201252074469995e+03Q, 1.44867552185420514387789438088656434e+03Q, 1.62478325953219761549580736728832563e+03Q, 1.82509875991531856022535679631713756e+03Q, 2.05330963597261755441688599655848892e+03Q, 2.31371761449477720025881552764731872e+03Q, 2.61134923664018699944734187657483567e+03Q, 2.95208799409362429898911389656789101e+03Q, 3.34283233256054817982471990245472659e+03Q, 3.79168492775659509883214798303432158e+03Q, 4.30817983871631895490690508451026040e+03Q, 4.90355562457020167332670064217006554e+03Q, 5.59108434363481145162671079876733528e+03Q, 6.38646862557124634146730890858054275e+03Q, 7.30832182941297944038809179971510199e+03Q, 8.37874981279970356111509048453001571e+03Q, 9.62405721874963805881171453111047092e+03Q, 1.10756066619114600841076275282388063e+04Q, 1.27708660544590438787794590107117849e+04Q, 1.47546879201948945213025955616435132e+04Q, 1.70808753741706634268551294101897318e+04Q, 1.98141030969548505096681178137364270e+04Q, 2.30322788820475490754732581365999861e+04Q, 2.68294531792863253502182123460963590e+04Q, 3.13194117839842820030641964449539820e+04Q, 3.66401220970699799668192565829190288e+04Q, 4.29592483666869017028607105165763804e+04Q, 5.04810088263984357248209974578040223e+04Q, 5.94547213318005529011388227962133751e+04Q, 7.01854787517268957919092596317475529e+04Q, 8.30475172617569400265716546608431303e+04Q, 9.85009980505357544638949542794405193e+04Q, 1.17113126626176606026864191754698095e+05Q, 1.39584798216058984483938678946454092e+05Q, 1.66784301639307755633312351999980104e+05Q, 1.99790062652052468605951710457597772e+05Q, 2.39944994603299218686253514351518948e+05Q, 2.88925793983801323167992289814829493e+05Q, 3.48831530919430454806103930858415528e+05Q, 4.22297220149677844682618484564386312e+05Q, 5.12639824636925361908056913471196846e+05Q, 6.24046487622198979196137566922551170e+05Q, 7.61817907323361594136262168936978923e+05Q, 9.32683930022411925704630601110030182e+05Q, 1.14521400777429753902355978052778602e+06Q, 1.41035264627423311876298925540665884e+06Q, 1.74212004187586338510201667214170577e+06Q, 2.15853171693428701405141183541166264e+06Q, 2.68280941012642673073659887232388938e+06Q, 3.34498056359541886091597912499527306e+06Q, 4.18399797233770604788689812330719069e+06Q, 5.25055800816550175243256559083639418e+06Q, 6.61086017414168098803951872291131863e+06Q, 8.35163942396755869310534556270941378e+06Q, 1.05869253239392990034806970327887878e+07Q, 1.34671523510623940861241599892229316e+07Q, 1.71914827102426302145958883698307763e+07Q, 2.20245344902770169422620623417295079e+07Q, 2.83191730172433779681268016861978467e+07Q, 3.65476782026834493187990343694010282e+07Q, 4.73445265723062610640363034466641760e+07Q, 6.15653406350951387288804933390908042e+07Q, 8.03684302689786924828741611740519293e+07Q, 1.05328028435969028854761469747289545e+08Q, 1.38592168908412628618546923035162247e+08Q, 1.83103698592568352374304770508191971e+08Q, 2.42910945745864082034287213456845086e+08Q, 3.23606239375966746282831194186614169e+08Q, 4.32947521859998666323053129499091577e+08Q, 5.81743296796292947920442886775592966e+08Q, 7.85117978938819178602650773642870262e+08Q, 1.06432919762707530726575966438229782e+09Q, 1.44938958291294548467516226794019366e+09Q, 1.98286646937799184909776706883985509e+09Q, 2.72541431469809432350206616813747393e+09Q, 3.76386796411162144400474070771015333e+09Q, 5.22313881495099093715899688078276720e+09Q, 7.28378581064439770444275729738468286e+09Q, 1.02080964238115874250636198090464363e+10Q, 1.43789931847051052135186583023967432e+10Q, 2.03583681254363357780032810961889254e+10Q, 2.89749982708002744366825785538936402e+10Q, 4.14577375164549487752492409798515416e+10Q, 5.96383768387242628650336526594122215e+10Q, 8.62622848391553079951805623395652598e+10Q, 1.25466704538982518000690409655705216e+11Q, 1.83521298226491318558080545133554232e+11Q, 2.69981220740015160361114268684563366e+11Q, 3.99492845215192295441294253418780644e+11Q, 5.94638055870143455023933020703444642e+11Q, 8.90440996742409110650533033931653292e+11Q, 1.34155194167777583831947241717631506e+12Q, 2.03376855033215189170105222958089604e+12Q, 3.10262795987575321360135087196684567e+12Q, 4.76359832170586206290082815387968037e+12Q, 7.36142036056081358397678626842794083e+12Q, 1.14512696145655742338758840735549183e+13Q, 1.79331418699627392634462052642542749e+13Q, 2.82758550128579223200239017529280909e+13Q, 4.48929705367844466861372765075631687e+13Q, 7.17780287265849957064212371548037347e+13Q, 1.15585509854582062520354852997620279e+14Q, 1.87483388636788309288478433629583664e+14Q, 3.06351035640217445409310567498133847e+14Q, 5.04340065300597024230361727189343426e+14Q, 8.36616339689242989007881200440488764e+14Q, 1.39855635164094728875364679627485304e+15Q, 2.35633574951616468243164849507855064e+15Q, 4.00176516738263745645278590345795707e+15Q, 6.85137512840494144543571512545601884e+15Q, 1.18269011176154399046326619510431010e+16Q, 2.05867352701380644281110910622942185e+16Q, 3.61396878431490463311666873476678412e+16Q, 6.39911218439421355095519025524482256e+16Q, 1.14301618562837692261569180960886276e+17Q, 2.05988138391566644299797673070467922e+17Q, 3.74584678835368091393630059068193045e+17Q, 6.87444303468314906803024757565005462e+17Q, 1.27340764361348531366853034790770231e+18Q, 2.38124191682989536626992792404294190e+18Q, 4.49583561730710839927340662784958898e+18Q, 8.57144202490195270096830399067728169e+18Q, 1.65044358418165696532477771893166700e+19Q, 3.21010035242131785085169993033188229e+19Q, 6.30778012444270309076492866733769742e+19Q, 1.25240403115766127899628450500249765e+20Q, 2.51300529564998539443832117224536420e+20Q, 5.09677625569083843571268035202853929e+20Q, 1.04501920001667304566512216455267827e+21Q, 2.16647647926087846601520265828431353e+21Q, 4.54213814567839546278770815494416868e+21Q, 9.63208232444913712819259248595549405e+21Q, 2.06638653668825452816630915727527426e+22Q, 4.48552978555442825059406438230470388e+22Q, 9.85387957361097750825498509227133701e+22Q, 2.19115887446437440814640517501285189e+23Q, 4.93283596439097166796547625560314132e+23Q, 1.12450152997177436346173556893175508e+24Q, 2.59626913615675600812300017445220112e+24Q, 6.07229293831362550112108555687653017e+24Q, 1.43898906630800383562329122001513450e+25Q, 3.45584195640657046905140678735606870e+25Q, 8.41265519171357648977229820858109463e+25Q, 2.07628906165081651016090959669418757e+26Q, 5.19651502464022032237151119613068945e+26Q, 1.31917319408964404296057699402007921e+27Q, 3.39745589598038079361346075350889747e+27Q, 8.87905745443850359109225209251728000e+27Q, 2.35527236149206412607849676379867126e+28Q, 6.34276200772262482389475687836384423e+28Q, 1.73453109399085970484897533524593455e+29Q, 4.81789317060683087119323058524624972e+29Q, 1.35959734649014823198654051259347560e+30Q, 3.89896968990650039174705544740914822e+30Q, 1.13654298652998993600898528562905634e+31Q, 3.36845004399178001650511659074612092e+31Q, 1.01530408470981725989945294876828360e+32Q, 3.11314437622191823730222798219255685e+32Q, 9.71307273973014040273869048577801862e+32Q, 3.08451764358172594571945077912559223e+33Q, 9.97268213982049728423469082288644341e+33Q, 3.28362505228849158612675319471610094e+34Q, 1.10137878539082753552686700652535380e+35Q, 3.76433336759271429732220889611944227e+35Q, 1.31140346593824292621577115225698644e+36Q, 4.65813571068281367213354863266427946e+36Q, 1.68751734747051139203189162215633629e+37Q, 6.23705368501832349017363870039959902e+37Q, 2.35257131442774486893301429598817553e+38Q, 9.05893824021969993626817980294413695e+38Q, 3.56224909761113607077591549609142868e+39Q, 1.43095929157855820977839447284784020e+40Q, 5.87397458498437504922632656680942932e+40Q, 2.46482854981128378684502286098690220e+41Q, 1.05764920309085562822396787743332401e+42Q, 4.64247563928107803530506772359734012e+42Q, 2.08528711827242177927156523287132065e+43Q, 9.58843998518663217709277358040461543e+43Q, 4.51498201124609227956079072858258677e+44Q, 2.17797404834197320411588567916752909e+45Q, 1.07672097682290045825361349736107198e+46Q, 5.45726743292908558875367244655615249e+46Q, 2.83686927045578113375020568154351117e+47Q, 1.51310320139201162564313806536303971e+48Q, 8.28397466722561707458255405781541923e+48Q, 4.65723949199597134403065145457979764e+49Q, 2.68979637071283693718739500357715726e+50Q, 1.59659784691197038762901224386099403e+51Q, 9.74415453825658662874112107295166701e+51Q, 6.11723839484331306452493250946377612e+52Q, 3.95204965058524182677586041680204451e+53Q, 2.62870159207425821306145211826683375e+54Q, 1.80099019650267939321809025642439880e+55Q, 1.27155446256306838318997486480890087e+56Q, 9.25588010447776071059464920928086632e+56Q, 6.94973792013391939342588109222317053e+57Q, 5.38516720076996562080859176422021036e+58Q, 4.30849366810297877444039522534393308e+59Q, 3.56095155754217837059656555899190815e+60Q, 3.04188852838464999204043663335571874e+61Q, 2.68709444193083718922293037351168007e+62Q, 2.45592053890000085507656649738841713e+63Q, 2.32364825416864153745578539849845717e+64Q, 2.27712974158489233058096874867974690e+65Q, 2.31263355291322473374027008502422191e+66Q, 2.43540759298129112939388619780518297e+67Q, 2.66091038882246524570905302589811279e+68Q, 3.01810594342353392025458974267831671e+69Q, 3.55582348951019250289525994888733340e+70Q, 4.35418887779384901315251041444022899e+71Q, 5.54497579551181331524599144834616000e+72Q, 7.34827648190988633565298908145357523e+73Q, 1.01399802572242326074394064208241565e+75Q, 1.45791146224460794340779409761344050e+76Q, 2.18548887681950529537081926891986328e+77Q, 3.41802215328662300798456454917771592e+78Q, 5.58084392060183572830239216435019125e+79Q, 9.51958650279973390758331753317257950e+80Q, 1.69757357824719778562747265505252946e+82Q, 3.16690667099018001388115076193097403e+83Q, 6.18509910641867543038652223056425804e+84Q, 1.26554113438693437654962757714903554e+86Q, 2.71482896587775689871692274985919286e+87Q, 6.11038680296449408162222719197467046e+88Q, 1.44405408617108323852658132530082074e+90Q, 3.58608372663838816495703910754396082e+91Q, 9.36523186806323959966772742491929522e+92Q, 2.57408011620512244881601880029319908e+94Q, 7.45213468986230271920125476429174422e+95Q, 2.27430990383616981910627355587444817e+97Q, 7.32301113412116474943463116371095103e+98Q, 2.48981642173793246167799170730006141e+100Q, 8.94653338635928158843209476986997508e+101Q, 3.40040137239116597862336436061445989e+103Q, 1.36828818620892821730981225660157834e+105Q, 5.83427748982959193060571787534606697e+106Q, 2.63848693767238342424340754241860221e+108Q, 1.26672888276713952132156406152434700e+110Q, 6.46222517831418280306046165038174027e+111Q, 3.50643232060757360375065377104810475e+113Q, 2.02560893394326816509670349356333828e+115Q, 1.24704167708478470702273287091045609e+117Q, 8.18986518840527903795498196049278255e+118Q, 5.74361089440609996487936977642920132e+120Q, 4.30580893408448976261136511421423734e+122Q, 3.45415696607949675499703108821962730e+124Q, 2.96831660153035273688363706593385374e+126Q, 2.73545624237218359223636851390580041e+128Q, 2.70631717669007784745026117275242499e+130Q, 2.87767991634206038473084413615742294e+132Q, 3.29241287826810639047033778585737812e+134Q, 4.05784096195372596931902665934287382e+136Q, 5.39378304910573732382585500687737807e+138Q, 7.74152390167223540621293648465491842e+140Q, 1.20120996231066845642412985516875175e+143Q, 2.01745607955680730064740044686640147e+145Q, 3.67217662348306252636962893865111425e+147Q, 7.25316379805857762968710347450256630e+149Q, 1.55659153530257056999948366173645285e+152Q, 3.63439983279039488510674235872123571e+154Q, 9.24438760046827764031744167566698413e+156Q, 2.56505460126015154661078513762260065e+159Q, 7.77468767447849521051212939671796074e+161Q, 2.57775340952739965069105894604883404e+164Q, 9.36236559200171990439286451934391539e+166Q, 3.73025928974609135812613567068392186e+169Q, 1.63280699411172483017448754437467171e+172Q, 7.86350685466830069681739337700194312e+174Q, 4.17288659053103260909421860789088638e+177Q, 2.44376468354452976432259429734905692e+180Q, 1.58182604983516221850901239956537929e+183Q, 1.13349408906485996833819126879692168e+186Q, 9.00609317867158059779746161516574861e+188Q, 7.94724581006520631483760616875503191e+191Q, 7.80148734070770210787180909072341250e+194Q, 8.53389980133319877537947288273508168e+197Q, 1.04199907704816359699116619452657846e+201Q, 1.42261945983107616739713958471131412e+204Q, 2.17558254343347922345039318825837040e+207Q, 3.73339221107050141050095672544726852e+210Q, 7.20212971416878494124587287789857735e+213Q, 1.56476087980246841023430707631510252e+217Q, 3.83599289170088247519036274601375492e+220Q, 1.06310518934360483187879118646180568e+224Q, 3.33719954606082150504485397744546787e+227Q, 1.18890644129926367056386614030943443e+231Q, 4.81657405194041613555936914144916344e+234Q, 2.22347874123114616622582251703709887e+238Q, 1.17199258523361213934517364652872480e+242Q, 7.06839671131322838482398929154588609e+245Q, 4.88812662946732326430886472870070228e+249Q, 3.88441192207630934518298772235960268e+253Q, 3.55483921979499015020713995580889030e+257Q, 3.75484510816250928148708038190395303e+261Q, 4.58798720933643387311573482445886110e+265Q, 6.49989966050568126079524541048529496e+269Q, 1.07018103272413666142402906179157598e+274Q, 2.05258799808849457042833394124187317e+278Q, 4.59710306190259625117029822247574448e+282Q, 1.20521640888055636836192268959955157e+287Q, 3.70784262206985650361726040790594581e+291Q, 1.34198324051735290325452259089861845e+296Q, 5.72866922601176092550850127280325304e+300Q, 2.89181208605318627652310091586335359e+305Q, 1.73078309894901278503683645288680165e+310Q, 1.23150483936231719457381379774516673e+315Q, 1.04456022524616506171048138618772005e+320Q, 1.05909848234544418123752752792015094e+325Q, 1.28725694153849592436889057738754649e+330Q, 1.88087499295689639308903342601320607e+335Q, 3.31344446614783992260480183208324732e+340Q, 7.05835740270200829603933852702222207e+345Q, 1.82360609116987101874149506325271866e+351Q, 5.73167527316999715111499624522524490e+356Q, 2.19834460849656433024448179756162490e+362Q, 1.03213196012299389398122351217909554e+368Q, 5.95090459142945173642877532664315820e+373Q, 4.22711326689560391486862730288730260e+379Q, 3.71146073815998244096864189178283440e+385Q, 4.04143285030597516778349567433491877e+391Q, 5.47630493200706306950643242188138639e+397Q, 9.26610183846830899934754118194991047e+403Q, 1.96463867218278875638951764233831097e+410Q, 5.23826401399289488725708314794013273e+416Q, 1.76269979359229195206462702562496087e+423Q, 7.51358974574222029659643352716721030e+429Q, 4.07203690042780566335825621191079282e+436Q, 2.81652392485993763998682010256080428e+443Q, 2.49586432083962995754217338958145192e+450Q, 2.84464997550187838898841424132533307e+457Q, 4.18656911271834268911740204159815337e+464Q, 7.98835944729121866190974499356597568e+471Q, 1.98427885725374523364086923738598523e+479Q, 6.44313780728812316513345459942694301e+486Q, 2.74646447436726496994650106679472135e+494Q, 1.54345331097536381511922890966406624e+502Q, 1.14854061177091306735355343708426610e+510Q, 1.13671799925771100929831048483235430e+518Q, 1.50301408173820906903238314130252343e+526Q, 2.66721742401349021977265127553699936e+534Q, 6.38191727827371990119668697526910696e+542Q, 2.06864189323929509313332139375745418e+551Q, 9.12718925758572793769909253655546363e+559Q, 5.50827087084343716443556503345322384e+568Q, 4.56943096951975523591483538202467049e+577Q, 5.23664812769936727945516120554813767e+586Q, 8.33295831969513770916127078276468196e+595Q, 1.85073603040006635508770638738735213e+605Q, 5.76725912854578779706265298662279369e+614Q, 2.53507221317613667093309510235117825e+624Q, 1.58037348241924263546145926074674624e+634Q, 1.40497098317887844492262106048698980e+644Q, 1.79118532756424559114150403858023467e+654Q, 3.29340233091271285034548969456076701e+664Q, 8.78384225704905897945003526718634352e+674Q, 3.41824790512159692619674889187554870e+685Q, 1.95247619547378795632466874007982924e+696Q, 1.64685615123975037569921507294781182e+707Q, 2.06385512057306929298128483493412318e+718Q, 3.86691162964076111860523245198584961e+729Q, 1.09008736553561747232882422664193409e+741Q, 4.65333391196364819411904308657257877e+752Q, 3.02768585771015415481330091322447912e+764Q, 3.02262040534180824988954474846992913e+776Q, 4.66133722640174567906974646266839244e+788Q, 1.11806119156969171229108916233644999e+801Q, 4.20019655376202192049844032418033555e+813Q, 2.48880615873773868126893696694455625e+826Q, 2.34286193142054643224145247339492426e+839Q, 3.52941162196327496812531706159176164e+852Q, 8.57183106082165907783781027353105401e+865Q, 3.38163627323872188047900717079347979e+879Q, 2.18363447282104345585022834572887531e+893Q, 2.32596275137292895223293068081362090e+907Q, 4.11925247272574761366980289309686003e+921Q, 1.22265489460258041690738897372130823e+936Q, 6.13184165651799059701146847592463464e+950Q, 5.23922303275545560334122760478493484e+965Q, 7.69087233862553980667730597006685190e+980Q, 1.95622275953749870274795206909257068e+996Q, 8.69670052895401378378113763338699958e+1011Q, 6.81715148318539616903616353647181598e+1027Q, 9.50697711954141544724599553989093262e+1043Q, 2.38019733682587370869498352841844428e+1060Q, 1.07973324919847346937291516197684901e+1077Q, 8.95814284819025403820872820042945790e+1093Q, 1.37229192661307043018958002675397831e+1111Q, 3.91918794622242371528673544888524419e+1128Q, 2.10730218913863433412315532873510194e+1146Q, 2.15459607934366008026324206138837528e+1164Q, 4.23163839295623007237154131840451677e+1182Q, 1.61294441956204958952970453918741185e+1201Q, 1.20568335528354973250479511763057854e+1220Q, 1.78630819666459637235669417819650103e+1239Q, 5.30233997012953850434143324467683139e+1258Q, 3.18800705045665419646272046839479382e+1278Q, 3.92589619613994835597705628928304867e+1298Q, 1.00145056975313260959947278741812233e+1319Q, 5.35268808912615454171856125906228237e+1339Q, 6.06491960606218539467705074145131193e+1360Q, 1.47410187506507259371724909079906759e+1382Q, 7.77855372825975976779550291054389078e+1403Q, 9.02071339187528665617085297107535931e+1425Q, 2.32776342394968427168699373890370933e+1448Q, 1.35351409374730203846799381939288903e+1471Q, 1.79625881886715571166142200348072039e+1494Q, 5.51189494978629938318487744451579809e+1517Q, 3.96270198063441303687686251379779681e+1541Q, 6.76492837567767494547614386605795924e+1565Q, 2.77991073110506719318274536923711255e+1590Q, 2.78805951202715437087943440518839779e+1615Q, 6.92116280606414755524296394791409952e+1640Q, 4.31380309053366092943951122004431463e+1666Q, 6.84923073262139995438889690748178280e+1692Q, 2.81137418164430829179092468240459910e+1719Q, 3.02821524237655652451836921974619657e+1746Q, 8.69048903533522694231765189726868666e+1773Q, 6.74828063313306417588175763238310325e+1801Q, 1.44026065844141159256872926595644247e+1830Q, 8.58426091495439408178371839859019039e+1858Q, 1.45211919400936944187225846047638548e+1888Q, 7.08718013380970011842483247147601395e+1917Q, 1.01475962220405902523641440040104610e+1948Q, 4.33542978691578087509838132034723750e+1978Q, 5.62285772227295495777726116212032065e+2009Q, 2.25285072921565445630031609130087435e+2041Q, 2.83839050906274298341210206309759282e+2073Q, 1.14501659579022194588844609345877849e+2106Q, 1.50629562239998305958408533546634030e+2139Q, 6.58342161306998815751663631350733541e+2172Q, 9.74198999952210922892973281379349494e+2206Q, 4.97552704772088889228035264268694867e+2241Q, 8.94330619882842342247706838649878784e+2276Q, 5.77072420156026800834371478648673792e+2312Q, 1.36388225285320494361282201451878478e+2349Q, 1.20508189950290985406298094670730466e+2386Q, 4.06413362486490272506766749982212198e+2423Q, 5.34308092015215251528601382597439463e+2461Q, }, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_weights.size() - 1); + m_committed_refinements = static_cast(m_weights.size() - 1); #else m_committed_refinements = m_weights.size() - 1; #endif @@ -488,7 +626,7 @@ void sinh_sinh_detail::init(const std::integral_constant&) } #endif -}}}} +}} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC @@ -501,8 +639,7 @@ void sinh_sinh_detail::init(const std::integral_constant&) #include #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail { @@ -1189,9 +1326,9 @@ __constant__ double* m_weights_double[8] = { m_weights_double_7, m_weights_double_8 }; -__constant__ boost::math::size_t float_coefficients_size[8] = {4, 4, 8, 16, 32, 65, 129, 259}; +__constant__ BOOST_MATH_NAMESPACE::size_t float_coefficients_size[8] = {4, 4, 8, 16, 32, 65, 129, 259}; -__constant__ boost::math::size_t double_coefficients_size[8] = {6, 6, 12, 24, 49, 98, 196, 391}; +__constant__ BOOST_MATH_NAMESPACE::size_t double_coefficients_size[8] = {6, 6, 12, 24, 49, 98, 196, 391}; template struct coefficients_selector; @@ -1212,31 +1349,31 @@ struct coefficients_selector __device__ static const auto size() { return double_coefficients_size; } }; -template > -__device__ auto sinh_sinh_integrate_impl(const F& f, Real tolerance, Real* error, Real* L1, boost::math::size_t* levels) +template > +__device__ auto sinh_sinh_integrate_impl(const F& f, Real tolerance, Real* error, Real* L1, BOOST_MATH_NAMESPACE::size_t* levels) { BOOST_MATH_STD_USING - using boost::math::constants::half; - using boost::math::constants::half_pi; - using boost::math::size_t; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::constants::half_pi; + using BOOST_MATH_NAMESPACE::size_t; constexpr auto function = "boost::math::quadrature::sinh_sinh<%1%>::integrate"; using K = decltype(f(static_cast(0))); - static_assert(!boost::math::is_integral::value, + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value, "The return type cannot be integral, it must be either a real or complex floating point type."); - K y_max = f(boost::math::tools::max_value()); + K y_max = f(BOOST_MATH_NAMESPACE::tools::max_value()); - if(abs(y_max) > boost::math::tools::epsilon()) + if(abs(y_max) > BOOST_MATH_NAMESPACE::tools::epsilon()) { return static_cast(policies::raise_domain_error(function, "The function you are trying to integrate does not go to zero at infinity, and instead evaluates to %1%", y_max, Policy())); } - K y_min = f(-boost::math::tools::max_value()); + K y_min = f(-BOOST_MATH_NAMESPACE::tools::max_value()); - if(abs(y_min) > boost::math::tools::epsilon()) + if(abs(y_min) > BOOST_MATH_NAMESPACE::tools::epsilon()) { return static_cast(policies::raise_domain_error(function, "The function you are trying to integrate does not go to zero at -infinity, and instead evaluates to %1%", y_max, Policy())); @@ -1286,7 +1423,7 @@ __device__ auto sinh_sinh_integrate_impl(const F& f, Real tolerance, Real* error Real absum = 0; Real abterm1 = 1; - Real eps = boost::math::tools::epsilon()*L1_I1; + Real eps = BOOST_MATH_NAMESPACE::tools::epsilon()*L1_I1; auto abscissa_row = m_abscissas[i]; auto weight_row = m_weights[i]; @@ -1312,7 +1449,7 @@ __device__ auto sinh_sinh_integrate_impl(const F& f, Real tolerance, Real* error L1_I1 += absum*h; err = abs(I0 - I1); - if (!(boost::math::isfinite)(L1_I1)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(L1_I1)) { constexpr auto err_msg = "The sinh_sinh quadrature evaluated your function at a singular point, leading to the value %1%.\n" "sinh_sinh quadrature cannot handle singularities in the domain.\n" @@ -1345,8 +1482,7 @@ __device__ auto sinh_sinh_integrate_impl(const F& f, Real tolerance, Real* error } // Namespace detail } // Namespace quadrature -} // Namespace math -} // Namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ENABLE_CUDA diff --git a/include/boost/math/quadrature/detail/tanh_sinh_detail.hpp b/include/boost/math/quadrature/detail/tanh_sinh_detail.hpp index 47961423b4..c4c5fa0ffd 100644 --- a/include/boost/math/quadrature/detail/tanh_sinh_detail.hpp +++ b/include/boost/math/quadrature/detail/tanh_sinh_detail.hpp @@ -7,19 +7,24 @@ #ifndef BOOST_MATH_QUADRATURE_DETAIL_TANH_SINH_DETAIL_HPP #define BOOST_MATH_QUADRATURE_DETAIL_TANH_SINH_DETAIL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include #include +#include #ifdef BOOST_MATH_HAS_THREADS +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif -namespace boost{ namespace math{ namespace quadrature { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail{ // Returns the tanh-sinh quadrature of a function f over the open interval (-1, 1) @@ -50,6 +55,8 @@ class tanh_sinh_detail template decltype(std::declval()(std::declval(), std::declval())) integrate(const F f, Real* error, Real* L1, const char* function, Real left_min_complement, Real right_min_complement, Real tolerance, std::size_t* levels) const; + template + decltype(std::declval()(std::declval(), std::declval())) integrate(const F f, const decltype(std::declval()(std::declval(), std::declval()))& zero, Norm norm, Real* error, Real* L1, const char* function, Real left_min_complement, Real right_min_complement, Real tolerance, std::size_t* levels) const; private: const std::vector& get_abscissa_row(std::size_t n)const @@ -126,7 +133,7 @@ class tanh_sinh_detail #endif Real h = ldexp(static_cast(1), -static_cast(row)); std::size_t first_complement = 0; - std::size_t n = boost::math::itrunc(ceil((m_t_max - h) / (2 * h))); + std::size_t n = BOOST_MATH_NAMESPACE::itrunc(ceil((m_t_max - h) / (2 * h))); m_abscissas[row].reserve(n); m_weights[row].reserve(n); for (Real pos = h; pos < m_t_max; pos += 2 * h) @@ -144,14 +151,14 @@ class tanh_sinh_detail { using std::tanh; using std::sinh; - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half_pi; return tanh(half_pi()*sinh(t)); } static inline Real weight_at_t(const Real& t) { using std::cosh; using std::sinh; - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half_pi; Real cs = cosh(half_pi() * sinh(t)); return half_pi() * cosh(t) / (cs * cs); } @@ -160,7 +167,7 @@ class tanh_sinh_detail using std::cosh; using std::exp; using std::sinh; - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half_pi; Real u2 = half_pi() * sinh(t); return 1 / (exp(u2) *cosh(u2)); } @@ -168,7 +175,7 @@ class tanh_sinh_detail { using std::log; using std::sqrt; - using boost::math::constants::pi; + using BOOST_MATH_NAMESPACE::constants::pi; Real l = log(2-x) - log(x); return log((sqrt(l * l + pi() * pi()) + l) / pi()); }; @@ -179,7 +186,7 @@ class tanh_sinh_detail mutable std::vector m_first_complements; std::size_t m_max_refinements, m_inital_row_length{}; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - mutable boost::math::detail::atomic_unsigned_type m_committed_refinements{}; + mutable BOOST_MATH_NAMESPACE::detail::atomic_unsigned_type m_committed_refinements{}; mutable std::mutex m_mutex; #else mutable unsigned m_committed_refinements; @@ -197,8 +204,8 @@ decltype(std::declval()(std::declval(), std::declval())) tanh_sin using std::tanh; using std::sinh; using std::sqrt; - using boost::math::constants::half; - using boost::math::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::constants::half_pi; // // The type of the result: @@ -238,10 +245,10 @@ decltype(std::declval()(std::declval(), std::declval())) tanh_sin // result_type yp{ f(-1 - m_abscissas[0][max_left_position], m_abscissas[0][max_left_position]) }; result_type ym{ f(1 + m_abscissas[0][max_right_position], -m_abscissas[0][max_right_position]) }; - result_type tail_tolerance{ (std::max)(boost::math::tools::epsilon(), Real(tolerance * tolerance)) }; + result_type tail_tolerance{ (std::max)(BOOST_MATH_NAMESPACE::tools::epsilon(), Real(tolerance * tolerance)) }; while (max_left_position) { - if ((boost::math::isfinite)(yp)) + if ((BOOST_MATH_NAMESPACE::isfinite)(yp)) break; --max_left_position; yp = f(-1 - m_abscissas[0][max_left_position], m_abscissas[0][max_left_position]); @@ -261,7 +268,7 @@ decltype(std::declval()(std::declval(), std::declval())) tanh_sin // while (max_right_position) { - if ((boost::math::isfinite)(ym)) + if ((BOOST_MATH_NAMESPACE::isfinite)(ym)) break; --max_right_position; ym = f(1 + m_abscissas[0][max_right_position], -m_abscissas[0][max_right_position]); @@ -296,7 +303,7 @@ decltype(std::declval()(std::declval(), std::declval())) tanh_sin Real x = m_abscissas[0][i]; Real xc = x; Real w = m_weights[0][i]; - if ((boost::math::signbit)(x)) + if ((BOOST_MATH_NAMESPACE::signbit)(x)) { // We have stored x - 1: x = 1 + xc; @@ -373,7 +380,7 @@ decltype(std::declval()(std::declval(), std::declval())) tanh_sin do { yp = f(-1 - abscissa_row[max_left_index], abscissa_row[max_left_index]); - if ((boost::math::isfinite)(yp)) + if ((BOOST_MATH_NAMESPACE::isfinite)(yp)) break; if(max_left_position <= 2) { @@ -388,7 +395,7 @@ decltype(std::declval()(std::declval(), std::declval())) tanh_sin do { ym = f(1 + abscissa_row[max_right_index], -abscissa_row[max_right_index]); - if ((boost::math::isfinite)(ym)) + if ((BOOST_MATH_NAMESPACE::isfinite)(ym)) break; if (max_right_position <= 2) { @@ -454,7 +461,7 @@ decltype(std::declval()(std::declval(), std::declval())) tanh_sin Real last_err = err; err = abs(I0 - I1); - if (!(boost::math::isfinite)(I1)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(I1)) { return policies::raise_evaluation_error(function, "The tanh_sinh quadrature evaluated your function at a singular point and got %1%. Please narrow the bounds of integration or check your function for singularities.", I1, Policy()); } @@ -470,7 +477,7 @@ decltype(std::declval()(std::declval(), std::declval())) tanh_sin else if(thrash_count > 2) // OK, terrible error, but giving up anyway! terminate = true; - else if (last_err < boost::math::tools::root_epsilon()) + else if (last_err < BOOST_MATH_NAMESPACE::tools::root_epsilon()) // Trying to squeeze precision that probably isn't there, abort: terminate = true; else @@ -557,6 +564,383 @@ decltype(std::declval()(std::declval(), std::declval())) tanh_sin return I1; } +template +template +decltype(std::declval()(std::declval(), std::declval())) tanh_sinh_detail::integrate(const F f, const decltype(std::declval()(std::declval(), std::declval()))& zero, Norm norm, Real* error, Real* L1, const char* function, Real left_min_complement, Real right_min_complement, Real tolerance, std::size_t* levels) const +{ + const auto magnitude = [&](const decltype(std::declval()(std::declval(), std::declval()))& value) -> Real { return static_cast(norm(value)); }; + using std::abs; + using std::fabs; + using std::floor; + using std::tanh; + using std::sinh; + using std::sqrt; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::constants::half_pi; + + // + // The type of the result: + typedef decltype(std::declval()(std::declval(), std::declval())) result_type; + + Real h = m_t_max / m_inital_row_length; + result_type I0 = half_pi() * f(0, 1); + Real L1_I0 = magnitude(I0); + // + // We maintain 4 integer values: + // max_left_position is the logical index of the abscissa value closest to the + // left endpoint of the range that we can call f(x_i) on without rounding error + // inside f(x_i) causing evaluation at the endpoint. + // max_left_index is the actual position in the current row that has a logical index + // no higher than max_left_position. Remember that since we only store odd numbered + // indexes in each row, this may actually be one position to the left of max_left_position + // in the case that is even. Then, if we only evaluate f(-x_i) for abscissa values + // i <= max_left_index we will never evaluate f(-x_i) at the left endpoint. + // max_right_position and max_right_index are defined similarly for the right boundary + // and are used to guard evaluation of f(x_i). + // + // max_left_position and max_right_position start off as the last element in row zero: + // + std::size_t max_left_position(m_abscissas[0].size() - 1); + std::size_t max_left_index, max_right_position(max_left_position), max_right_index; + // + // Decrement max_left_position and max_right_position until the complement + // of the abscissa value is greater than the smallest permitted (as specified + // by the function caller): + // + while ((max_left_position > 1) && fabs(m_abscissas[0][max_left_position]) < left_min_complement) + --max_left_position; + while ((max_right_position > 1) && fabs(m_abscissas[0][max_right_position]) < right_min_complement) + --max_right_position; + // + // Check for non-finite values at the end points: + // + result_type yp{ f(-1 - m_abscissas[0][max_left_position], m_abscissas[0][max_left_position]) }; + result_type ym{ f(1 + m_abscissas[0][max_right_position], -m_abscissas[0][max_right_position]) }; + Real tail_tolerance{ (std::max)(BOOST_MATH_NAMESPACE::tools::epsilon(), Real(tolerance * tolerance)) }; + while (max_left_position) + { + if ((BOOST_MATH_NAMESPACE::isfinite)(magnitude(yp))) + break; + --max_left_position; + yp = f(-1 - m_abscissas[0][max_left_position], m_abscissas[0][max_left_position]); + } + // + // Also remove points which are insignificant or zero: + // + while (max_left_position > 1) + { + if (magnitude(yp * m_weights[0][max_left_position]) > abs(L1_I0 * tail_tolerance)) + break; + --max_left_position; + yp = f(-1 - m_abscissas[0][max_left_position], m_abscissas[0][max_left_position]); + } + // + // Over again for the right hand side: + // + while (max_right_position) + { + if ((BOOST_MATH_NAMESPACE::isfinite)(magnitude(ym))) + break; + --max_right_position; + ym = f(1 + m_abscissas[0][max_right_position], -m_abscissas[0][max_right_position]); + } + while (max_right_position > 1) + { + if (magnitude(ym * m_weights[0][max_right_position]) > abs(L1_I0 * tail_tolerance)) + break; + --max_right_position; + ym = f(1 + m_abscissas[0][max_right_position], -m_abscissas[0][max_right_position]); + } + + if ((max_left_position == 0) || (max_right_position == 0)) + { + policies::raise_evaluation_error(function, "The tanh_sinh quadrature found your function to be non-finite everywhere! Please check your function for singularities.", magnitude(ym), Policy()); + return ym; + } + + I0 += yp * m_weights[0][max_left_position] + ym * m_weights[0][max_right_position]; + L1_I0 += magnitude(yp * m_weights[0][max_left_position]) + magnitude(ym * m_weights[0][max_right_position]); + // + // Assumption: left_min_complement/right_min_complement are sufficiently small that we only + // ever decrement through the stored values that are complements (the negative ones), and + // never ever hit the true abscissa values (positive stored values). + // + BOOST_MATH_ASSERT(m_abscissas[0][max_left_position] < 0); + BOOST_MATH_ASSERT(m_abscissas[0][max_right_position] < 0); + + for(size_t i = 1; i < m_abscissas[0].size(); ++i) + { + if ((i >= max_right_position) && (i >= max_left_position)) + break; + Real x = m_abscissas[0][i]; + Real xc = x; + Real w = m_weights[0][i]; + if ((BOOST_MATH_NAMESPACE::signbit)(x)) + { + // We have stored x - 1: + x = 1 + xc; + } + else + xc = x - 1; + yp = i < max_right_position ? f(x, -xc) : zero; + ym = i < max_left_position ? f(-x, xc) : zero; + I0 += (yp + ym)*w; + L1_I0 += (magnitude(yp) + magnitude(ym))*w; + } + // + // We have: + // k = current row. + // I0 = last integral value. + // I1 = current integral value. + // L1_I0 and L1_I1 are the absolute integral values. + // + size_t k = 1; + result_type I1 = I0; + Real L1_I1 = L1_I0; + Real err = 0; + // + // thrash_count is a heuristic - it counts how many time the error has actually increased + // rather than decreased, if this gets too high we abort... + // + unsigned thrash_count = 0; + + while (k < 4 || (k < m_weights.size() && k < m_max_refinements) ) + { + I0 = I1; + L1_I0 = L1_I1; + + I1 = half()*I0; + L1_I1 = half()*L1_I0; + h *= half(); + result_type sum = zero; + Real absum = 0; + Real endpoint_error = 0; + auto const& abscissa_row = this->get_abscissa_row(k); + auto const& weight_row = this->get_weight_row(k); + std::size_t first_complement_index = this->get_first_complement_index(k); + // + // At the start of each new row we need to update the max left/right indexes + // at which we can evaluate f(x_i). The new logical position is simply twice + // the old value. The new max index is one position to the left of the new + // logical value (remember each row contains only odd numbered positions). + // Then we have to make a single check, to see if one position to the right + // is also in bounds (this is the new abscissa value in this row which is + // known to be in between a value known to be in bounds, and one known to be + // not in bounds). + // Thus, we filter which abscissa values generate a call to f(x_i), with a single + // floating point comparison per loop. Everything else is integer logic. + // + BOOST_MATH_ASSERT(max_left_position); + max_left_index = max_left_position - 1; + max_left_position *= 2; + BOOST_MATH_ASSERT(max_right_position); + max_right_index = max_right_position - 1; + max_right_position *= 2; + if ((abscissa_row.size() > max_left_index + 1) && (fabs(abscissa_row[max_left_index + 1]) > left_min_complement)) + { + ++max_left_position; + ++max_left_index; + } + if ((abscissa_row.size() > max_right_index + 1) && (fabs(abscissa_row[max_right_index + 1]) > right_min_complement)) + { + ++max_right_position; + ++max_right_index; + } + // + // We also check that our endpoints don't hit singularities: + // + do + { + yp = f(-1 - abscissa_row[max_left_index], abscissa_row[max_left_index]); + if ((BOOST_MATH_NAMESPACE::isfinite)(magnitude(yp))) + break; + if(max_left_position <= 2) + { + policies::raise_evaluation_error(function, "The tanh_sinh quadrature found your function to be non-finite everywhere! Please check your function for singularities.", magnitude(ym), Policy()); + return ym; + } + max_left_position -= 2; + --max_left_index; + } while (abscissa_row[max_left_index] < 0); + bool truncate_left(false), truncate_right(false); + if (abs(L1_I1 * tail_tolerance) > magnitude(yp * weight_row[max_left_index])) + truncate_left = true; + do + { + ym = f(1 + abscissa_row[max_right_index], -abscissa_row[max_right_index]); + if ((BOOST_MATH_NAMESPACE::isfinite)(magnitude(ym))) + break; + if (max_right_position <= 2) + { + policies::raise_evaluation_error(function, "The tanh_sinh quadrature found your function to be non-finite everywhere! Please check your function for singularities.", magnitude(ym), Policy()); + return ym; + } + --max_right_index; + max_right_position -= 2; + } while (abscissa_row[max_right_index] < 0); + if (abs(L1_I1 * tail_tolerance) > magnitude(ym * weight_row[max_right_index])) + truncate_right = true; + + sum += yp * weight_row[max_left_index] + ym * weight_row[max_right_index]; + absum += magnitude(yp * weight_row[max_left_index]) + magnitude(ym * weight_row[max_right_index]); + // + // We estimate the error due to truncation as the value contributed by the two most extreme points. + // In most cases this is tiny and can be ignored, if it is significant then either the area of the + // integral is so far our in the tails that our exponent range can't reach it (example x^-p at double + // precision and p ~ 1), or our function is truncated near epsilon, and we have had to narrow our endpoints. + // In this latter case we may over-estimate the error, but this is the best we can do. + // In any event, we do not add endpoint_error to the error estimate until we terminate the main loop, + // otherwise it can make things appear to be non-converged, when in reality, they are as converged as they + // will ever be. + // + endpoint_error = absum; + + for(size_t j = 0; j < weight_row.size(); ++j) + { + // If both left and right abscissa values are out of bounds at this step + // we can just stop this loop right now: + if ((j >= max_left_index) && (j >= max_right_index)) + break; + Real x = abscissa_row[j]; + Real xc = x; + Real w = weight_row[j]; + if (j >= first_complement_index) + { + // We have stored x - 1: + BOOST_MATH_ASSERT(x < 0); + x = 1 + xc; + } + else + { + BOOST_MATH_ASSERT(x >= 0); + xc = x - 1; + } + + yp = j >= max_right_index ? zero : f(x, -xc); + ym = j >= max_left_index ? zero : f(-x, xc); + result_type term = (yp + ym)*w; + sum += term; + + // A question arises as to how accurately we actually need to estimate the L1 integral. + // For simple integrands, computing the L1 norm makes the integration 20% slower, + // but for more complicated integrands, this calculation is not noticeable. + Real abterm = (magnitude(yp) + magnitude(ym))*w; + absum += abterm; + } + + I1 += sum*h; + L1_I1 += absum*h; + + ++k; + Real last_err = err; + err = magnitude(I0 - I1); + + if (!(BOOST_MATH_NAMESPACE::isfinite)(magnitude(I1))) + { + policies::raise_evaluation_error(function, "The tanh_sinh quadrature evaluated your function at a singular point and got %1%. Please narrow the bounds of integration or check your function for singularities.", magnitude(I1), Policy()); + return I1; + } + // + // If the error is increasing, and we're past level 4, something bad is very likely happening: + // + if ((err * 1.5 > last_err) && (k > 4)) + { + bool terminate = false; + if ((++thrash_count > 1) && (last_err < 1e-3)) + // Probably just thrashing, abort: + terminate = true; + else if(thrash_count > 2) + // OK, terrible error, but giving up anyway! + terminate = true; + else if (last_err < BOOST_MATH_NAMESPACE::tools::root_epsilon()) + // Trying to squeeze precision that probably isn't there, abort: + terminate = true; + else + { + // Take a look at the end points, if there's significant new area being + // discovered, then we're not able to get close enough to the endpoints + // to ever find the integral: + if (endpoint_error * h > err) + terminate = true; + } + + if (terminate) + { + // We could raise an evaluation_error, but since we likely have some sort of result, just return the last one + // (ie before the error started going up) + I1 = I0; + L1_I1 = L1_I0; + --k; + err = last_err + endpoint_error * h; + break; + } + // Fall through and keep going, assume we've discovered a new feature of f(x).... + } + // + // Termination condition: + // No more levels are considered once the error is less than the specified tolerance. + // Note however, that we always go down at least 4 levels, otherwise we risk missing + // features of interest in f() - imagine for example a function which flatlines, except + // for a very small "spike". An example would be the incomplete beta integral with large + // parameters. We could keep hunting until we find something, but that would handicap + // integrals which really are zero.... so a compromise then! + // + if ((err <= abs(tolerance*L1_I1)) && (k >= 4)) + { + // + // A quick sanity check: have we at some point narrowed our boundaries as a result + // of non-finite values? If so let's check that the area isn't on an increasing + // trajectory at our new end point, and increase our error estimate by the last + // good value as an estimate for what we may have discarded. + // + if (max_left_index && (max_left_index < abscissa_row.size() - 1) && (abs(abscissa_row[max_left_index + 1]) > left_min_complement)) + { + yp = f(-1 - abscissa_row[max_left_index], abscissa_row[max_left_index]) * weight_row[max_left_index]; + ym = f(-1 - abscissa_row[max_left_index - 1], abscissa_row[max_left_index - 1]) * weight_row[max_left_index - 1]; + if (magnitude(yp) > magnitude(ym)) + { + policies::raise_evaluation_error(function, "The tanh_sinh quadrature evaluated your function at a singular point and got %1%. Integration bounds were automatically narrowed, but the integral was found to be increasing at the new endpoint. Please check your function, and consider providing a 2-argument functor.", magnitude(I1), Policy()); + return I1; + } + } + if (max_right_index && (max_right_index < abscissa_row.size() - 1) && (abs(abscissa_row[max_right_index + 1]) > right_min_complement)) + { + yp = f(1 + abscissa_row[max_right_index], -abscissa_row[max_right_index]) * weight_row[max_right_index]; + ym = f(1 + abscissa_row[max_right_index - 1], -abscissa_row[max_right_index - 1]) * weight_row[max_right_index - 1]; + if (magnitude(yp) > magnitude(ym)) + { + policies::raise_evaluation_error(function, "The tanh_sinh quadrature evaluated your function at a singular point and got %1%. Integration bounds were automatically narrowed, but the integral was found to be increasing at the new endpoint. Please check your function, and consider providing a 2-argument functor.", magnitude(I1), Policy()); + return I1; + } + } + err += endpoint_error * h; + break; + } + + if ((truncate_left) && (max_left_position > 1)) + --max_left_position; + if ((truncate_right) && (max_right_position > 1)) + --max_right_position; + + } + if (error) + { + *error = err; + } + + if (L1) + { + *L1 = L1_I1; + } + + if (levels) + { + *levels = k; + } + + return I1; +} + template void tanh_sinh_detail::init(const Real& min_complement, const std::integral_constant&) { @@ -565,10 +949,10 @@ void tanh_sinh_detail::init(const Real& min_complement, const std: using std::asinh; using std::atanh; using std::ceil; - using boost::math::constants::half_pi; - using boost::math::constants::pi; - using boost::math::constants::two_div_pi; - using boost::math::lltrunc; + using BOOST_MATH_NAMESPACE::constants::half_pi; + using BOOST_MATH_NAMESPACE::constants::pi; + using BOOST_MATH_NAMESPACE::constants::two_div_pi; + using BOOST_MATH_NAMESPACE::lltrunc; m_committed_refinements = 4; // @@ -669,7 +1053,7 @@ void tanh_sinh_detail::init(const Real& min_complement, const std: 1, 0, 1, 1, 3, 5, 11, 22, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_abscissas.size() - 1); + m_committed_refinements = static_cast(m_abscissas.size() - 1); #else m_committed_refinements = m_abscissas.size() - 1; #endif @@ -722,7 +1106,7 @@ void tanh_sinh_detail::init(const Real& min_complement, const std: 1, 0, 1, 1, 3, 5, 11, 22, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_abscissas.size() - 1); + m_committed_refinements = static_cast(m_abscissas.size() - 1); #else m_committed_refinements = m_abscissas.size() - 1; #endif @@ -774,7 +1158,7 @@ void tanh_sinh_detail::init(const Real& min_complement, const std: 1, 0, 1, 1, 3, 5, 11, 22, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_abscissas.size() - 1); + m_committed_refinements = static_cast(m_abscissas.size() - 1); #else m_committed_refinements = m_abscissas.size() - 1; #endif @@ -828,7 +1212,7 @@ void tanh_sinh_detail::init(const Real& min_complement, const std: 1, 0, 1, 1, 3, 5, 11, 22, }; #if !defined(BOOST_MATH_NO_ATOMIC_INT) && defined(BOOST_MATH_HAS_THREADS) - m_committed_refinements = static_cast(m_abscissas.size() - 1); + m_committed_refinements = static_cast(m_abscissas.size() - 1); #else m_committed_refinements = m_abscissas.size() - 1; #endif @@ -874,6 +1258,6 @@ void tanh_sinh_detail::prune_to_min_complement(const Real& m) } } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/quadrature/detail/van_den_bos_unit_square_tables.hpp b/include/boost/math/quadrature/detail/van_den_bos_unit_square_tables.hpp new file mode 100644 index 0000000000..e7bb7ed983 --- /dev/null +++ b/include/boost/math/quadrature/detail/van_den_bos_unit_square_tables.hpp @@ -0,0 +1,1002 @@ +/* + * Copyright 2026 Nicholas Thompson and Matt Borland + * Distributed under the Boost Software License, Version 1.0. + * + * Generated by tools/dump_van_den_bos_unit_square.cpp. + * + * The Fejer type-II candidates, moment matrices, support reductions, nodes, + * and weights were all computed in cpp_bin_float_quad. Nodes and weights + * were rounded once, at emission, to double. + * + * Every hexadecimal floating-point literal exactly represents its intended + * double value. C++17 or later is therefore required. + */ +#ifndef BOOST_MATH_QUADRATURE_DETAIL_VAN_DEN_BOS_UNIT_SQUARE_TABLES_HPP +#define BOOST_MATH_QUADRATURE_DETAIL_VAN_DEN_BOS_UNIT_SQUARE_TABLES_HPP + +#include +#include +#include + +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail { + +inline constexpr std::array van_den_bos_unit_square_level_0_weights{{ + 0x1.1e1e7d23aeec2p-6, + 0x1.d49a81c26d5b7p-6, + 0x1.400e6541d1775p-5, + 0x1.46951b4b2064ep-4 +}}; + +inline constexpr std::array van_den_bos_unit_square_level_1_weights{{ + 0x1.69002148d2cf6p-7, + 0x1.1ed018e44c70bp-6, + 0x1.8f11df5603f6p-6, + 0x1.23a0c0bedb829p-5, + 0x1.0373cc41eb249p-7, + 0x1.f64b4772a30cfp-7, + 0x1.3d0f08f1196d6p-5, + 0x1.07cedd3f10351p-6, + 0x1.6f0fa08500ffap-6, + 0x1.0c3ca688946cp-5 +}}; + +inline constexpr std::array van_den_bos_unit_square_level_2_weights{{ + 0x1.2299882630bccp-9, + 0x1.80d5cd0e7b9cdp-9, + 0x1.74fc8eb3dfe81p-8, + 0x1.0c36def1f5c08p-7, + 0x1.2bd4c7abd67f8p-10, + 0x1.19a70b9504b4cp-8, + 0x1.edf034b34926ep-8, + 0x1.a1f0a95e5eb6ep-9, + 0x1.95127cc2fc5d8p-8, + 0x1.2349806163773p-7, + 0x1.dbff34ee5f1d2p-11, + 0x1.86b8b719a2129p-8, + 0x1.d8911a7f4cb7p-10, + 0x1.6182579f7a9dep-8, + 0x1.4da18269b6fdap-6, + 0x1.49e5dfc336f95p-8, + 0x1.1cb152472072ep-7, + 0x1.0ddd944dc59e2p-6, + 0x1.54a98555b6bb7p-6, + 0x1.9f571db6559c3p-7, + 0x1.daab797196221p-8, + 0x1.3affb5d1440f7p-8 +}}; + +inline constexpr std::array van_den_bos_unit_square_level_3_weights{{ + 0x1.3b2f7e163bf2dp-11, + 0x1.9e95930d0e90ap-11, + 0x1.8872586d22285p-10, + 0x1.17d63c8e7b686p-9, + 0x1.4cf702ff05833p-12, + 0x1.2a5b02ede20f7p-10, + 0x1.021b00555f46bp-9, + 0x1.c17d9264d4cbfp-11, + 0x1.a97d2fa8d760cp-10, + 0x1.2f65df65556e4p-9, + 0x1.42ddd7aa91c2ep-13, + 0x1.eb6c15b70043ep-12, + 0x1.31a05d28f39c3p-12, + 0x1.74359ae267f3ep-11, + 0x1.6055a063b864p-10, + 0x1.9202b47671af1p-12, + 0x1.b8ade28915b7dp-11, + 0x1.a125f24a69aefp-10, + 0x1.1259ed021f478p-9, + 0x1.239e9f93f5233p-9, + 0x1.4bb3795d438dbp-10, + 0x1.f6781bb057b05p-10, + 0x1.e615b8728e52bp-15, + 0x1.b7f9c8c81c22fp-10, + 0x1.745f57435d396p-10, + 0x1.9040d1d7f32aep-8, + 0x1.585ee4952e7ddp-9, + 0x1.027e72656d1c6p-9, + 0x1.2f03db7389d85p-9, + 0x1.179ab7e2e699p-7, + 0x1.950be216ab805p-8, + 0x1.45f685edd108bp-7, + 0x1.e32a028b0f3c2p-8, + 0x1.8912ac53ae97dp-9, + 0x1.555c3f6996423p-9, + 0x1.ae8ba88236926p-7, + 0x1.e168a5c1fa9ap-9, + 0x1.0e1b330c7198ap-8, + 0x1.cf7395fc5ba37p-9, + 0x1.c3c6e14c2fecdp-8, + 0x1.aed12f888e63ap-7, + 0x1.239952bd42d8ep-7 +}}; + +inline constexpr std::array van_den_bos_unit_square_level_4_weights{{ + 0x1.3b2f7e163bf2dp-11, + 0x1.9e95930d0e90ap-11, + 0x1.8872586d22285p-10, + 0x1.17d63c8e7b686p-9, + 0x1.4cf702ff05833p-12, + 0x1.2a5b02ede20f7p-10, + 0x1.021b00555f46bp-9, + 0x1.c17d9264d4cbfp-11, + 0x1.a97d2fa8d760cp-10, + 0x1.2f65df65556e4p-9, + 0x1.42ddd7aa91c2ep-13, + 0x1.eb6c15b70043ep-12, + 0x1.31a05d28f39c3p-12, + 0x1.74359ae267f3ep-11, + 0x1.6055a063b864p-10, + 0x1.9202b47671af1p-12, + 0x1.b8ade28915b7dp-11, + 0x1.a125f24a69aefp-10, + 0x1.1259ed021f478p-9, + 0x1.239e9f93f5233p-9, + 0x1.4bb3795d438dbp-10, + 0x1.f6781bb057b05p-10, + 0x1.9b3a35dc8de8ap-15, + 0x1.1c231055a41f7p-12, + 0x1.38f4d16473479p-13, + 0x1.bace806bdf289p-11, + 0x1.0cf7018d11f89p-11, + 0x1.5831ab7f821afp-10, + 0x1.3da05da777e53p-11, + 0x1.f793940f57b02p-11, + 0x1.967756a854b7cp-10, + 0x1.7591f6130b06ep-10, + 0x1.017852f30b967p-9, + 0x1.1d48f62352cdep-12, + 0x1.7e472aa25e09cp-11, + 0x1.e93360ece2531p-10, + 0x1.2871ec786a09p-9, + 0x1.d182f9f3e0287p-11, + 0x1.3ae782a24dd78p-10, + 0x1.a3759864a80d2p-10, + 0x1.2118f7132dcbp-9, + 0x1.340d6e3c426d9p-9, + 0x1.3e9885c0e9189p-12, + 0x1.16d0f109b6016p-12, + 0x1.0c3487fdcbfa5p-11, + 0x1.92fa2ba707287p-11, + 0x1.55d25b37a967fp-10, + 0x1.ee547c28f66b4p-12, + 0x1.9cc6607f1154fp-9, + 0x1.78b7892d7e619p-9, + 0x1.bc6462d19c112p-10, + 0x1.adff1a69c99a5p-9, + 0x1.2612808ced54ap-8, + 0x1.4bb96392deecbp-11, + 0x1.d7e9ad85e4891p-10, + 0x1.a4d41d4870bddp-8, + 0x1.d764fbf562e7ap-10, + 0x1.2204c39ff3874p-8, + 0x1.161f6e7c9e3e4p-8, + 0x1.23154c95c315bp-10, + 0x1.b1d4eeee8183bp-9, + 0x1.87acf6b1c3fe1p-9, + 0x1.0661e5badc918p-8, + 0x1.1e476618ab836p-8, + 0x1.7bb73ce6d3f6dp-10, + 0x1.0812012b809ap-8, + 0x1.36f9430c542d1p-8, + 0x1.ca775e834d3a7p-11, + 0x1.3f0b7773464afp-10, + 0x1.124c85aecf895p-9, + 0x1.bd118b0162927p-8, + 0x1.c747515ddd963p-10, + 0x1.6901c022f0874p-8, + 0x1.d0bc1e6d9b191p-11, + 0x1.4f847f50fb82ep-10, + 0x1.143cf4ba58b1ep-8, + 0x1.647f9f53728ep-8, + 0x1.90a35ba801eaap-10 +}}; + +inline constexpr std::array van_den_bos_unit_square_level_5_weights{{ + 0x1.484f30c5cb5c8p-13, + 0x1.ae63d29bba2c2p-13, + 0x1.9277f8a67868fp-12, + 0x1.1dc67c927536dp-11, + 0x1.5f15f8a0dd779p-14, + 0x1.3302ada5ba457p-12, + 0x1.07cdc0a4ce1eep-11, + 0x1.d23c73aeee3bep-13, + 0x1.b3fd45a51791bp-12, + 0x1.3593b12fc5ba9p-11, + 0x1.5cf86cc8c8caep-15, + 0x1.00f35dcc13ec9p-13, + 0x1.4654c6d900ee9p-14, + 0x1.82df791294b9fp-13, + 0x1.69c6585efff55p-12, + 0x1.abcbf35e1bf0dp-14, + 0x1.c93009adfdeep-13, + 0x1.ab87224c6ccfdp-12, + 0x1.183aa936ab82dp-11, + 0x1.29ad6211089fdp-11, + 0x1.5539e7be3fa69p-12, + 0x1.00e1630fbe3e3p-11, + 0x1.4b501460e5acfp-17, + 0x1.08154335a09eep-14, + 0x1.e7e5f9b5ec69dp-16, + 0x1.ae71210724b36p-13, + 0x1.ede6d25008ff1p-14, + 0x1.50081c76030f9p-12, + 0x1.2300729401c3ap-13, + 0x1.deee980aeacfbp-13, + 0x1.8bf90910048b8p-12, + 0x1.687e3ac52fd88p-12, + 0x1.f762b6ad5a74ep-12, + 0x1.a764c2e714e0ep-15, + 0x1.4f720901a100dp-13, + 0x1.c872c80baa823p-12, + 0x1.225db6735f25p-11, + 0x1.cff7f35b0c652p-13, + 0x1.1f2fc0359343cp-12, + 0x1.849e50de8e4d2p-12, + 0x1.0f54634223fc6p-11, + 0x1.2e17a51f3cfd1p-11, + 0x1.f570fd7e14f9fp-17, + 0x1.8d47ee84625fp-15, + 0x1.b002a3a158cf6p-15, + 0x1.b2a10cd2b2825p-14, + 0x1.828d179047edfp-14, + 0x1.17304b32141c3p-15, + 0x1.6c0b3652e16e1p-13, + 0x1.12fda11cc7589p-12, + 0x1.652dc1b1ad806p-14, + 0x1.bcda2d59362acp-13, + 0x1.6fcbd637e8f74p-12, + 0x1.85da88d15f897p-15, + 0x1.34df5b2ed59f4p-13, + 0x1.2c87c8133fa09p-12, + 0x1.57f179fdbdf9ap-12, + 0x1.c47cebb873ef4p-12, + 0x1.b8836c6acd4fap-12, + 0x1.bb458bcf24346p-14, + 0x1.bdf56ecffc816p-13, + 0x1.7588900317498p-12, + 0x1.eb6a9ed5fbf0dp-12, + 0x1.1158b27af3735p-11, + 0x1.1afd421c97eadp-12, + 0x1.7ef0524c8ad9fp-12, + 0x1.0b5d390b4d7efp-11, + 0x1.b87dfdabadf4cp-15, + 0x1.5cfe049dac57dp-13, + 0x1.53910d2535093p-12, + 0x1.dae1bee7c5b18p-12, + 0x1.26ac36e428a71p-11, + 0x1.3292abb60c3aap-11, + 0x1.cf6d49963104fp-14, + 0x1.2097118ecfa5dp-12, + 0x1.10a7ddac636f2p-11, + 0x1.281ce60d607efp-11, + 0x1.2f919cc8cb4e5p-11, + 0x1.8748500d34d79p-16, + 0x1.8a0be8888e96ep-12, + 0x1.25a3cb2246f88p-12, + 0x1.abfb3d7f5b8cbp-12, + 0x1.1b7217ca454ccp-13, + 0x1.279ab56efcb71p-11, + 0x1.845e09a9879aap-12, + 0x1.e236dfb714aap-10, + 0x1.f57a2baa1033ep-13, + 0x1.06eef1f273059p-10, + 0x1.e1e83dadb5eap-12, + 0x1.c9b06f4a71988p-12, + 0x1.445e27d9239cap-10, + 0x1.42d3bf42f2953p-10, + 0x1.91417c13b73c1p-10, + 0x1.4e86cc31f68c8p-12, + 0x1.f888bbc9e524ep-10, + 0x1.cbef889ae62d2p-10, + 0x1.0b723cb2fb1dfp-11, + 0x1.24b373f415f92p-10, + 0x1.568dc10ba0667p-12, + 0x1.3faf89d9cf28fp-10, + 0x1.8dc637c3ed23p-12, + 0x1.0cce8c6e6d1bbp-11, + 0x1.4ad46afb27518p-9, + 0x1.5c1976c1a4d69p-9, + 0x1.5584e2e4f0fbap-9, + 0x1.341aa3416ef31p-11, + 0x1.5ab23c77d4e62p-10, + 0x1.563fa985937cfp-11, + 0x1.8d138550bcf76p-10, + 0x1.04818f336453p-11, + 0x1.a05a110ae5e91p-9, + 0x1.ecc7450d8ee6ep-9, + 0x1.f386a0fd990a2p-9, + 0x1.62e5a24d08c38p-10, + 0x1.b3cbd69e090bfp-13, + 0x1.0cfe3439be58bp-8, + 0x1.7b6f8cb26da67p-8, + 0x1.65cea31f4416fp-10, + 0x1.05db9cdba3674p-10, + 0x1.aa615768666eap-10, + 0x1.9fa0f3516335dp-12, + 0x1.40d7ab0efc284p-11, + 0x1.654ac4e1292c7p-9, + 0x1.fde52524da192p-10, + 0x1.c817521a3c20dp-10, + 0x1.2c09665a21b3ap-9, + 0x1.35b0a08aa082fp-8, + 0x1.07b9697e37cacp-8, + 0x1.d624100c14221p-11, + 0x1.076a636da6566p-11, + 0x1.018a4b38ee3fdp-9, + 0x1.8ececfe841c28p-11, + 0x1.05e98fd9c470fp-9, + 0x1.3db66831f56bap-11, + 0x1.2bda719e92952p-10, + 0x1.d417d7c8d1567p-11, + 0x1.66bf8ca3101f9p-9, + 0x1.b3dc0fce8c4bfp-10, + 0x1.0df228bc29fb1p-9, + 0x1.c509759e7b08ep-13, + 0x1.4270d0dfbdae3p-10, + 0x1.85084483ec35fp-10, + 0x1.15b22dc97053ap-9, + 0x1.b210014f6841ap-9, + 0x1.737d993d20ce1p-10, + 0x1.7e45886120496p-9, + 0x1.4edd8fbb87b8dp-9, + 0x1.6e3f944f7313ep-12, + 0x1.dcda5d8a691f2p-13, + 0x1.ac62047fad70ep-11 +}}; + +inline constexpr std::array van_den_bos_unit_square_level_6_weights{{ + 0x1.484f30c5cb5c8p-13, + 0x1.ae63d29bba2c2p-13, + 0x1.9277f8a67868fp-12, + 0x1.1dc67c927536dp-11, + 0x1.5f15f8a0dd779p-14, + 0x1.3302ada5ba457p-12, + 0x1.07cdc0a4ce1eep-11, + 0x1.d23c73aeee3bep-13, + 0x1.b3fd45a51791bp-12, + 0x1.3593b12fc5ba9p-11, + 0x1.5cf86cc8c8caep-15, + 0x1.00f35dcc13ec9p-13, + 0x1.4654c6d900ee9p-14, + 0x1.82df791294b9fp-13, + 0x1.69c6585efff55p-12, + 0x1.abcbf35e1bf0dp-14, + 0x1.c93009adfdeep-13, + 0x1.ab87224c6ccfdp-12, + 0x1.183aa936ab82dp-11, + 0x1.29ad6211089fdp-11, + 0x1.5539e7be3fa69p-12, + 0x1.00e1630fbe3e3p-11, + 0x1.4b501460e5acfp-17, + 0x1.08154335a09eep-14, + 0x1.e7e5f9b5ec69dp-16, + 0x1.ae71210724b36p-13, + 0x1.ede6d25008ff1p-14, + 0x1.50081c76030f9p-12, + 0x1.2300729401c3ap-13, + 0x1.deee980aeacfbp-13, + 0x1.8bf90910048b8p-12, + 0x1.687e3ac52fd88p-12, + 0x1.f762b6ad5a74ep-12, + 0x1.a764c2e714e0ep-15, + 0x1.4f720901a100dp-13, + 0x1.c872c80baa823p-12, + 0x1.225db6735f25p-11, + 0x1.cff7f35b0c652p-13, + 0x1.1f2fc0359343cp-12, + 0x1.849e50de8e4d2p-12, + 0x1.0f54634223fc6p-11, + 0x1.2e17a51f3cfd1p-11, + 0x1.f570fd7e14f9fp-17, + 0x1.8d47ee84625fp-15, + 0x1.b002a3a158cf6p-15, + 0x1.b2a10cd2b2825p-14, + 0x1.828d179047edfp-14, + 0x1.17304b32141c3p-15, + 0x1.6c0b3652e16e1p-13, + 0x1.12fda11cc7589p-12, + 0x1.652dc1b1ad806p-14, + 0x1.bcda2d59362acp-13, + 0x1.6fcbd637e8f74p-12, + 0x1.85da88d15f897p-15, + 0x1.34df5b2ed59f4p-13, + 0x1.2c87c8133fa09p-12, + 0x1.57f179fdbdf9ap-12, + 0x1.c47cebb873ef4p-12, + 0x1.b8836c6acd4fap-12, + 0x1.bb458bcf24346p-14, + 0x1.bdf56ecffc816p-13, + 0x1.7588900317498p-12, + 0x1.eb6a9ed5fbf0dp-12, + 0x1.1158b27af3735p-11, + 0x1.1afd421c97eadp-12, + 0x1.7ef0524c8ad9fp-12, + 0x1.0b5d390b4d7efp-11, + 0x1.b87dfdabadf4cp-15, + 0x1.5cfe049dac57dp-13, + 0x1.53910d2535093p-12, + 0x1.dae1bee7c5b18p-12, + 0x1.26ac36e428a71p-11, + 0x1.3292abb60c3aap-11, + 0x1.cf6d49963104fp-14, + 0x1.2097118ecfa5dp-12, + 0x1.10a7ddac636f2p-11, + 0x1.281ce60d607efp-11, + 0x1.2f919cc8cb4e5p-11, + 0x1.9ddacef7d0f5ap-19, + 0x1.bb6bf199f31fdp-16, + 0x1.dc4a2a9577d4ep-15, + 0x1.7f5469c0013f9p-14, + 0x1.0dd1ddba22ccbp-16, + 0x1.46ec65d86bc81p-14, + 0x1.ea94eda298a27p-15, + 0x1.2d8ea146b9d7dp-13, + 0x1.0ec633871f8b5p-15, + 0x1.a17809079b403p-13, + 0x1.8ef0469d03512p-14, + 0x1.0d6fe435c02b9p-14, + 0x1.2a92a5c98f3fp-13, + 0x1.04b5681b53fe6p-12, + 0x1.966ecb923a8c1p-13, + 0x1.5f7a98778d2a8p-14, + 0x1.1f4167b01e65dp-12, + 0x1.4aab57470eba9p-12, + 0x1.4e4f67d864c23p-13, + 0x1.a5b9cfa1c9b98p-13, + 0x1.db726465a4a7ep-16, + 0x1.03be5dcd3a701p-13, + 0x1.371283e7f9a14p-12, + 0x1.81ae3190e4579p-12, + 0x1.0feeb9885a94cp-12, + 0x1.61a4d03f4c7d6p-12, + 0x1.a5f5f283d8fb8p-12, + 0x1.7c234ffd940c8p-13, + 0x1.2b0bd5b174997p-12, + 0x1.58becb76b48a5p-14, + 0x1.dde76711649cfp-12, + 0x1.abcba28ab5379p-14, + 0x1.ae63814ae5b4p-13, + 0x1.896c02a41ed3ep-12, + 0x1.b883193053ebcp-12, + 0x1.07cd8ecd4ffdbp-11, + 0x1.162aa360968eap-15, + 0x1.47ef156b35d86p-12, + 0x1.04bd92d8dc62ap-11, + 0x1.2e7f7fe1d029fp-13, + 0x1.c12a14800cb12p-12, + 0x1.1c93f647a0146p-11, + 0x1.b6237677b45cep-15, + 0x1.ad56fbbd93c8ep-13, + 0x1.1da6ec0f62e94p-12, + 0x1.a5d9f6976c59p-12, + 0x1.f7583e33b94cfp-12, + 0x1.2519254d9f687p-11, + 0x1.cc79592d36572p-12, + 0x1.183a7444b9025p-11, + 0x1.3f25f8e4aa956p-13, + 0x1.1417acb73cab6p-12, + 0x1.7e37575595946p-12, + 0x1.033b901d000b7p-11, + 0x1.32593c19683ebp-11, + 0x1.cd2c48ad1f6e3p-14, + 0x1.afa569556ddd6p-13, + 0x1.461f78878f1d5p-12, + 0x1.0dfd5bac91cbap-11, + 0x1.1c6276ace28a8p-11, + 0x1.28120df5bd3fcp-11, + 0x1.26e77423083dfp-15, + 0x1.16c024b4eb4bep-12, + 0x1.81e55ddb72059p-12, + 0x1.b23bd452c11eep-12, + 0x1.030f3b655be9fp-11, + 0x1.232b2e46f97d7p-11, + 0x1.38354f5913189p-11, + 0x1.39e2a8a4007c5p-11, + 0x1.876da9abb1c18p-14, + 0x1.5eb2aa3bc6ba6p-13, + 0x1.d59669d06dfafp-12, + 0x1.d3af3b7e8c24dp-16, + 0x1.ec2b598dce96fp-17, + 0x1.8575141456d5bp-16, + 0x1.d690ed3d1759dp-14, + 0x1.c037c16c90783p-14, + 0x1.c447db8c04f8ap-13, + 0x1.461a20ff6844cp-13, + 0x1.8a57a6df3ed7cp-15, + 0x1.6159ccab2f102p-13, + 0x1.1c86f710470f9p-13, + 0x1.e229a83aca59dp-12, + 0x1.9a00a4382be1bp-13, + 0x1.3f029081707bep-15, + 0x1.0ccc126d8fdadp-13, + 0x1.70508ff7e858cp-12, + 0x1.5986730ca89e4p-13, + 0x1.6aac17b7ff35p-12, + 0x1.a06f54722c6cbp-12, + 0x1.583aa7aa501d4p-12, + 0x1.a11a45808618p-11, + 0x1.b2b4d8f85c1ccp-12, + 0x1.665fbdac13544p-14, + 0x1.f8d0421ba6a7dp-14, + 0x1.2596fcba2eef8p-12, + 0x1.3d4e7dff8ecf4p-12, + 0x1.963b5fd93dc3dp-13, + 0x1.1e5f98421094ap-12, + 0x1.08c2f6eb14ea3p-12, + 0x1.0d38eac73f479p-10, + 0x1.2f4388289843ep-11, + 0x1.711840290162ap-14, + 0x1.352325e1c3197p-12, + 0x1.4815d19736f4cp-11, + 0x1.de21e705bdffdp-13, + 0x1.2e0f5db6749a3p-12, + 0x1.bba936d90e742p-11, + 0x1.285ee1a2c303bp-10, + 0x1.a947ad59c5e53p-14, + 0x1.7d8b937fddfbap-11, + 0x1.f56d00888379bp-12, + 0x1.275e230a4af83p-10, + 0x1.941b52a4ad7e1p-13, + 0x1.215f6ab98fc78p-14, + 0x1.50e42b4c4afdap-13, + 0x1.31d56feeea5e8p-11, + 0x1.e914824167b9p-11, + 0x1.c6b52330fba72p-12, + 0x1.348b7f9de889cp-10, + 0x1.d4406274d88b9p-15, + 0x1.c6aa2c4b7d53cp-13, + 0x1.67e629e30ea9dp-12, + 0x1.1109585ba0839p-11, + 0x1.a992bde0206c6p-10, + 0x1.fa0a75087b1b1p-12, + 0x1.44deda601f3cdp-11, + 0x1.3f496b894e14ep-11, + 0x1.c084d2967a0bcp-10, + 0x1.0f67146fe1df6p-9, + 0x1.1c378252512bfp-12, + 0x1.c779ab90ccd79p-12, + 0x1.8acfceb21ff1bp-10, + 0x1.b03c4565a2b99p-10, + 0x1.83cf8ca2b3a39p-14, + 0x1.2baf90a520d42p-11, + 0x1.5e3a105718172p-10, + 0x1.4dfa78c3bf61fp-14, + 0x1.0061fdd0cdb3ep-10, + 0x1.18a0e654c062ap-10, + 0x1.2d03e32d788c7p-10, + 0x1.3af5ccd4736f3p-13, + 0x1.aedd0eff44705p-12, + 0x1.290290e1f48bdp-13, + 0x1.c75ec02685fb9p-11, + 0x1.448e5a935635cp-11, + 0x1.a586809264fd9p-10, + 0x1.05b6d0094a572p-12, + 0x1.301fbbc3e4b4bp-13, + 0x1.9092b8926a2ecp-11, + 0x1.c71df812d7901p-11, + 0x1.8314fda58851cp-10, + 0x1.2b345cc22772ep-11, + 0x1.82bee2cf92f39p-10, + 0x1.1252a2659e9c8p-9, + 0x1.31e8dc2e98eacp-13, + 0x1.435b3d31a3c5cp-11, + 0x1.be21a463f01afp-11, + 0x1.398c402efc007p-10, + 0x1.1858813d7249dp-10, + 0x1.8c9f8f7b598bp-12, + 0x1.76f2af16a8449p-13, + 0x1.282bafa064cdp-10, + 0x1.66c070fa20cf5p-10, + 0x1.35795a64cf0c3p-10, + 0x1.b792b9995934fp-10, + 0x1.1695796d1d1b9p-9, + 0x1.9f4ec2edef861p-12, + 0x1.06f005e26a108p-11, + 0x1.cb4b4d1fef2c5p-12, + 0x1.ee283c28edc53p-11, + 0x1.e6ba283aca1e1p-10, + 0x1.e257035ccf93ap-11, + 0x1.ab88a2b149bd4p-13, + 0x1.01a2f678f5235p-13, + 0x1.b828b0209a241p-11, + 0x1.439677ac4e856p-15, + 0x1.ab716e97bbf75p-11, + 0x1.1905deec992bbp-11, + 0x1.eb838a3ec7053p-12, + 0x1.86e338fdb1befp-11, + 0x1.4c52cec65280ep-10, + 0x1.84eda56634b8ap-12, + 0x1.6b6ed18a04a55p-10, + 0x1.e08392f55b71ap-10, + 0x1.9116d526e70ffp-11, + 0x1.07ef174da63c5p-13, + 0x1.0e4ec9a412a5bp-10, + 0x1.449d46dbcdab7p-11, + 0x1.7a86eb12321efp-11, + 0x1.0409b2a889cd5p-10, + 0x1.b3d31edc2428fp-11, + 0x1.3f6420e66efb1p-12, + 0x1.698c1dd7a61a9p-14, + 0x1.1e1d6bccfd1d3p-13, + 0x1.133943462ea38p-12, + 0x1.42d010d9c1bc6p-11, + 0x1.5b678eb656e63p-11, + 0x1.ad56b86d77037p-11, + 0x1.5b20b7d289436p-10, + 0x1.a5d68d8bf00b2p-10, + 0x1.d5a05413d7594p-11, + 0x1.abab646894e4dp-11, + 0x1.480292f8ed57bp-10, + 0x1.d68603f00894bp-12, + 0x1.5e56c9adb4029p-15, + 0x1.26e12f2f5a824p-12, + 0x1.343958f876bd7p-14, + 0x1.5bb5ddd4b872p-12, + 0x1.94db661847ad8p-10, + 0x1.474ba9c31bbadp-11, + 0x1.686eb088e3552p-10, + 0x1.1aa14cddde99p-12, + 0x1.ecea2c3316db3p-11, + 0x1.2232f05cd1be9p-11, + 0x1.396a02bdf877ep-11 +}}; + +inline constexpr std::array van_den_bos_unit_square_coordinates{{ + 0x1.2bec333018867p-3, + 0x1.37ca1866b95cfp-5, + 0x1.3c10eaca8ab4fp-2, + 0x1p-1, + 0x1.3ad06011469fbp-7, + 0x1.592675bc57974p-4, + 0x1.c71898ca32e6fp-3, + 0x1.9c1d1f0e5967dp-2, + 0x1.3b92e176d6d31p-9, + 0x1.60bea939d225ap-6, + 0x1.d0dfe53aba2fdp-4, + 0x1.76619b5edc454p-3, + 0x1.e3a6873fa1279p-5, + 0x1.0ea5163fc84e2p-2, + 0x1.6b5fce895307dp-2, + 0x1.cdd0b287ac97bp-2, + 0x1.3bc390d250439p-11, + 0x1.62aa03dd6ba58p-8, + 0x1.eb0208db9e51bp-7, + 0x1.894285e19c468p-5, + 0x1.dedefb09791b4p-6, + 0x1.235f2eb9a470ap-4, + 0x1.9307ee031e2fdp-4, + 0x1.09441bb2aa0a2p-3, + 0x1.5052d96e626c1p-3, + 0x1.9e010063d1f96p-3, + 0x1.f18f0cdba0025p-3, + 0x1.25177fb0f51ap-2, + 0x1.53832c52a7012p-2, + 0x1.83981a137a839p-2, + 0x1.b4dfbe45c67b1p-2, + 0x1.e6e09a0ef227fp-2 +}}; + +inline constexpr std::array, 294> van_den_bos_unit_square_node_indices{{ + {{0, 1}}, + {{2, 1}}, + {{2, 0}}, + {{3, 2}}, + {{1, 1}}, + {{0, 0}}, + {{2, 2}}, + {{3, 1}}, + {{3, 0}}, + {{3, 3}}, + {{1, 4}}, + {{5, 1}}, + {{0, 4}}, + {{6, 1}}, + {{6, 0}}, + {{2, 4}}, + {{7, 1}}, + {{7, 0}}, + {{7, 2}}, + {{7, 7}}, + {{3, 5}}, + {{3, 6}}, + {{4, 8}}, + {{1, 9}}, + {{5, 8}}, + {{10, 5}}, + {{0, 9}}, + {{11, 0}}, + {{6, 9}}, + {{6, 12}}, + {{6, 11}}, + {{2, 10}}, + {{2, 13}}, + {{14, 8}}, + {{14, 9}}, + {{14, 11}}, + {{7, 14}}, + {{15, 1}}, + {{15, 12}}, + {{15, 10}}, + {{15, 13}}, + {{15, 7}}, + {{9, 8}}, + {{9, 9}}, + {{12, 4}}, + {{12, 1}}, + {{5, 9}}, + {{10, 8}}, + {{10, 12}}, + {{0, 10}}, + {{11, 4}}, + {{11, 12}}, + {{11, 11}}, + {{13, 8}}, + {{13, 9}}, + {{13, 5}}, + {{13, 10}}, + {{13, 6}}, + {{2, 11}}, + {{14, 4}}, + {{14, 1}}, + {{14, 10}}, + {{14, 6}}, + {{14, 2}}, + {{7, 12}}, + {{7, 10}}, + {{7, 13}}, + {{15, 8}}, + {{15, 9}}, + {{15, 5}}, + {{15, 11}}, + {{15, 14}}, + {{15, 15}}, + {{3, 4}}, + {{3, 12}}, + {{3, 13}}, + {{3, 14}}, + {{3, 7}}, + {{8, 16}}, + {{9, 17}}, + {{1, 18}}, + {{19, 20}}, + {{12, 16}}, + {{12, 9}}, + {{21, 4}}, + {{5, 19}}, + {{22, 8}}, + {{22, 5}}, + {{10, 18}}, + {{23, 17}}, + {{23, 20}}, + {{23, 22}}, + {{0, 12}}, + {{24, 4}}, + {{24, 22}}, + {{24, 0}}, + {{11, 20}}, + {{11, 19}}, + {{25, 16}}, + {{25, 18}}, + {{25, 22}}, + {{25, 24}}, + {{6, 21}}, + {{6, 23}}, + {{6, 25}}, + {{26, 20}}, + {{26, 5}}, + {{13, 17}}, + {{13, 26}}, + {{27, 4}}, + {{27, 1}}, + {{27, 23}}, + {{27, 11}}, + {{2, 27}}, + {{28, 16}}, + {{28, 5}}, + {{28, 26}}, + {{14, 18}}, + {{14, 24}}, + {{14, 28}}, + {{29, 8}}, + {{29, 20}}, + {{29, 12}}, + {{29, 23}}, + {{29, 25}}, + {{29, 14}}, + {{7, 24}}, + {{7, 27}}, + {{30, 18}}, + {{30, 19}}, + {{30, 22}}, + {{30, 6}}, + {{30, 7}}, + {{15, 4}}, + {{15, 20}}, + {{15, 21}}, + {{15, 26}}, + {{15, 27}}, + {{15, 28}}, + {{31, 16}}, + {{31, 19}}, + {{31, 22}}, + {{31, 23}}, + {{31, 25}}, + {{31, 2}}, + {{31, 29}}, + {{31, 15}}, + {{3, 17}}, + {{3, 9}}, + {{3, 24}}, + {{17, 8}}, + {{4, 16}}, + {{18, 8}}, + {{18, 4}}, + {{20, 8}}, + {{20, 18}}, + {{1, 20}}, + {{19, 16}}, + {{19, 4}}, + {{12, 17}}, + {{12, 20}}, + {{12, 19}}, + {{21, 16}}, + {{21, 1}}, + {{21, 12}}, + {{5, 17}}, + {{5, 18}}, + {{5, 21}}, + {{22, 9}}, + {{22, 19}}, + {{22, 22}}, + {{10, 16}}, + {{10, 17}}, + {{10, 20}}, + {{10, 21}}, + {{23, 4}}, + {{23, 9}}, + {{23, 19}}, + {{23, 5}}, + {{23, 10}}, + {{0, 8}}, + {{0, 20}}, + {{0, 19}}, + {{24, 17}}, + {{24, 18}}, + {{24, 21}}, + {{24, 23}}, + {{11, 16}}, + {{11, 1}}, + {{11, 5}}, + {{11, 10}}, + {{11, 24}}, + {{25, 8}}, + {{25, 4}}, + {{25, 9}}, + {{25, 21}}, + {{25, 0}}, + {{25, 25}}, + {{6, 16}}, + {{6, 18}}, + {{6, 19}}, + {{6, 10}}, + {{6, 24}}, + {{26, 17}}, + {{26, 1}}, + {{26, 12}}, + {{26, 22}}, + {{26, 26}}, + {{13, 18}}, + {{13, 1}}, + {{13, 0}}, + {{13, 25}}, + {{27, 8}}, + {{27, 9}}, + {{27, 12}}, + {{27, 5}}, + {{27, 10}}, + {{27, 24}}, + {{27, 13}}, + {{2, 16}}, + {{2, 18}}, + {{2, 20}}, + {{2, 21}}, + {{2, 22}}, + {{2, 25}}, + {{28, 17}}, + {{28, 18}}, + {{28, 1}}, + {{28, 21}}, + {{28, 23}}, + {{28, 11}}, + {{28, 6}}, + {{28, 27}}, + {{28, 28}}, + {{14, 20}}, + {{14, 5}}, + {{14, 0}}, + {{14, 26}}, + {{29, 17}}, + {{29, 4}}, + {{29, 19}}, + {{29, 22}}, + {{29, 24}}, + {{29, 13}}, + {{29, 28}}, + {{7, 18}}, + {{7, 21}}, + {{7, 22}}, + {{7, 11}}, + {{7, 6}}, + {{7, 28}}, + {{30, 16}}, + {{30, 17}}, + {{30, 9}}, + {{30, 20}}, + {{30, 12}}, + {{30, 5}}, + {{30, 10}}, + {{30, 23}}, + {{30, 11}}, + {{30, 26}}, + {{30, 27}}, + {{30, 29}}, + {{30, 30}}, + {{15, 19}}, + {{15, 23}}, + {{15, 0}}, + {{15, 6}}, + {{15, 2}}, + {{15, 29}}, + {{31, 17}}, + {{31, 4}}, + {{31, 18}}, + {{31, 20}}, + {{31, 1}}, + {{31, 21}}, + {{31, 0}}, + {{31, 11}}, + {{31, 26}}, + {{31, 27}}, + {{31, 14}}, + {{31, 30}}, + {{31, 31}}, + {{3, 8}}, + {{3, 18}}, + {{3, 19}}, + {{3, 21}}, + {{3, 22}}, + {{3, 25}}, + {{3, 28}}, + {{3, 29}}, + {{3, 30}}, + {{3, 15}}, + {{3, 31}} +}}; + +inline constexpr std::size_t van_den_bos_unit_square_level_count = 7; + +inline constexpr std::array van_den_bos_unit_square_weights{{ + van_den_bos_unit_square_level_0_weights.data(), + van_den_bos_unit_square_level_1_weights.data(), + van_den_bos_unit_square_level_2_weights.data(), + van_den_bos_unit_square_level_3_weights.data(), + van_den_bos_unit_square_level_4_weights.data(), + van_den_bos_unit_square_level_5_weights.data(), + van_den_bos_unit_square_level_6_weights.data() +}}; + +inline constexpr std::array van_den_bos_unit_square_sizes{{ + van_den_bos_unit_square_level_0_weights.size(), + van_den_bos_unit_square_level_1_weights.size(), + van_den_bos_unit_square_level_2_weights.size(), + van_den_bos_unit_square_level_3_weights.size(), + van_den_bos_unit_square_level_4_weights.size(), + van_den_bos_unit_square_level_5_weights.size(), + van_den_bos_unit_square_level_6_weights.size() +}}; + +}} BOOST_MATH_NAMESPACE_END + +#endif diff --git a/include/boost/math/quadrature/exp_sinh.hpp b/include/boost/math/quadrature/exp_sinh.hpp index d3148e0c0a..83e5908b56 100644 --- a/include/boost/math/quadrature/exp_sinh.hpp +++ b/include/boost/math/quadrature/exp_sinh.hpp @@ -20,14 +20,16 @@ #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif -namespace boost{ namespace math{ namespace quadrature { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { -template > +BOOST_MATH_EXPORT template > class exp_sinh { public: @@ -35,9 +37,14 @@ class exp_sinh : m_imp(std::make_shared>(max_refinements)) {} template - auto integrate(const F& f, Real a, Real b, Real tol = boost::math::tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(std::declval()(std::declval())); + auto integrate(const F& f, Real a, Real b, Real tol = BOOST_MATH_NAMESPACE::tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(std::declval()(std::declval())); template - auto integrate(const F& f, Real tol = boost::math::tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(std::declval()(std::declval())); + auto integrate(const F& f, Real tol = BOOST_MATH_NAMESPACE::tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(std::declval()(std::declval())); + + template + auto integrate(const F& f, Real a, Real b, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance = tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(static_cast(norm(std::declval()(std::declval()))), std::declval()(std::declval())); + template + auto integrate(const F& f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance = tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(static_cast(norm(std::declval()(std::declval()))), std::declval()(std::declval())); private: std::shared_ptr> m_imp; @@ -51,18 +58,18 @@ auto exp_sinh::integrate(const F& f, Real a, Real b, Real toleranc static_assert(!std::is_integral::value, "The return type cannot be integral, it must be either a real or complex floating point type."); using std::abs; - using boost::math::constants::half; - using boost::math::quadrature::detail::exp_sinh_detail; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::quadrature::detail::exp_sinh_detail; static const char* function = "boost::math::quadrature::exp_sinh<%1%>::integrate"; // Neither limit may be a NaN: - if((boost::math::isnan)(a) || (boost::math::isnan)(b)) + if((BOOST_MATH_NAMESPACE::isnan)(a) || (BOOST_MATH_NAMESPACE::isnan)(b)) { return static_cast(policies::raise_domain_error(function, "NaN supplied as one limit of integration - sorry I don't know what to do", a, Policy())); } // Right limit is infinite: - if ((boost::math::isfinite)(a) && (b >= boost::math::tools::max_value())) + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (b >= BOOST_MATH_NAMESPACE::tools::max_value())) { // If a = 0, don't use an additional level of indirection: if (a == static_cast(0)) @@ -73,14 +80,14 @@ auto exp_sinh::integrate(const F& f, Real a, Real b, Real toleranc return m_imp->integrate(u, error, L1, function, tolerance, levels); } - if ((boost::math::isfinite)(b) && a <= -boost::math::tools::max_value()) + if ((BOOST_MATH_NAMESPACE::isfinite)(b) && a <= -BOOST_MATH_NAMESPACE::tools::max_value()) { const auto u = [&](Real t)->K { return f(b-t);}; return m_imp->integrate(u, error, L1, function, tolerance, levels); } // Infinite limits: - if ((a <= -boost::math::tools::max_value()) && (b >= boost::math::tools::max_value())) + if ((a <= -BOOST_MATH_NAMESPACE::tools::max_value()) && (b >= BOOST_MATH_NAMESPACE::tools::max_value())) { return static_cast(policies::raise_domain_error(function, "Use sinh_sinh quadrature for integration over the whole real line; exp_sinh is for half infinite integrals.", a, Policy())); } @@ -101,7 +108,64 @@ auto exp_sinh::integrate(const F& f, Real tolerance, Real* error, } -}}} +template +template +auto exp_sinh::integrate(const F& f, Real a, Real b, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(static_cast(norm(std::declval()(std::declval()))), std::declval()(std::declval())) +{ + typedef decltype(f(a)) K; + static_assert(!std::is_integral::value, + "The return type cannot be integral, it must be either a real or complex floating point type."); + using std::abs; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::quadrature::detail::exp_sinh_detail; + + static const char* function = "boost::math::quadrature::exp_sinh<%1%>::integrate"; + + // Neither limit may be a NaN: + if((BOOST_MATH_NAMESPACE::isnan)(a) || (BOOST_MATH_NAMESPACE::isnan)(b)) + { + return detail::norm_quadrature_error(zero, policies::raise_domain_error(function, "NaN supplied as one limit of integration - sorry I don't know what to do", a, Policy()), error, L1, levels); + } + // Right limit is infinite: + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (b >= BOOST_MATH_NAMESPACE::tools::max_value())) + { + // If a = 0, don't use an additional level of indirection: + if (a == static_cast(0)) + { + return m_imp->integrate(f, zero, norm, error, L1, function, tolerance, levels); + } + const auto u = [&](Real t)->K { return f(t + a); }; + return m_imp->integrate(u, zero, norm, error, L1, function, tolerance, levels); + } + + if ((BOOST_MATH_NAMESPACE::isfinite)(b) && a <= -BOOST_MATH_NAMESPACE::tools::max_value()) + { + const auto u = [&](Real t)->K { return f(b-t);}; + return m_imp->integrate(u, zero, norm, error, L1, function, tolerance, levels); + } + + // Infinite limits: + if ((a <= -BOOST_MATH_NAMESPACE::tools::max_value()) && (b >= BOOST_MATH_NAMESPACE::tools::max_value())) + { + return detail::norm_quadrature_error(zero, policies::raise_domain_error(function, "Use sinh_sinh quadrature for integration over the whole real line; exp_sinh is for half infinite integrals.", a, Policy()), error, L1, levels); + } + // If we get to here then both ends must necessarily be finite: + return detail::norm_quadrature_error(zero, policies::raise_domain_error(function, "Use tanh_sinh quadrature for integration over finite domains; exp_sinh is for half infinite integrals.", a, Policy()), error, L1, levels); +} + +template +template +auto exp_sinh::integrate(const F& f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(static_cast(norm(std::declval()(std::declval()))), std::declval()(std::declval())) +{ + static const char* function = "boost::math::quadrature::exp_sinh<%1%>::integrate"; + using std::abs; + if (abs(tolerance) > 1) { + return detail::norm_quadrature_error(zero, policies::raise_domain_error(function, "The tolerance provided (%1%) is unusually large; did you confuse it with a domain bound?", tolerance, Policy()), error, L1, levels); + } + return m_imp->integrate(f, zero, norm, error, L1, function, tolerance, levels); +} + +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC @@ -113,28 +177,27 @@ auto exp_sinh::integrate(const F& f, Real tolerance, Real* error, #include #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { template > -__device__ auto exp_sinh_integrate(const F& f, Real a, Real b, Real tolerance, Real* error, Real* L1, boost::math::size_t* levels) +__device__ auto exp_sinh_integrate(const F& f, Real a, Real b, Real tolerance, Real* error, Real* L1, BOOST_MATH_NAMESPACE::size_t* levels) { BOOST_MATH_STD_USING using K = decltype(f(a)); - static_assert(!boost::math::is_integral::value, + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value, "The return type cannot be integral, it must be either a real or complex floating point type."); constexpr auto function = "boost::math::quadrature::exp_sinh<%1%>::integrate"; // Neither limit may be a NaN: - if((boost::math::isnan)(a) || (boost::math::isnan)(b)) + if((BOOST_MATH_NAMESPACE::isnan)(a) || (BOOST_MATH_NAMESPACE::isnan)(b)) { return static_cast(policies::raise_domain_error(function, "NaN supplied as one limit of integration - sorry I don't know what to do", a, Policy())); } // Right limit is infinite: - if ((boost::math::isfinite)(a) && (b >= boost::math::tools::max_value())) + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (b >= BOOST_MATH_NAMESPACE::tools::max_value())) { // If a = 0, don't use an additional level of indirection: if (a == static_cast(0)) @@ -145,14 +208,14 @@ __device__ auto exp_sinh_integrate(const F& f, Real a, Real b, Real tolerance, R return detail::exp_sinh_integrate_impl(u, tolerance, error, L1, levels); } - if ((boost::math::isfinite)(b) && a <= -boost::math::tools::max_value()) + if ((BOOST_MATH_NAMESPACE::isfinite)(b) && a <= -BOOST_MATH_NAMESPACE::tools::max_value()) { const auto u = [&](Real t)->K { return f(b-t);}; return detail::exp_sinh_integrate_impl(u, tolerance, error, L1, levels); } // Infinite limits: - if ((a <= -boost::math::tools::max_value()) && (b >= boost::math::tools::max_value())) + if ((a <= -BOOST_MATH_NAMESPACE::tools::max_value()) && (b >= BOOST_MATH_NAMESPACE::tools::max_value())) { return static_cast(policies::raise_domain_error(function, "Use sinh_sinh quadrature for integration over the whole real line; exp_sinh is for half infinite integrals.", a, Policy())); } @@ -161,7 +224,7 @@ __device__ auto exp_sinh_integrate(const F& f, Real a, Real b, Real tolerance, R } template > -__device__ auto exp_sinh_integrate(const F& f, Real tolerance, Real* error, Real* L1, boost::math::size_t* levels) +__device__ auto exp_sinh_integrate(const F& f, Real tolerance, Real* error, Real* L1, BOOST_MATH_NAMESPACE::size_t* levels) { BOOST_MATH_STD_USING constexpr auto function = "boost::math::quadrature::exp_sinh<%1%>::integrate"; @@ -172,8 +235,7 @@ __device__ auto exp_sinh_integrate(const F& f, Real tolerance, Real* error, Real } } // namespace quadrature -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ENABLE_CUDA diff --git a/include/boost/math/quadrature/gauss.hpp b/include/boost/math/quadrature/gauss.hpp index 91ffcf0bcd..6d12cfdc75 100644 --- a/include/boost/math/quadrature/gauss.hpp +++ b/include/boost/math/quadrature/gauss.hpp @@ -10,57 +10,20 @@ #pragma once #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include +#include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4127) #endif -namespace boost { namespace math{ namespace quadrature{ namespace detail{ - -template -struct gauss_constant_category -{ - static const unsigned value = - (std::numeric_limits::is_specialized == 0) ? 999 : - (std::numeric_limits::radix == 2) ? - ( -#ifdef BOOST_HAS_FLOAT128 - (std::numeric_limits::digits <= 113) && std::is_constructible::value ? 0 : -#else - (std::numeric_limits::digits <= std::numeric_limits::digits) && std::is_constructible::value ? 0 : -#endif - (std::numeric_limits::digits10 <= 110) && std::is_constructible::value ? 4 : 999 - ) : (std::numeric_limits::digits10 <= 110) && std::is_constructible::value ? 4 : 999; - - using storage_type = - std::conditional_t<(std::numeric_limits::is_specialized == 0), T, - std::conditional_t<(std::numeric_limits::radix == 2), - std::conditional_t< ((std::numeric_limits::digits <= std::numeric_limits::digits) && std::is_constructible::value), - float, - std::conditional_t<((std::numeric_limits::digits <= std::numeric_limits::digits) && std::is_constructible::value), - double, - std::conditional_t<((std::numeric_limits::digits <= std::numeric_limits::digits) && std::is_constructible::value), - long double, -#ifdef BOOST_HAS_FLOAT128 - std::conditional_t<((std::numeric_limits::digits <= 113) && std::is_constructible::value), - __float128, - T - > - > -#else - T - > -#endif - > - >, T - > - >; -}; +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature{ namespace detail { #ifndef BOOST_MATH_GAUSS_NO_COMPUTE_ON_DEMAND @@ -73,7 +36,7 @@ class gauss_detail for (unsigned i = 0; i < abscissa().size(); ++i) { Real x = abscissa()[i]; - Real p = boost::math::legendre_p_prime(N, x); + Real p = BOOST_MATH_NAMESPACE::legendre_p_prime(N, x); result[i] = 2 / ((1 - x * x) * p * p); } return result; @@ -81,7 +44,7 @@ class gauss_detail public: static const std::vector& abscissa() { - static std::vector data = boost::math::legendre_p_zeros(N); + static std::vector data = BOOST_MATH_NAMESPACE::legendre_p_zeros(N); return data; } static const std::vector& weights() @@ -101,7 +64,7 @@ class gauss_detail; template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -128,7 +91,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -181,7 +144,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -210,7 +173,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -268,7 +231,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -303,7 +266,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -373,7 +336,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -412,7 +375,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -490,7 +453,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -535,7 +498,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -626,7 +589,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -675,7 +638,7 @@ class gauss_detail template class gauss_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -771,10 +734,10 @@ class gauss_detail } -template > -class gauss : public detail::gauss_detail::value> +BOOST_MATH_EXPORT template > +class gauss : public detail::gauss_detail::value> { - typedef detail::gauss_detail::value> base; + typedef detail::gauss_detail::value> base; public: template @@ -812,7 +775,7 @@ class gauss : public detail::gauss_detail(); @@ -829,7 +792,7 @@ class gauss : public detail::gauss_detail= tools::max_value())) + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (b >= tools::max_value())) { auto u = [&](const Real& t)->K { @@ -846,7 +809,7 @@ class gauss : public detail::gauss_detail())) + if ((BOOST_MATH_NAMESPACE::isfinite)(b) && (a <= -tools::max_value())) { auto v = [&](const Real& t)->K { @@ -863,7 +826,7 @@ class gauss : public detail::gauss_detail(policies::raise_domain_error(function, "The domain of integration is not sensible; please check the bounds.", a, Policy())); } + + // Explicit zero and norm for vector- and matrix-valued integrands. + // The original overloads above retain their existing behavior. + template + static auto integrate(F f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real* pL1 = nullptr) + ->decltype(static_cast(norm(f(Real(0)))), f(Real(0))) + { + typedef decltype(f(Real(0))) K; + static_assert(!std::is_integral::value, + "The return type cannot be integral."); + unsigned non_zero_start = 1; + K result = zero; + if (N & 1) { + result = f(Real(0)) * static_cast(base::weights()[0]); + } + else { + result = zero; + non_zero_start = 0; + } + Real L1 = static_cast(norm(result)); + for (unsigned i = non_zero_start; i < base::abscissa().size(); ++i) + { + K fp = f(static_cast(base::abscissa()[i])); + K fm = f(static_cast(-base::abscissa()[i])); + result += (fp + fm) * static_cast(base::weights()[i]); + L1 += (static_cast(norm(fp)) + static_cast(norm(fm))) * static_cast(base::weights()[i]); + } + if (pL1) + *pL1 = L1; + return result; + } + template + static auto integrate(F f, Real a, Real b, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real* pL1 = nullptr) + ->decltype(static_cast(norm(f(Real(0)))), f(Real(0))) + { + typedef decltype(f(a)) K; + static const char* function = "boost::math::quadrature::gauss<%1%>::integrate(f, %1%, %1%)"; + if (!(BOOST_MATH_NAMESPACE::isnan)(a) && !(BOOST_MATH_NAMESPACE::isnan)(b)) + { + // Infinite limits: + Real min_inf = -tools::max_value(); + if ((a <= min_inf) && (b >= tools::max_value())) + { + auto u = [&](const Real& t)->K + { + Real t_sq = t*t; + Real inv = 1 / (1 - t_sq); + K res = f(t*inv)*(1 + t_sq)*inv*inv; + return res; + }; + return integrate(u, zero, norm, pL1); + } + + // Right limit is infinite: + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (b >= tools::max_value())) + { + auto u = [&](const Real& t)->K + { + Real z = 1 / (t + 1); + Real arg = 2 * z + a - 1; + K res = f(arg)*z*z; + return res; + }; + K Q = Real(2) * integrate(u, zero, norm, pL1); + if (pL1) + { + *pL1 *= 2; + } + return Q; + } + + if ((BOOST_MATH_NAMESPACE::isfinite)(b) && (a <= -tools::max_value())) + { + auto v = [&](const Real& t)->K + { + Real z = 1 / (t + 1); + Real arg = 2 * z - 1; + K res = f(b - arg) * z * z; + return res; + }; + K Q = Real(2) * integrate(v, zero, norm, pL1); + if (pL1) + { + *pL1 *= 2; + } + return Q; + } + + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (BOOST_MATH_NAMESPACE::isfinite)(b)) + { + if (a == b) + { + if (pL1) + *pL1 = Real(0); + return zero; + } + if (b < a) + { + return -integrate(f, b, a, zero, norm, pL1); + } + Real avg = (a + b)*constants::half(); + Real scale = (b - a)*constants::half(); + + auto u = [&](Real z)->K + { + return f(avg + scale*z); + }; + K Q = scale*integrate(u, zero, norm, pL1); + + if (pL1) + { + *pL1 *= scale; + } + return Q; + } + } + // Preserve the scalar error policy, including non-throwing policies, + // and use scalar multiplication to produce a result with the right shape. + Real error = policies::raise_domain_error(function, "The domain of integration is not sensible; please check the bounds.", a, Policy()); + if (pL1) + *pL1 = error; + K result = zero * error; + return result; + } }; } // namespace quadrature -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/quadrature/gauss_hermite.hpp b/include/boost/math/quadrature/gauss_hermite.hpp new file mode 100644 index 0000000000..ec2d7ef2f4 --- /dev/null +++ b/include/boost/math/quadrature/gauss_hermite.hpp @@ -0,0 +1,618 @@ +// Copyright Jacob Hass 2026. +// Copyright Nick Thompson 2026. +// 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) + +#ifndef BOOST_MATH_QUADRATURE_GAUSS_HERMITE_HPP +#define BOOST_MATH_QUADRATURE_GAUSS_HERMITE_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include + +#ifdef BOOST_MATH_NO_CXX17_IF_CONSTEXPR +#error "The header requires C++17 or later." +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail { + +#ifndef BOOST_MATH_GAUSS_NO_COMPUTE_ON_DEMAND + +template +class gauss_hermite_detail +{ + static_assert(N > 0, "Gauss-Hermite quadrature needs at least one point."); + + // The nonnegative zeros of the Hermite polynomial H_N, in increasing order, and their weights. + // Everything is evaluated with the orthonormal recurrence + // p_0 = pi^(-1/4), p_{k+1} = x sqrt(2/(k+1)) p_k - sqrt(k/(k+1)) p_{k-1}, + // whose values stay representable long after H_N itself overflows. Then p_N' = sqrt(2N) p_{N-1}, + // p_N'' = 2x p_N' - 2N p_N, and the weight is 2/p_N'(x)^2. Evaluating H_N from its monomial + // coefficients instead would be hopelessly ill-conditioned: the largest zero of H_100 has + // condition number ~1e13. + // + // By Sturm's theorem for orthogonal polynomials, the number of sign changes in p_0(x), ..., p_N(x) + // is the number of zeros of p_N above x. Bisecting on that count isolates each zero, and Halley's + // method then converges to it inside its bracket. Asymptotic initial guesses alone are not enough: + // for N = 215, even Halley's method from those of Numerical Recipes' gauher finds the wrong zero. + struct recurrence + { + Real p; + Real p_prime; + unsigned zeros_above; + }; + + class orthonormal_hermite + { + public: + orthonormal_hermite() : a(N), b(N) + { + using std::sqrt; + for (unsigned k = 0; k < N; ++k) + { + a[k] = sqrt(Real(2) / Real(k + 1)); + b[k] = sqrt(Real(k) / Real(k + 1)); + } + p0 = 1 / sqrt(sqrt(BOOST_MATH_NAMESPACE::constants::pi())); + derivative_scale = sqrt(Real(2 * N)); + } + + recurrence operator()(const Real& x) const + { + Real p = p0; + Real p_previous = 0; + bool last_negative = false; + unsigned sign_changes = 0; + for (unsigned k = 0; k < N; ++k) + { + Real p_next = x * a[k] * p - b[k] * p_previous; + p_previous = p; + p = p_next; + // A zero p_k(x) lies between values of opposite sign, so skipping it keeps the count right. + if ((p != 0) && ((p < 0) != last_negative)) + { + ++sign_changes; + last_negative = !last_negative; + } + } + return recurrence{ p, derivative_scale * p_previous, sign_changes }; + } + + private: + std::vector a; + std::vector b; + Real p0; + Real derivative_scale; + }; + + // The weight is 2/p_N'(x)^2 at the exact zero, but d(log w)/dx is about -4x, so evaluating it at + // the rounded zero z costs far more accuracy than the rounding itself. Use p'' to move p' to the + // exact zero, which lies a Newton step delta = -p/p' away. + static Real weight(const Real& z, const recurrence& r) + { + Real delta = -r.p / r.p_prime; + Real p_prime = r.p_prime + (2 * z * r.p_prime - 2 * Real(N) * r.p) * delta; + return 2 / (p_prime * p_prime); + } + + static std::pair, std::vector > calculate_values() + { + using std::abs; + using std::sqrt; + const unsigned positive_zeros = N / 2; + const unsigned offset = N & 1; + std::vector x(positive_zeros + offset), w(positive_zeros + offset); + const orthonormal_hermite evaluate; + // All zeros lie below sqrt(2N + 1), so none lie above `upper`. Every p_k grows with x beyond + // its zeros, so if the recurrence overflows anywhere we need it, it overflows here: report + // that with NaNs, which gauss_hermite turns into an evaluation error. + Real upper = sqrt(Real(2 * N + 2)); + recurrence top = evaluate(upper); + if (!(BOOST_MATH_NAMESPACE::isfinite)(top.p) || !(BOOST_MATH_NAMESPACE::isfinite)(top.p_prime)) + { + std::fill(x.begin(), x.end(), std::numeric_limits::quiet_NaN()); + std::fill(w.begin(), w.end(), std::numeric_limits::quiet_NaN()); + return std::make_pair(x, w); + } + if (offset) + { + w[0] = weight(Real(0), evaluate(Real(0))); + } + // Find the zeros from the largest down: after each one, `upper` is a point with exactly t - 1 + // zeros above it. + for (unsigned t = 1; t <= positive_zeros; ++t) + { + Real lower = 0; + Real high = upper; + for (int i = 0; i < tools::digits(); ++i) + { + Real mid = (lower + high) / 2; + unsigned above = evaluate(mid).zeros_above; + if (above >= t) + lower = mid; + else + high = mid; + if (above == t) + break; + } + // Halley's method, falling back to bisection whenever a step would leave the bracket. + // With u = p/p' and v = p''/p' = 2z - 2N u, the step is u/(1 - uv/2); the ratios cannot + // overflow even where p'^2 would. + const bool lower_negative = evaluate(lower).p < 0; + Real z = (lower + high) / 2; + recurrence r = evaluate(z); + for (int i = 0; (r.p != 0) && (i < 4 * tools::digits()); ++i) + { + if ((r.p < 0) == lower_negative) + lower = z; + else + high = z; + Real u = r.p / r.p_prime; + Real v = 2 * z - 2 * Real(N) * u; + Real next = z - u / (1 - u * v / 2); + if (!((next > lower) && (next < high))) + next = (lower + high) / 2; + const bool converged = abs(next - z) <= 2 * tools::epsilon() * abs(next); + z = next; + r = evaluate(z); + if (converged) + break; + } + x[positive_zeros + offset - t] = z; + w[positive_zeros + offset - t] = weight(z, r); + upper = lower; + } + // Every node runs through the same rounded coefficients a and b, so the weights share a relative error + // of a few eps that grows with N (against 50 digits: -5 eps at N = 200, -10 at 500); exact coefficients + // remove it only with the recurrence in twice the precision. The exact weights sum to sqrt(pi), the + // integral of exp(-x^2), so scale them to that: weights with relative errors e_i then have e_i - e, e + // their weighted mean, plus two roundings. That removes the shared part, which is what integrals of + // smooth functions see, and moves no weight by more than |e| <= max |e_i|; measured, both the largest and + // the mean |e_i| fall for N = 200, 500 and 706. Sum from the smallest weight, with Neumaier's compensation: + BOOST_MATH_NAMESPACE::detail::compensated_sum sum; + for (std::size_t i = w.size(); i-- > 0;) + { + sum.add((offset && (i == 0)) ? w[i] : Real(2 * w[i])); + } + const Real scale = BOOST_MATH_NAMESPACE::constants::root_pi() / sum.value(); + for (Real& weight_i : w) + { + weight_i *= scale; + } + return std::make_pair(x, w); + } + + static const std::pair, std::vector >& values() + { + static const std::pair, std::vector > data = calculate_values(); + return data; + } + +public: + static const std::vector& abscissa() + { + return values().first; + } + static const std::vector& weights() + { + return values().second; + } +}; + +#else + +template +class gauss_hermite_detail; + +#endif + +#ifndef BOOST_HAS_FLOAT128 +template +class gauss_hermite_detail +{ + using storage_type = typename quadrature_constant_category::storage_type; + public: + static std::array const & abscissa() + { + static std::array data = { + static_cast(0.00000000000000000000000000000000000e+00L), + static_cast(8.16287882858964663038710959027145817e-01L), + static_cast(1.67355162876747144503180139830359482e+00L), + static_cast(2.65196135683523349244708200651661611e+00L), + }; + return data; + } + static std::array const & weights() + { + static std::array data = { + static_cast(8.10264617556807326764876563813094941e-01L), + static_cast(4.25607252610127800520317466666391035e-01L), + static_cast(5.45155828191270305921785688416951260e-02L), + static_cast(9.71781245099519154149424255938959644e-04L), + }; + return data; + } + }; + +#else +template +class gauss_hermite_detail +{ + using storage_type = typename quadrature_constant_category::storage_type; + public: + static std::array const & abscissa() + { + static std::array data = { + static_cast(0.00000000000000000000000000000000000e+00Q), + static_cast(8.16287882858964663038710959027145817e-01Q), + static_cast(1.67355162876747144503180139830359482e+00Q), + static_cast(2.65196135683523349244708200651661611e+00Q), + }; + return data; + } + static std::array const & weights() + { + static std::array data = { + static_cast(8.10264617556807326764876563813094941e-01Q), + static_cast(4.25607252610127800520317466666391035e-01Q), + static_cast(5.45155828191270305921785688416951260e-02Q), + static_cast(9.71781245099519154149424255938959644e-04Q), + }; + return data; + } + }; + +#endif +template +class gauss_hermite_detail +{ + using storage_type = typename quadrature_constant_category::storage_type; + public: + static std::array const & abscissa() + { + static std::array data = { + BOOST_MATH_HUGE_CONSTANT(T, 0, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 8.1628788285896466303871095902714581674288940037863615684472203343594907048766511668519794976704116666704491757953733e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.6735516287674714450318013983035948191078100577354089269242175099937138333690347986612540761793805055242734953861690e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 2.6519613568352334924470820065166161144381584786255294172031003071471600949016031668052906818697878641942881494964276e+00), + }; + return data; + } + static std::array const & weights() + { + static std::array data = { + BOOST_MATH_HUGE_CONSTANT(T, 0, 8.1026461755680732676487656381309494070745117994166268718345498964704515867018614005712030022333470419027511937110060e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 4.2560725261012780052031746666639103543970682101400152587878953913358027297072602373305673647185542480994656431711885e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 5.4515582819127030592178568841695125960899915859346492986586846631369448562711195465546454603039043598893480308577392e-02), + BOOST_MATH_HUGE_CONSTANT(T, 0, 9.7178124509951915414942425593895964444240121701420164980001433798334142698580146031198718271051220413580750089473744e-04), + }; + return data; + } + }; + +#ifndef BOOST_HAS_FLOAT128 +template +class gauss_hermite_detail +{ + using storage_type = typename quadrature_constant_category::storage_type; + public: + static std::array const & abscissa() + { + static std::array data = { + static_cast(3.42901327223704608789165025557258031e-01L), + static_cast(1.03661082978951365417749191675920902e+00L), + static_cast(1.75668364929988177345140122010615676e+00L), + static_cast(2.53273167423278979640896079775479348e+00L), + static_cast(3.43615911883773760332672549431912138e+00L), + }; + return data; + } + static std::array const & weights() + { + static std::array data = { + static_cast(6.10862633735325798783564990433419713e-01L), + static_cast(2.40138611082314686416523295005861395e-01L), + static_cast(3.38743944554810631361647312775859737e-02L), + static_cast(1.34364574678123269220156558584591387e-03L), + static_cast(7.64043285523262062915936785959522211e-06L), + }; + return data; + } + }; + +#else +template +class gauss_hermite_detail +{ + using storage_type = typename quadrature_constant_category::storage_type; + public: + static std::array const & abscissa() + { + static std::array data = { + static_cast(3.42901327223704608789165025557258031e-01Q), + static_cast(1.03661082978951365417749191675920902e+00Q), + static_cast(1.75668364929988177345140122010615676e+00Q), + static_cast(2.53273167423278979640896079775479348e+00Q), + static_cast(3.43615911883773760332672549431912138e+00Q), + }; + return data; + } + static std::array const & weights() + { + static std::array data = { + static_cast(6.10862633735325798783564990433419713e-01Q), + static_cast(2.40138611082314686416523295005861395e-01Q), + static_cast(3.38743944554810631361647312775859737e-02Q), + static_cast(1.34364574678123269220156558584591387e-03Q), + static_cast(7.64043285523262062915936785959522211e-06Q), + }; + return data; + } + }; + +#endif +template +class gauss_hermite_detail +{ + using storage_type = typename quadrature_constant_category::storage_type; + public: + static std::array const & abscissa() + { + static std::array data = { + BOOST_MATH_HUGE_CONSTANT(T, 0, 3.4290132722370460878916502555725803120830265867773062820577103907292018192312101560713520305443248063627958675235231e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.0366108297895136541774919167592090162982561106572157244372326874036404187243878992980306028243900733070850998719429e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.7566836492998817734514012201061567632954744937388471000872849560961705796098190771278266711469838314640623161517203e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 2.5327316742327897964089607977547934803078465081567249459332874134930859380473865340227292325941771646240824732515703e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 3.4361591188377376033267254943191213848406783093901772906871762944002361145649511153468627231618843292611320162500620e+00), + }; + return data; + } + static std::array const & weights() + { + static std::array data = { + BOOST_MATH_HUGE_CONSTANT(T, 0, 6.1086263373532579878356499043341971323859272928403754564871663738953676910082005768001121074412857938126204657377493e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 2.4013861108231468641652329500586139537004249390192739899066056147994315237169314350600241149865696523148172530499056e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 3.3874394455481063136164731277585973698161942481867016739715157699771381277813573402914401584449869233310982466662099e-02), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.3436457467812326922015655858459138698692732786257703646162498020762483818413155201782152234375992775169973716992552e-03), + BOOST_MATH_HUGE_CONSTANT(T, 0, 7.6404328552326206291593678595952221082891147358323631952885551280911633480005783690893185993195845416600950144409630e-06), + }; + return data; + } + }; + +#ifndef BOOST_HAS_FLOAT128 +template +class gauss_hermite_detail +{ + using storage_type = typename quadrature_constant_category::storage_type; + public: + static std::array const & abscissa() + { + static std::array data = { + static_cast(0.00000000000000000000000000000000000e+00L), + static_cast(5.65069583255575748526020337198188867e-01L), + static_cast(1.13611558521092066631913490555610213e+00L), + static_cast(1.71999257518648893241583152515256151e+00L), + static_cast(2.32573248617385774545404479448534701e+00L), + static_cast(2.96716692790560324848896036354980632e+00L), + static_cast(3.66995037340445253472922383311568148e+00L), + static_cast(4.49999070730939155366438053053482422e+00L), + }; + return data; + } + static std::array const & weights() + { + static std::array data = { + static_cast(5.64100308726417532852625797339963533e-01L), + static_cast(4.12028687498898627025891079567810319e-01L), + static_cast(1.58488915795935746883839384959994027e-01L), + static_cast(3.07800338725460822286814158757801456e-02L), + static_cast(2.77806884291277589607887049229213490e-03L), + static_cast(1.00004441232499868127296736176978509e-04L), + static_cast(1.05911554771106663577520791055016329e-06L), + static_cast(1.52247580425351702016062666964826618e-09L), + }; + return data; + } + }; + +#else +template +class gauss_hermite_detail +{ + using storage_type = typename quadrature_constant_category::storage_type; + public: + static std::array const & abscissa() + { + static std::array data = { + static_cast(0.00000000000000000000000000000000000e+00Q), + static_cast(5.65069583255575748526020337198188867e-01Q), + static_cast(1.13611558521092066631913490555610213e+00Q), + static_cast(1.71999257518648893241583152515256151e+00Q), + static_cast(2.32573248617385774545404479448534701e+00Q), + static_cast(2.96716692790560324848896036354980632e+00Q), + static_cast(3.66995037340445253472922383311568148e+00Q), + static_cast(4.49999070730939155366438053053482422e+00Q), + }; + return data; + } + static std::array const & weights() + { + static std::array data = { + static_cast(5.64100308726417532852625797339963533e-01Q), + static_cast(4.12028687498898627025891079567810319e-01Q), + static_cast(1.58488915795935746883839384959994027e-01Q), + static_cast(3.07800338725460822286814158757801456e-02Q), + static_cast(2.77806884291277589607887049229213490e-03Q), + static_cast(1.00004441232499868127296736176978509e-04Q), + static_cast(1.05911554771106663577520791055016329e-06Q), + static_cast(1.52247580425351702016062666964826618e-09Q), + }; + return data; + } + }; + +#endif +template +class gauss_hermite_detail +{ + using storage_type = typename quadrature_constant_category::storage_type; + public: + static std::array const & abscissa() + { + static std::array data = { + BOOST_MATH_HUGE_CONSTANT(T, 0, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 5.6506958325557574852602033719818886681552078800505788680930739682745058470915375159973526283034610292989738379345761e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.1361155852109206663191349055561021252835292947846650850648392599800715967101004409631966601830482707422651868052475e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.7199925751864889324158315251525615148429195630613888498938216300095132434761832428439718888176122448729491067241320e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 2.3257324861738577454540447944853470123070950095634828957721625948740238048583608727061841554643103134570736658336089e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 2.9671669279056032484889603635498063155705164076381381507212727522118956916046294049934561649283587290854852693064039e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 3.6699503734044525347292238331156814846958556260108268200827250197712929612325341525137596165272567610075980577793224e+00), + BOOST_MATH_HUGE_CONSTANT(T, 0, 4.4999907073093915536643805305348242199319830534949905938271742846019366228525630586264389556919589962713446071341276e+00), + }; + return data; + } + static std::array const & weights() + { + static std::array data = { + BOOST_MATH_HUGE_CONSTANT(T, 0, 5.6410030872641753285262579733996353292453477640072243023805413420648986959478382400247069852378235816199417789938317e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 4.1202868749889862702589107956781031893375232741692141877844273550979447720862335855236503495494156330750630603931556e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.5848891579593574688383938495999402721002703620834420484147417162556491543397074116784210832986285797844312792251258e-01), + BOOST_MATH_HUGE_CONSTANT(T, 0, 3.0780033872546082228681415875780145569645078095357831670126204320943426296907483543543105075772562113024847790201415e-02), + BOOST_MATH_HUGE_CONSTANT(T, 0, 2.7780688429127758960788704922921349030124251134822666685717061210098979501372205289327949738880183107056484267658214e-03), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.0000444123249986812729673617697850851699387810876387789234107161752152460966503439378917351614005951603805751399265e-04), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.0591155477110666357752079105501632872963524018315499158761728455091303265515893684325618169279641299843625141139696e-06), + BOOST_MATH_HUGE_CONSTANT(T, 0, 1.5224758042535170201606266696482661827962160316014537930014349599535491582697947140375830838937903702636262186650310e-09), + }; + return data; + } + }; + +} // namespace detail + +template > +class gauss_hermite : public detail::gauss_hermite_detail::value> +{ + using base = detail::gauss_hermite_detail::value>; + + // Abscissas computed on demand are NaN when the recurrence overflows Real. + static bool overflowed() + { + return !(BOOST_MATH_NAMESPACE::isfinite)(static_cast(base::abscissa().back())); + } + + static Real overflow_error() + { + return policies::raise_evaluation_error( + "boost::math::quadrature::gauss_hermite<%1%>::integrate", + "The Hermite recurrence overflows with this many points; use fewer points or a type with a wider exponent range.", + std::numeric_limits::quiet_NaN(), Policy()); + } + +public: + // Integrates f(x) exp(-x^2) over the real line. + template + static auto integrate(F f, Real* pL1 = nullptr)->decltype(std::declval()(std::declval())) + { + // In many math texts, K represents the field of real or complex numbers. + // Too bad we can't put blackboard bold into C++ source! + using K = decltype(f(Real(0))); + static_assert(!std::is_integral::value, + "The return type cannot be integral, it must be either a real or complex floating point type."); + using std::abs; + if (overflowed()) + { + Real error = overflow_error(); + if (pL1) + *pL1 = error; + return static_cast(error); + } + unsigned non_zero_start = 1; + K result = Real(0); + if (N & 1) + { + result = f(Real(0)) * static_cast(base::weights()[0]); + } + else + { + non_zero_start = 0; + } + Real L1 = abs(result); + for (unsigned i = non_zero_start; i < base::abscissa().size(); ++i) + { + K fp = f(static_cast(base::abscissa()[i])); + K fm = f(-static_cast(base::abscissa()[i])); + result += (fp + fm) * static_cast(base::weights()[i]); + L1 += (abs(fp) + abs(fm)) * static_cast(base::weights()[i]); + } + if (pL1) + *pL1 = L1; + return result; + } + + // Explicit zero and norm for vector- and matrix-valued integrands. + template + static auto integrate(F f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real* pL1 = nullptr) + ->decltype(static_cast(norm(f(Real(0)))), f(Real(0))) + { + using K = decltype(f(Real(0))); + static_assert(!std::is_integral::value, "The return type cannot be integral."); + if (overflowed()) + { + // Preserve the scalar error policy, including non-throwing policies, + // and use scalar multiplication to produce a result with the right shape. + Real error = overflow_error(); + if (pL1) + *pL1 = error; + K result = zero * error; + return result; + } + unsigned non_zero_start = 1; + K result = zero; + if (N & 1) + { + result = f(Real(0)) * static_cast(base::weights()[0]); + } + else + { + non_zero_start = 0; + } + Real L1 = static_cast(norm(result)); + for (unsigned i = non_zero_start; i < base::abscissa().size(); ++i) + { + K fp = f(static_cast(base::abscissa()[i])); + K fm = f(-static_cast(base::abscissa()[i])); + result += (fp + fm) * static_cast(base::weights()[i]); + L1 += (static_cast(norm(fp)) + static_cast(norm(fm))) * static_cast(base::weights()[i]); + } + if (pL1) + *pL1 = L1; + return result; + } +}; + +} // namespace quadrature +BOOST_MATH_NAMESPACE_END + +#endif // BOOST_MATH_QUADRATURE_GAUSS_HERMITE_HPP diff --git a/include/boost/math/quadrature/gauss_kronrod.hpp b/include/boost/math/quadrature/gauss_kronrod.hpp index a81cb43c4f..f66b9de5d0 100644 --- a/include/boost/math/quadrature/gauss_kronrod.hpp +++ b/include/boost/math/quadrature/gauss_kronrod.hpp @@ -13,14 +13,17 @@ #pragma warning(disable: 4127) #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include +#include -namespace boost { namespace math{ namespace quadrature{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature{ namespace detail{ #ifndef BOOST_MATH_GAUSS_NO_COMPUTE_ON_DEMAND @@ -34,7 +37,7 @@ class gauss_kronrod_detail } static std::vector calculate_abscissa() { - static std::vector result = boost::math::legendre_p_zeros((N - 1) / 2); + static std::vector result = BOOST_MATH_NAMESPACE::legendre_p_zeros((N - 1) / 2); const legendre_stieltjes E = get_legendre_stieltjes(); std::vector ls_zeros = E.zeros(); result.insert(result.end(), ls_zeros.begin(), ls_zeros.end()); @@ -51,7 +54,7 @@ class gauss_kronrod_detail for (unsigned i = gauss_start; i < abscissa().size(); i += 2) { Real x = abscissa()[i]; - Real p = boost::math::legendre_p_prime(gauss_order, x); + Real p = BOOST_MATH_NAMESPACE::legendre_p_prime(gauss_order, x); Real gauss_weight = 2 / ((1 - x * x) * p * p); result[i] = gauss_weight + static_cast(2) / (static_cast(gauss_order + 1) * legendre_p_prime(gauss_order, x) * E(x)); } @@ -86,7 +89,7 @@ class gauss_kronrod_detail; template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -122,7 +125,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -194,7 +197,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -236,7 +239,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -320,7 +323,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -373,7 +376,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -477,7 +480,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -540,7 +543,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -664,7 +667,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -737,7 +740,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -881,7 +884,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -964,7 +967,7 @@ class gauss_kronrod_detail template class gauss_kronrod_detail { - using storage_type = typename gauss_constant_category::storage_type; + using storage_type = typename quadrature_constant_category::storage_type; public: static std::array const & abscissa() { @@ -1125,10 +1128,10 @@ class gauss_kronrod_detail } -template > -class gauss_kronrod : public detail::gauss_kronrod_detail::value> +BOOST_MATH_EXPORT template > +class gauss_kronrod : public detail::gauss_kronrod_detail::value> { - typedef detail::gauss_kronrod_detail::value> base; + typedef detail::gauss_kronrod_detail::value> base; public: typedef Real value_type; private: @@ -1233,7 +1236,7 @@ class gauss_kronrod : public detail::gauss_kronrod_detail::value, "The return type cannot be integral, it must be either a real or complex floating point type."); static const char* function = "boost::math::quadrature::gauss_kronrod<%1%>::integrate(f, %1%, %1%)"; - if (!(boost::math::isnan)(a) && !(boost::math::isnan)(b)) + if (!(BOOST_MATH_NAMESPACE::isnan)(a) && !(BOOST_MATH_NAMESPACE::isnan)(b)) { // Infinite limits: if ((a <= -tools::max_value()) && (b >= tools::max_value())) @@ -1253,7 +1256,7 @@ class gauss_kronrod : public detail::gauss_kronrod_detail= tools::max_value())) + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (b >= tools::max_value())) { auto u = [&](const Real& t)->K { @@ -1271,7 +1274,7 @@ class gauss_kronrod : public detail::gauss_kronrod_detail())) + if ((BOOST_MATH_NAMESPACE::isfinite)(b) && (a <= -tools::max_value())) { auto v = [&](const Real& t)->K { @@ -1288,7 +1291,7 @@ class gauss_kronrod : public detail::gauss_kronrod_detail(policies::raise_domain_error(function, "The domain of integration is not sensible; please check the bounds.", a, Policy())); } + +private: + // Explicit zero/norm path; preserve the original scalar/complex path above. + template + static auto integrate_non_adaptive_m1_1(F f, const decltype(f(Real(0)))& zero, Norm norm, Real* error = nullptr, Real* pL1 = nullptr)->decltype(std::declval()(std::declval())) + { + typedef decltype(f(Real(0))) K; + unsigned gauss_start = 2; + unsigned kronrod_start = 1; + unsigned gauss_order = (N - 1) / 2; + K kronrod_result = zero; + K gauss_result = zero; + K fp = zero, fm = zero; + if (gauss_order & 1) + { + fp = f(value_type(0)); + kronrod_result = fp * static_cast(base::weights()[0]); + gauss_result += fp * static_cast(gauss::weights()[0]); + } + else + { + fp = f(value_type(0)); + kronrod_result = fp * static_cast(base::weights()[0]); + gauss_start = 1; + kronrod_start = 2; + } + Real L1 = static_cast(norm(kronrod_result)); + for (unsigned i = gauss_start; i < base::abscissa().size(); i += 2) + { + fp = f(static_cast(base::abscissa()[i])); + fm = f(static_cast(-base::abscissa()[i])); + kronrod_result += (fp + fm) * static_cast(base::weights()[i]); + L1 += (static_cast(norm(fp)) + static_cast(norm(fm))) * static_cast(base::weights()[i]); + gauss_result += (fp + fm) * static_cast(gauss::weights()[i / 2]); + } + for (unsigned i = kronrod_start; i < base::abscissa().size(); i += 2) + { + fp = f(static_cast(base::abscissa()[i])); + fm = f(static_cast(-base::abscissa()[i])); + kronrod_result += (fp + fm) * static_cast(base::weights()[i]); + L1 += (static_cast(norm(fp)) + static_cast(norm(fm))) * static_cast(base::weights()[i]); + } + if (pL1) + *pL1 = L1; + if (error) + *error = (std::max)(static_cast(norm(kronrod_result - gauss_result)), static_cast(norm(kronrod_result * tools::epsilon() * Real(2)))); + return kronrod_result; + } + + template + struct norm_recursive_info + { + F f; + Real tol; + const decltype(std::declval()(std::declval()))& zero; + Norm norm; + }; + + template + static auto recursive_adaptive_integrate(const norm_recursive_info* info, Real a, Real b, unsigned max_levels, Real abs_tol, Real* error, Real* L1)->decltype(std::declval()(std::declval())) + { + typedef decltype(info->f(Real(a))) K; + Real error_local; + Real mean = (b + a) / 2; + Real scale = (b - a) / 2; + auto ff = [&](const Real& x)->K + { + return info->f(scale * x + mean); + }; + K r1 = integrate_non_adaptive_m1_1(ff, info->zero, info->norm, &error_local, L1); + K estimate = scale * r1; + error_local *= scale; + + K tmp = estimate * info->tol; + Real abs_tol1 = static_cast(info->norm(tmp)); + if (abs_tol == 0) + abs_tol = abs_tol1; + + if (max_levels && (abs_tol1 < error_local) && (abs_tol < error_local)) + { + Real mid = (a + b) / 2; + Real L1_local; + estimate = recursive_adaptive_integrate(info, a, mid, max_levels - 1, abs_tol / 2, error, L1); + estimate += recursive_adaptive_integrate(info, mid, b, max_levels - 1, abs_tol / 2, &error_local, &L1_local); + if (error) + *error += error_local; + if (L1) + *L1 += L1_local; + return estimate; + } + if(L1) + *L1 *= scale; + if (error) + *error = error_local; + return estimate; + } + +public: + template + static auto integrate(F f, Real a, Real b, const decltype(f(a))& zero, Norm norm, unsigned max_depth = 15, Real tol = tools::root_epsilon(), Real* error = nullptr, Real* pL1 = nullptr)->decltype(static_cast(norm(f(a))), f(a)) + { + typedef decltype(f(a)) K; + static_assert(!std::is_integral::value, + "The return type cannot be integral."); + static const char* function = "boost::math::quadrature::gauss_kronrod<%1%>::integrate(f, %1%, %1%)"; + if (!(BOOST_MATH_NAMESPACE::isnan)(a) && !(BOOST_MATH_NAMESPACE::isnan)(b)) + { + // Infinite limits: + if ((a <= -tools::max_value()) && (b >= tools::max_value())) + { + auto u = [&](const Real& t)->K + { + Real t_sq = t*t; + Real inv = 1 / (1 - t_sq); + Real w = (1 + t_sq)*inv*inv; + Real arg = t*inv; + K res = f(arg)*w; + return res; + }; + norm_recursive_info info = { u, tol, zero, norm }; + K res = recursive_adaptive_integrate(&info, Real(-1), Real(1), max_depth, Real(0), error, pL1); + return res; + } + + // Right limit is infinite: + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (b >= tools::max_value())) + { + auto u = [&](const Real& t)->K + { + Real z = 1 / (t + 1); + Real arg = 2 * z + a - 1; + K res = f(arg)*z*z; + return res; + }; + norm_recursive_info info = { u, tol, zero, norm }; + K Q = Real(2) * recursive_adaptive_integrate(&info, Real(-1), Real(1), max_depth, Real(0), error, pL1); + if (pL1) + { + *pL1 *= 2; + } + if (error) + *error *= 2; + return Q; + } + + if ((BOOST_MATH_NAMESPACE::isfinite)(b) && (a <= -tools::max_value())) + { + auto v = [&](const Real& t)->K + { + Real z = 1 / (t + 1); + Real arg = 2 * z - 1; + return f(b - arg) * z * z; + }; + norm_recursive_info info = { v, tol, zero, norm }; + K Q = Real(2) * recursive_adaptive_integrate(&info, Real(-1), Real(1), max_depth, Real(0), error, pL1); + if (pL1) + { + *pL1 *= 2; + } + if (error) + *error *= 2; + return Q; + } + + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (BOOST_MATH_NAMESPACE::isfinite)(b)) + { + if (a==b) + { + if (error) + *error = Real(0); + if (pL1) + *pL1 = Real(0); + return zero; + } + norm_recursive_info info = { f, tol, zero, norm }; + if (b < a) + { + return -recursive_adaptive_integrate(&info, b, a, max_depth, Real(0), error, pL1); + } + return recursive_adaptive_integrate(&info, a, b, max_depth, Real(0), error, pL1); + } + } + Real invalid = policies::raise_domain_error(function, "The domain of integration is not sensible; please check the bounds.", a, Policy()); + if (error) + *error = invalid; + if (pL1) + *pL1 = invalid; + K result = zero * invalid; + return result; + } }; } // namespace quadrature -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/quadrature/naive_monte_carlo.hpp b/include/boost/math/quadrature/naive_monte_carlo.hpp index 954612c268..9fb62f6472 100644 --- a/include/boost/math/quadrature/naive_monte_carlo.hpp +++ b/include/boost/math/quadrature/naive_monte_carlo.hpp @@ -6,6 +6,7 @@ */ #ifndef BOOST_MATH_QUADRATURE_NAIVE_MONTE_CARLO_HPP #define BOOST_MATH_QUADRATURE_NAIVE_MONTE_CARLO_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -21,14 +22,17 @@ #include #include #include +#endif #include #include #ifdef BOOST_NAIVE_MONTE_CARLO_DEBUG_FAILURES +#ifndef BOOST_MATH_BUILD_MODULE # include #endif +#endif -namespace boost { namespace math { namespace quadrature { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { namespace detail { enum class limit_classification {FINITE, @@ -37,7 +41,7 @@ namespace detail { DOUBLE_INFINITE}; } -template, +BOOST_MATH_EXPORT template, typename std::enable_if::value, bool>::type = true> class naive_monte_carlo { @@ -51,7 +55,7 @@ class naive_monte_carlo { using std::numeric_limits; using std::sqrt; - using boost::math::isinf; + using BOOST_MATH_NAMESPACE::isinf; std::uint64_t n = bounds.size(); m_lbs.resize(n); @@ -63,7 +67,7 @@ class naive_monte_carlo { if (bounds[i].second <= bounds[i].first) { - boost::math::policies::raise_domain_error(function, "The upper bound is <= the lower bound.\n", bounds[i].second, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "The upper bound is <= the lower bound.\n", bounds[i].second, Policy()); return; } if (isinf(bounds[i].first)) @@ -391,6 +395,7 @@ class naive_monte_carlo // The idea is that the unstabilized additions have error sigma(f)/sqrt(N) + epsilon*N, which diverges faster than it converges! // Kahan summation turns this to sigma(f)/sqrt(N) + epsilon^2*N, and the random walk occurs on a timescale of 10^14 years (on current hardware) Real compensator = 0; + Real S_compensator = 0; std::uint64_t k = m_thread_calls[thread_index].load(std::memory_order_consume); while (!m_done) // relaxed load { @@ -419,14 +424,18 @@ class naive_monte_carlo } os << x[x.size() -1] << "}, and returned " << f << std::endl; static const char* function = "boost::math::quadrature::naive_monte_carlo<%1%>"; - boost::math::policies::raise_domain_error(function, os.str().c_str(), /*this is a dummy arg to make it compile*/ 7.2, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, os.str().c_str(), /*this is a dummy arg to make it compile*/ 7.2, Policy()); } ++k; Real term = (f - M1)/k; Real y1 = term - compensator; Real M2 = M1 + y1; compensator = (M2 - M1) - y1; - S += (f - M1)*(f - M2); + Real S_term = (f - M1)*(f - M2); + Real y2 = S_term - S_compensator; + Real S2 = S + y2; + S_compensator = (S2 - S) - y2; + S = S2; M1 = M2; } m_thread_averages[thread_index].store(M1, std::memory_order_release); @@ -465,5 +474,5 @@ class naive_monte_carlo std::mutex m_exception_mutex; }; -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/quadrature/ooura_fourier_integrals.hpp b/include/boost/math/quadrature/ooura_fourier_integrals.hpp index b31996c2bc..2f98b2ad6b 100644 --- a/include/boost/math/quadrature/ooura_fourier_integrals.hpp +++ b/include/boost/math/quadrature/ooura_fourier_integrals.hpp @@ -11,12 +11,14 @@ */ #ifndef BOOST_MATH_QUADRATURE_OOURA_FOURIER_INTEGRALS_HPP #define BOOST_MATH_QUADRATURE_OOURA_FOURIER_INTEGRALS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include -namespace boost { namespace math { namespace quadrature { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { -template +BOOST_MATH_EXPORT template class ooura_fourier_sin { public: ooura_fourier_sin(const Real relative_error_tolerance = tools::root_epsilon(), size_t levels = sizeof(Real)) : impl_(std::make_shared>(relative_error_tolerance, levels)) @@ -49,7 +51,7 @@ class ooura_fourier_sin { }; -template +BOOST_MATH_EXPORT template class ooura_fourier_cos { public: ooura_fourier_cos(const Real relative_error_tolerance = tools::root_epsilon(), size_t levels = sizeof(Real)) : impl_(std::make_shared>(relative_error_tolerance, levels)) @@ -64,5 +66,5 @@ class ooura_fourier_cos { }; -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/quadrature/sinh_sinh.hpp b/include/boost/math/quadrature/sinh_sinh.hpp index 7aabcb4376..3f6daf2e1d 100644 --- a/include/boost/math/quadrature/sinh_sinh.hpp +++ b/include/boost/math/quadrature/sinh_sinh.hpp @@ -24,13 +24,15 @@ #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif -namespace boost{ namespace math{ namespace quadrature { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { -template > +BOOST_MATH_EXPORT template > class sinh_sinh { public: @@ -38,34 +40,41 @@ class sinh_sinh : m_imp(std::make_shared >(max_refinements)) {} template - auto integrate(const F f, Real tol = boost::math::tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(std::declval()(std::declval())) + auto integrate(const F f, Real tol = BOOST_MATH_NAMESPACE::tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(std::declval()(std::declval())) { return m_imp->integrate(f, tol, error, L1, levels); } + template + auto integrate(const F f, const decltype(f(Real(0)))& zero, Norm norm, + Real tol = tools::root_epsilon(), Real* error = nullptr, + Real* L1 = nullptr, std::size_t* levels = nullptr) const + ->decltype(static_cast(norm(f(Real(0)))), f(Real(0))) + { + return m_imp->integrate(f, zero, norm, tol, error, L1, levels); + } + private: std::shared_ptr> m_imp; }; -}}} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC #ifdef BOOST_MATH_ENABLE_CUDA -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { -template > -__device__ auto sinh_sinh_integrate(const F& f, Real tol = boost::math::tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, boost::math::size_t* levels = nullptr) +template > +__device__ auto sinh_sinh_integrate(const F& f, Real tol = BOOST_MATH_NAMESPACE::tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, BOOST_MATH_NAMESPACE::size_t* levels = nullptr) { return detail::sinh_sinh_integrate_impl(f, tol, error, L1, levels); } } // namespace quadrature -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ENABLE_CUDA diff --git a/include/boost/math/quadrature/symplectic.hpp b/include/boost/math/quadrature/symplectic.hpp new file mode 100644 index 0000000000..04a3bc5e43 --- /dev/null +++ b/include/boost/math/quadrature/symplectic.hpp @@ -0,0 +1,696 @@ +// Copyright Jacob Hass, 2026 +// 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) + +// Disable warnings when defining size_check for numeric types +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning (disable : 4100) // 'function': unreferenced parameter +#endif + +#ifndef BOOST_MATH_QUADRATURE_SYMPLECTIC_HPP +#define BOOST_MATH_QUADRATURE_SYMPLECTIC_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { + +BOOST_MATH_EXPORT enum class available_methods +{ + Y6, + Y4, + Y2, + SRKNB6, + SRKNB11 +}; + +namespace detail { + +template +using void_t = void; + +template +struct has_plus : std::false_type {}; + +template +struct has_plus() + std::declval())> > : std::true_type {}; + +template +BOOST_MATH_INLINE_CONSTEXPR bool has_plus_v = has_plus::value; + +template +struct has_size : std::false_type {}; + +template +struct has_size().size())> > : std::true_type {}; + +template +BOOST_MATH_INLINE_CONSTEXPR bool has_size_v = has_size::value; + +template +typename std::enable_if_t, void> +add(T& x, const U& y) +{ + x = x + y; +} + +template +typename std::enable_if_t, void> +add(T& vec1, const U& vec2) +{ + for (std::size_t i=0; i < vec1.size(); i++) + { + vec1[i] = vec1[i] + vec2[i]; + } +} + +template +typename std::enable_if_t, void> +subtract(T& x, const U& y) +{ + x = x - y; +} + +template +typename std::enable_if_t, void> +subtract(T& vec1, const U& vec2) +{ + for (std::size_t i=0; i < vec1.size(); i++) + { + vec1[i] = vec1[i] - vec2[i]; + } +} + +template +typename std::enable_if_t, typename T::value_type> +l2_norm(const T& vec) +{ + typename T::value_type sum = 0; + for (std::size_t i=0; i < vec.size(); i++) + { + sum += vec[i] * vec[i]; + } + return std::sqrt(sum); +} + +template +typename std::enable_if_t, T> +l2_norm(const T& val) +{ + BOOST_MATH_STD_USING; + return abs(val); +} + +template +typename std::enable_if_t, typename T::value_type> +avg_l2_norm(const T& vec) +{ + typename T::value_type sum = 0; + for (std::size_t i=0; i < vec.size(); i++) + { + sum += vec[i] * vec[i]; + } + typename T::value_type size = vec.size(); + return std::sqrt(sum / size); +} + +template +typename std::enable_if_t, T> +avg_l2_norm(const T& val) +{ + BOOST_MATH_STD_USING; + return abs(val); +} + +template +struct has_mult : std::false_type {}; + +template +struct has_mult() * std::declval())> > : std::true_type {}; + +template +BOOST_MATH_INLINE_CONSTEXPR bool has_mult_v = has_mult::value; + +template +typename std::enable_if_t, void> +mult_prefactor(T& x, U prefactor) +{ + x = x * prefactor; +} + +template +typename std::enable_if_t, void> +mult_prefactor(T& vec1, U prefactor) +{ + for (std::size_t i=0; i < vec1.size(); i++) + { + vec1[i] = vec1[i] * prefactor; + } +} + +template +typename std::enable_if_t<(has_size_v && has_size_v), void> +size_check(const T& vec1, const U& vec2, const char* function, const Policy& pol) +{ + if (vec1.size() != vec2.size()) + { + std::string msg = "Starting vectors (p0, q0) are not the same size but got (" + std::to_string(vec1.size()) + "!=" + std::to_string(vec2.size()) + ")"; + BOOST_MATH_NAMESPACE::policies::raise_evaluation_error(function, msg.c_str(), 0, pol); + } +} + +template +typename std::enable_if_t && has_size_v), void> +size_check(const T& /*vec1*/, const U& /*vec2*/, const char* /*function*/, const Policy& /*pol*/){ return; } + +// Function to initialize array of integer types of size N +template +typename std::enable_if_t, std::vector > +initialize_array(const T& /*p0*/, const size_t N) +{ + std::vector initializedArr(N); + return initializedArr; +} + +// Function to initialize vector of vectors of size (N, p0.size()) +template +typename std::enable_if_t, std::vector > +initialize_array(const T& p0, const size_t N) +{ + std::vector initializedArr(N, T(p0.size(), 0)); + return initializedArr; +} + +template +void second_order_yoshida(RandomAccessContainer& p0, RandomAccessContainer& q0, const RealType dt, + const Func dHdp, const Func dHdq) +{ + + // Half step in q + RandomAccessContainer dq = dHdp(p0); + mult_prefactor(dq, dt / RealType(2)); + add(q0, dq); + + // Full step in p + RandomAccessContainer dp = dHdq(q0); + mult_prefactor(dp, -dt); + add(p0, dp); + + // Half step in q + dq = dHdp(p0); + mult_prefactor(dq, dt / RealType(2)); + add(q0, dq); +} + +template +void fourth_order_yoshida(RandomAccessContainer& p0, RandomAccessContainer& q0, const RealType dt, + const Func dHdp, const Func dHdq) +{ + BOOST_MATH_STD_USING + + RealType x1 = RealType(1) / (RealType(2) - cbrt(RealType(2))); + RealType x0 = RealType(1) - RealType(2) * x1; + + std::array weights = { x1, x0, x1 }; + + for (std::size_t i=0; i < weights.size(); i++) + { + second_order_yoshida(p0, q0, weights[i] * dt, dHdp, dHdq); + } +} + +template +void sixth_order_yoshida(RandomAccessContainer& p0, RandomAccessContainer& q0, const RealType dt, + const Func dHdp, const Func dHdq) +{ + + // Choosing "System A" solution + // The following Mathematica command can calculate these coefficients to arbitrary precision + // FindRoot[{w0+2(w1+w2+w3)==1, + // w0^3 + 2(w1^3 + w2^3+w3^3)==0, + // w0^5 + 2(w1^5 + w2^5+w3^5)==0, + // 1/6(w0^2w1^3-w0^4*w1) - 1/6(w0^3w1^2-w0*w1^4)+1/6((w0+2w1)^2w2^3-(w0+2w1)(w0^3+2w1^3)w2) - 1/6((w0^3+2w1^3)w2^2-(w0+2w1)w2^4) +1/6((w0+2w1+2w2)^2w3^3-(w0+2w1+2w2)(w0^3+2w1^3+2w2^3)w3)-1/6((w0^3+2w1^3+2w2^3)w3^2-(w0+2w1+2w2)w3^4)==0}, {{w0,1.3151863206839063}, {w1,-1.17767998417887}, {w2,0.235573213359357}, {w3,0.784513610477560}}, WorkingPrecision->64] + RealType w1 = static_cast(-1.17767998417887100694641568096431573463926925263459848447536851379674155618156L); + RealType w2 = static_cast(0.23557321335935813368479318297853460168646808210340111900349313095621471215223L); + RealType w3 = static_cast(0.78451361047755726381949763386634987577682441745149338456794779895125997479548L); + // w0 = 1.31518632068391121888424972823886251435195350615940796180785516777853373846773 + RealType w0 = RealType(1) - RealType(2) * (w1 + w2 + w3); + std::array weights = { w3, w2, w1, w0, w1, w2, w3}; + + for (std::size_t i=0; i < weights.size(); i++) + { + second_order_yoshida(p0, q0, weights[i] * dt, dHdp, dHdq); + } +} + +template +void SRKN_b_6(RandomAccessContainer& p0, RandomAccessContainer& q0, const RealType dt, + const Func dHdp, const Func dHdq) +{ // This method implements SRKN_b^6 in Table 3 here + // https://www.sciencedirect.com/science/article/pii/S0377042701004927 + + RealType b1 = static_cast(0.0829844064174052); + RealType b2 = static_cast(0.396309801498368); + RealType b3 = static_cast(-0.0390563049223486); + RealType b4 = 1.0 - 2.0 * (b1 + b2 + b3); + + RealType a1 = static_cast(0.245298957184271); + RealType a2 = static_cast(0.604872665711080); + RealType a3 = 0.5 - (a1 + a2); + + std::array b_weights = {b1, b2, b3, b4, b3, b2}; + std::array a_weights = {a1, a2, a3, a3, a2, a1}; + + RealType a, b; + for (std::size_t i=0; i < b_weights.size(); i++) + { + b = b_weights[i]; + a = a_weights[i]; + + RandomAccessContainer dq = dHdp(p0); + mult_prefactor(dq, dt * b); + add(q0, dq); + + RandomAccessContainer dp = dHdq(q0); + mult_prefactor(dp, -a * dt); + add(p0, dp); + } + // Need to do one more step in q + RandomAccessContainer dq = dHdp(p0); + mult_prefactor(dq, dt * b1); + add(q0, dq); +} + +template +void SRKN_b_11(RandomAccessContainer& p0, RandomAccessContainer& q0, const RealType dt, + const Func dHdp, const Func dHdq) +{ // This method implements SRKN_b^11 in Table 3 here + // https://www.sciencedirect.com/science/article/pii/S0377042701004927 + + RealType b1 = static_cast(0.0414649985182624); + RealType b2 = static_cast(0.198128671918067); + RealType b3 = static_cast(-0.0400061921041533); + RealType b4 = static_cast(0.0752539843015807); + RealType b5 = static_cast(-0.0115113874206879); + RealType b6 = 0.5 - (b1 + b2 + b3 + b4 + b5); + + RealType a1 = static_cast(0.123229775946271); + RealType a2 = static_cast(0.290553797799558); + RealType a3 = static_cast(-0.127049212625417); + RealType a4 = static_cast(-0.246331761062075); + RealType a5 = static_cast(0.357208872795928); + RealType a6 = 1.0 - 2.0 * (a1 + a2 + a3 + a4 + a5); + + std::array b_weights = {b1, b2, b3, b4, b5, b6, b6, b5, b4, b3, b2}; + std::array a_weights = {a1, a2, a3, a4, a5, a6, a5, a4, a3, a2, a1}; + + RealType a, b; + for (std::size_t i=0; i < b_weights.size(); i++) + { + b = b_weights[i]; + a = a_weights[i]; + + RandomAccessContainer dq = dHdp(p0); + mult_prefactor(dq, dt * b); + add(q0, dq); + + RandomAccessContainer dp = dHdq(q0); + mult_prefactor(dp, -a * dt); + add(p0, dp); + } + // Need to do one more step in q + RandomAccessContainer dq = dHdp(p0); + mult_prefactor(dq, dt * b1); + add(q0, dq); +} + +template +std::pair, std::vector > integrate_hamiltonian_imp(RandomAccessContainer& p0, + RandomAccessContainer& q0, + const RealType dt, + const unsigned steps, + const Func& dHdp, + const Func& dHdq, + const available_methods& method, + const Policy& pol) +{ + // Not sure how to make this function string nicer + static const char* function = "boost::math::quadrature::integrate_hamiltonian(p0, q0, %1%, steps, dHdp, dHdq)"; + + if ((dt <= 0) || !(BOOST_MATH_NAMESPACE::isfinite)(dt)) + { + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Time step must be positive and finite but got: dt = %1%.\n", dt, pol); + } + + // Check that p0 and q0 have the same size + size_check(p0, q0, function, pol); + #ifdef _MSC_VER + # pragma warning(pop) + #endif + + typedef void (*stepperType)(RandomAccessContainer&, RandomAccessContainer&, RealType, Func, Func); + + stepperType stepper; + switch (method) { + case available_methods::Y6: stepper = sixth_order_yoshida; break; + case available_methods::Y4: stepper = fourth_order_yoshida; break; + case available_methods::Y2: stepper = second_order_yoshida; break; + case available_methods::SRKNB6: stepper = SRKN_b_6; break; + case available_methods::SRKNB11: stepper = SRKN_b_11; break; + default: BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Incorrect method recieved. Must be in `available_methods` enum class.", 0, pol); + } + + std::vector p = initialize_array(p0, steps); + std::vector q = initialize_array(q0, steps); + p[0] = p0; + q[0] = q0; + + for (unsigned i=1; i < steps; i++) + { + stepper(p0, q0, dt, dHdp, dHdq); + p[i] = p0; + q[i] = q0; + } + return std::make_pair(p, q); +} + +template +struct error_info +{ + error_info(stepperType stepper_, const Func& dHdp_, const Func& dHdq_, unsigned order_, RealType atol_, RealType rtol_) + : stepper(stepper_), dHdp(dHdp_), dHdq(dHdq_), order(order_), atol(atol_), rtol(rtol_) + { + safe = RealType(0.9); + maxScale = RealType(2); + minScale = RealType(0.2); + rejected = true; + } + + // Here, current_p/q represents (p, q) before a single step of size dt is made + // whereas next_p/q represents (p, q) after a step of size dt + bool success(RandomAccessContainer& current_p, + RandomAccessContainer& current_q, + RandomAccessContainer& next_p, + RandomAccessContainer& /*next_q*/, + RealType& dt, + RealType& currentError) + { + using std::min; + using std::max; + BOOST_MATH_STD_USING + + RandomAccessContainer error_p = current_p; + RandomAccessContainer error_q = current_q; + + // For the error, reference method is using two half steps + stepper(error_p, error_q, dt / 2, dHdp, dHdq); + stepper(error_p, error_q, dt / 2, dHdp, dHdq); + + // Get difference in solution between one/two timesteps + subtract(error_p, next_p); + RealType error = avg_l2_norm(error_p); + currentError = error; + + // Get scale in which to reject error + RealType currentDistance = l2_norm(current_p); + RealType newDistance = l2_norm(next_p); + RealType tol = atol + rtol * (std::max)(currentDistance, newDistance); + error /= tol; + + RealType scale; + if (error <= 1.0) + { + if (error == 0.0) + { + scale = maxScale; + } + else + { + scale = safe * pow(static_cast(1 / error), RealType(1) / (order + 1)); + if (scale < minScale) scale = minScale; + if (scale > maxScale) scale = maxScale; + } + + if (rejected) + { + dt *= (min)(scale, RealType(1.0)); + } + else + { + dt *= scale; + } + errorOld = (max)(error, RealType(1e-4)); + rejected = false; + return true; + } + else + { + scale = (max)(safe * pow(static_cast(1 / error), RealType(1) / (order + 1)), minScale); + dt *= scale; + rejected = true; + return false; + } + } + + stepperType stepper; + const Func& dHdp; + const Func& dHdq; + unsigned order; + RealType atol; + RealType rtol; + + RealType errorOld; + RealType safe; + RealType maxScale; + RealType minScale; + bool rejected; +}; + +template +std::tuple, std::vector, std::vector, std::vector > integrate_hamiltonian_adaptive_imp(RandomAccessContainer& p0, + RandomAccessContainer& q0, + const std::pair& timeInterval, + const Func& dHdp, + const Func& dHdq, + const RealType& atol, + const RealType& rtol, + const available_methods& method, + const Policy& pol) +{ + BOOST_MATH_STD_USING + // Not sure how to make this function string nicer + static const char* function = "boost::math::quadrature::integrate_hamiltonian(p0, q0, %1%, steps, dHdp, dHdq)"; + + if (!(BOOST_MATH_NAMESPACE::isfinite)(timeInterval.second)) + { + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Maximum time must be positive and finite but got: tMax = %1%.\n", timeInterval.second, pol); + } + + if ((timeInterval.first < 0)) + { + BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Minimum time must be positive and finite but got: tMin = %1%.\n", timeInterval.first, pol); + } + + // Check that p0 and q0 have the same size + size_check(p0, q0, function, pol); + #ifdef _MSC_VER + # pragma warning(pop) + #endif + + typedef void (*stepperType)(RandomAccessContainer&, RandomAccessContainer&, RealType, Func, Func); + + unsigned order; + stepperType stepper; + switch (method) { + case available_methods::Y2: stepper = second_order_yoshida; order = 2; break; + case available_methods::Y6: stepper = sixth_order_yoshida; order = 6; break; + case available_methods::Y4: stepper = fourth_order_yoshida; order = 4; break; + case available_methods::SRKNB6: stepper = SRKN_b_6; order = 4; break; + case available_methods::SRKNB11: stepper = SRKN_b_11; order = 6; break; + default: BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Incorrect method recieved. Must be in `available_methods` enum class.", 0, pol); + } + + std::vector p = { p0 }; + std::vector q = { q0 }; + + std::vector time = { timeInterval.first }; + RealType dt = 0.01; + + // To calculate the error, we need to store the current values of p and q seperately + // from the values updated in the loop. This is because the steppers modify p and q in place + RandomAccessContainer current_p; + RandomAccessContainer current_q; + + error_info info( + stepper, dHdp, dHdq, order, atol, rtol); + + RealType currentError = 0; + std::vector error = { currentError }; + + while (time.back() < timeInterval.second) + { + // Save p0 and q0 for error estimation step + current_p = p0; + current_q = q0; + + // Step p0 and q0 forward one step + stepper(p0, q0, dt, dHdp, dHdq); + + bool stepSuccessful = info.success(current_p, current_q, p0, q0, dt, currentError); + if (!stepSuccessful) + { + // Reject the step and reset p0/q0 to current_p/q + p0 = current_p; + q0 = current_q; + } + else + { + // Accept the step, push back p/q and step t forward + p.push_back(p0); + q.push_back(q0); + time.push_back(time.back() + dt); + error.push_back(currentError); + } + } + return std::make_tuple(time, p, q, error); +} +} // namespace detail + +template +BOOST_MATH_EXPORT std::tuple, std::vector, std::vector, std::vector > integrate_hamiltonian_adaptive(RandomAccessContainer p0, + RandomAccessContainer q0, + const std::pair timeInterval, + const Func dHdp, + const Func dHdq, + const RealType atol, + const RealType rtol, + const available_methods& method, + const Policy pol) + { + return detail::integrate_hamiltonian_adaptive_imp(p0, q0, timeInterval, dHdp, dHdq, atol, rtol, method, pol); +} + +template +BOOST_MATH_EXPORT std::tuple, std::vector, std::vector, std::vector > integrate_hamiltonian_adaptive(RandomAccessContainer p0, + RandomAccessContainer q0, + const std::pair timeInterval, + const Func dHdp, + const Func dHdq, + const RealType atol, + const RealType rtol, + const available_methods& method) +{ + return detail::integrate_hamiltonian_adaptive_imp(p0, q0, timeInterval, dHdp, dHdq, atol, rtol, method, BOOST_MATH_NAMESPACE::policies::policy<>()); +} + +template +BOOST_MATH_EXPORT std::tuple, std::vector, std::vector, std::vector > integrate_hamiltonian_adaptive(RandomAccessContainer p0, + RandomAccessContainer q0, + const std::pair timeInterval, + const Func dHdp, + const Func dHdq, + const RealType atol, + const RealType rtol) +{ + return detail::integrate_hamiltonian_adaptive_imp(p0, q0, timeInterval, dHdp, dHdq, atol, rtol, available_methods::Y6, BOOST_MATH_NAMESPACE::policies::policy<>()); +} + +template +BOOST_MATH_EXPORT std::pair, std::vector > integrate_hamiltonian(RandomAccessContainer p0, + RandomAccessContainer q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq, + available_methods method, + const Policy& pol) +{ + return detail::integrate_hamiltonian_imp(p0, q0, dt, steps, dHdp, dHdq, method, pol); +} + +template +BOOST_MATH_EXPORT std::pair, std::vector > integrate_hamiltonian(RandomAccessContainer p0, + RandomAccessContainer q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq, + available_methods method) +{ + return integrate_hamiltonian(p0, q0, dt, steps, dHdp, dHdq, method, BOOST_MATH_NAMESPACE::policies::policy<>()); +} + +template +BOOST_MATH_EXPORT std::pair, std::vector > integrate_hamiltonian(RandomAccessContainer p0, + RandomAccessContainer q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq) +{ + return integrate_hamiltonian(p0, q0, dt, steps, dHdp, dHdq, available_methods::Y6, BOOST_MATH_NAMESPACE::policies::policy<>()); +} + +template +BOOST_MATH_EXPORT BOOST_MATH_NAMESPACE::interpolators::cubic_hermite > integrate_hamiltonian_cubic(RealType p0, + RealType q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq, + available_methods method, + const Policy& pol) +{ + std::vector p; + std::vector q; + std::tie(p, q) = detail::integrate_hamiltonian_imp(p0, q0, dt, steps, dHdp, dHdq, method, pol); + + std::vector dpdt(p.size()); + std::vector time(p.size(), 0); + for (std::size_t i=0; i < p.size(); i++) + { + dpdt[i] = -dHdq(p[i]); + time[i] = i * dt; + } + return BOOST_MATH_NAMESPACE::interpolators::cubic_hermite >(std::move(time), std::move(p), std::move(dpdt)); +} + +template +BOOST_MATH_EXPORT BOOST_MATH_NAMESPACE::interpolators::cubic_hermite > integrate_hamiltonian_cubic(RealType p0, + RealType q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq, + available_methods method) +{ + return integrate_hamiltonian_cubic(p0, q0, dt, steps, dHdp, dHdq, method, BOOST_MATH_NAMESPACE::policies::policy<>()); +} + +template +BOOST_MATH_EXPORT BOOST_MATH_NAMESPACE::interpolators::cubic_hermite > integrate_hamiltonian_cubic(RealType p0, + RealType q0, + const RealType dt, + const unsigned steps, + Func dHdp, + Func dHdq) +{ + return integrate_hamiltonian_cubic(p0, q0, dt, steps, dHdp, dHdq, available_methods::Y6, BOOST_MATH_NAMESPACE::policies::policy<>()); +} + +} BOOST_MATH_NAMESPACE_END + +#endif diff --git a/include/boost/math/quadrature/tanh_sinh.hpp b/include/boost/math/quadrature/tanh_sinh.hpp index d5fbe82525..5a5cd7e219 100644 --- a/include/boost/math/quadrature/tanh_sinh.hpp +++ b/include/boost/math/quadrature/tanh_sinh.hpp @@ -29,14 +29,16 @@ #ifndef BOOST_MATH_QUADRATURE_TANH_SINH_HPP #define BOOST_MATH_QUADRATURE_TANH_SINH_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include -namespace boost{ namespace math{ namespace quadrature { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { -template > +BOOST_MATH_EXPORT template > class tanh_sinh { public: @@ -53,6 +55,15 @@ class tanh_sinh template auto integrate(const F f, Real tolerance = tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(std::declval()(std::declval(), std::declval())); + template + auto integrate(const F f, Real a, Real b, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance = tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(static_cast(norm(std::declval()(std::declval()))), std::declval()(std::declval())); + template + auto integrate(const F f, Real a, Real b, const decltype(std::declval()(std::declval(), std::declval()))& zero, Norm norm, Real tolerance = tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(static_cast(norm(std::declval()(std::declval(), std::declval()))), std::declval()(std::declval(), std::declval())); + template + auto integrate(const F f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance = tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(static_cast(norm(std::declval()(std::declval()))), std::declval()(std::declval())); + template + auto integrate(const F f, const decltype(std::declval()(std::declval(), std::declval()))& zero, Norm norm, Real tolerance = tools::root_epsilon(), Real* error = nullptr, Real* L1 = nullptr, std::size_t* levels = nullptr) const ->decltype(static_cast(norm(std::declval()(std::declval(), std::declval()))), std::declval()(std::declval(), std::declval())); + private: std::shared_ptr> m_imp; }; @@ -62,15 +73,15 @@ template auto tanh_sinh::integrate(const F f, Real a, Real b, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(std::declval()(std::declval())) { BOOST_MATH_STD_USING - using boost::math::constants::half; - using boost::math::quadrature::detail::tanh_sinh_detail; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::quadrature::detail::tanh_sinh_detail; static const char* function = "tanh_sinh<%1%>::integrate"; typedef decltype(std::declval()(std::declval())) result_type; static_assert(!std::is_integral::value, "The return type cannot be integral, it must be either a real or complex floating point type."); - if (!(boost::math::isnan)(a) && !(boost::math::isnan)(b)) + if (!(BOOST_MATH_NAMESPACE::isnan)(a) && !(BOOST_MATH_NAMESPACE::isnan)(b)) { // Infinite limits: @@ -93,7 +104,7 @@ auto tanh_sinh::integrate(const F f, Real a, Real b, Real toleranc } // Right limit is infinite: - if ((boost::math::isfinite)(a) && (b >= tools::max_value())) + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (b >= tools::max_value())) { auto u = [&](const Real& t, const Real& tc)->result_type { @@ -122,7 +133,7 @@ auto tanh_sinh::integrate(const F f, Real a, Real b, Real toleranc return Q; } - if ((boost::math::isfinite)(b) && (a <= -tools::max_value())) + if ((BOOST_MATH_NAMESPACE::isfinite)(b) && (a <= -tools::max_value())) { auto v = [&](const Real& t, const Real& tc)->result_type { @@ -152,7 +163,7 @@ auto tanh_sinh::integrate(const F f, Real a, Real b, Real toleranc return Q; } - if ((boost::math::isfinite)(a) && (boost::math::isfinite)(b)) + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (BOOST_MATH_NAMESPACE::isfinite)(b)) { if (a == b) { @@ -227,12 +238,12 @@ template auto tanh_sinh::integrate(const F f, Real a, Real b, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(std::declval()(std::declval(), std::declval())) { BOOST_MATH_STD_USING - using boost::math::constants::half; - using boost::math::quadrature::detail::tanh_sinh_detail; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::quadrature::detail::tanh_sinh_detail; static const char* function = "tanh_sinh<%1%>::integrate"; - if ((boost::math::isfinite)(a) && (boost::math::isfinite)(b)) + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (BOOST_MATH_NAMESPACE::isfinite)(b)) { if (b <= a) { @@ -267,7 +278,7 @@ template template auto tanh_sinh::integrate(const F f, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(std::declval()(std::declval())) { - using boost::math::quadrature::detail::tanh_sinh_detail; + using BOOST_MATH_NAMESPACE::quadrature::detail::tanh_sinh_detail; static const char* function = "tanh_sinh<%1%>::integrate"; Real min_complement = tools::epsilon(); return m_imp->integrate([&](const Real& arg, const Real&) { return f(arg); }, error, L1, function, min_complement, min_complement, tolerance, levels); @@ -277,13 +288,248 @@ template template auto tanh_sinh::integrate(const F f, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(std::declval()(std::declval(), std::declval())) { - using boost::math::quadrature::detail::tanh_sinh_detail; + using BOOST_MATH_NAMESPACE::quadrature::detail::tanh_sinh_detail; static const char* function = "tanh_sinh<%1%>::integrate"; Real min_complement = tools::min_value() * 4; return m_imp->integrate(f, error, L1, function, min_complement, min_complement, tolerance, levels); } + +template +template +auto tanh_sinh::integrate(const F f, Real a, Real b, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(static_cast(norm(std::declval()(std::declval()))), std::declval()(std::declval())) +{ + BOOST_MATH_STD_USING + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::quadrature::detail::tanh_sinh_detail; + + static const char* function = "tanh_sinh<%1%>::integrate"; + + typedef decltype(std::declval()(std::declval())) result_type; + static_assert(!std::is_integral::value, + "The return type cannot be integral, it must be either a real or complex floating point type."); + if (!(BOOST_MATH_NAMESPACE::isnan)(a) && !(BOOST_MATH_NAMESPACE::isnan)(b)) + { + + // Infinite limits: + if ((a <= -tools::max_value()) && (b >= tools::max_value())) + { + auto u = [&](const Real& t, const Real& tc)->result_type + { + Real t_sq = t*t; + Real inv; + if (t > 0.5f) + inv = 1 / ((2 - tc) * tc); + else if(t < -0.5) + inv = 1 / ((2 + tc) * -tc); + else + inv = 1 / (1 - t_sq); + return f(t*inv)*(1 + t_sq)*inv*inv; + }; + Real limit = sqrt(tools::min_value()) * 4; + return m_imp->integrate(u, zero, norm, error, L1, function, limit, limit, tolerance, levels); + } + + // Right limit is infinite: + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (b >= tools::max_value())) + { + auto u = [&](const Real& t, const Real& tc)->result_type + { + Real z, arg; + if (t > -0.5f) + z = 1 / (t + 1); + else + z = -1 / tc; + if (t < 0.5) + arg = 2 * z + a - 1; + else + arg = a + tc / (2 - tc); + return f(arg)*z*z; + }; + Real left_limit = sqrt(tools::min_value()) * 4; + result_type Q = Real(2) * m_imp->integrate(u, zero, norm, error, L1, function, left_limit, tools::min_value(), tolerance, levels); + if (L1) + { + *L1 *= 2; + } + if (error) + { + *error *= 2; + } + + return Q; + } + + if ((BOOST_MATH_NAMESPACE::isfinite)(b) && (a <= -tools::max_value())) + { + auto v = [&](const Real& t, const Real& tc)->result_type + { + Real z; + if (t > -0.5) + z = 1 / (t + 1); + else + z = -1 / tc; + Real arg; + if (t < 0.5) + arg = 2 * z - 1; + else + arg = tc / (2 - tc); + return f(b - arg) * z * z; + }; + + Real left_limit = sqrt(tools::min_value()) * 4; + result_type Q = Real(2) * m_imp->integrate(v, zero, norm, error, L1, function, left_limit, tools::min_value(), tolerance, levels); + if (L1) + { + *L1 *= 2; + } + if (error) + { + *error *= 2; + } + return Q; + } + + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (BOOST_MATH_NAMESPACE::isfinite)(b)) + { + if (a == b) + { + if (error) *error = Real(0); + if (L1) *L1 = Real(0); + if (levels) *levels = 0; + return zero; + } + if (b < a) + { + return -this->integrate(f, b, a, zero, norm, tolerance, error, L1, levels); + } + Real avg = (a + b)*half(); + Real diff = (b - a)*half(); + Real avg_over_diff_m1 = a / diff; + Real avg_over_diff_p1 = b / diff; + bool have_small_left = fabs(a) < 0.5f; + bool have_small_right = fabs(b) < 0.5f; + Real left_min_complement = float_next(avg_over_diff_m1) - avg_over_diff_m1; + Real min_complement_limit = (std::max)(tools::min_value(), float_next(Real(tools::min_value() / diff))); + if (left_min_complement < min_complement_limit) + left_min_complement = min_complement_limit; + Real right_min_complement = avg_over_diff_p1 - float_prior(avg_over_diff_p1); + if (right_min_complement < min_complement_limit) + right_min_complement = min_complement_limit; + // + // These asserts will fail only if rounding errors on + // type Real have accumulated so much error that it's + // broken our internal logic. Should that prove to be + // a persistent issue, we might need to add a bit of fudge + // factor to move left_min_complement and right_min_complement + // further from the end points of the range. + // + BOOST_MATH_ASSERT((left_min_complement * diff + a) > a); + BOOST_MATH_ASSERT((b - right_min_complement * diff) < b); + auto u = [&](Real z, Real zc)->result_type + { + Real position; + if (z < -0.5) + { + if(have_small_left) + return f(diff * (avg_over_diff_m1 - zc)); + position = a - diff * zc; + } + else if (z > 0.5) + { + if(have_small_right) + return f(diff * (avg_over_diff_p1 - zc)); + position = b - diff * zc; + } + else + position = avg + diff*z; + BOOST_MATH_ASSERT(position != a); + BOOST_MATH_ASSERT(position != b); + return f(position); + }; + result_type Q = diff*m_imp->integrate(u, zero, norm, error, L1, function, left_min_complement, right_min_complement, tolerance, levels); + + if (L1) + { + *L1 *= diff; + } + if (error) + { + *error *= diff; + } + return Q; + } + } + return detail::norm_quadrature_error(zero, policies::raise_domain_error(function, "The domain of integration is not sensible; please check the bounds.", a, Policy()), error, L1, levels); +} + +template +template +auto tanh_sinh::integrate(const F f, Real a, Real b, const decltype(std::declval()(std::declval(), std::declval()))& zero, Norm norm, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(static_cast(norm(std::declval()(std::declval(), std::declval()))), std::declval()(std::declval(), std::declval())) +{ + BOOST_MATH_STD_USING + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::quadrature::detail::tanh_sinh_detail; + + static const char* function = "tanh_sinh<%1%>::integrate"; + + if ((BOOST_MATH_NAMESPACE::isfinite)(a) && (BOOST_MATH_NAMESPACE::isfinite)(b)) + { + if (a == b) + { + if (error) *error = Real(0); + if (L1) *L1 = Real(0); + if (levels) *levels = 0; + return zero; + } + if (b < a) + { + return -this->integrate(f, b, a, zero, norm, tolerance, error, L1, levels); + } + auto u = [&](Real z, Real zc)->decltype(std::declval()(std::declval(), std::declval())) + { + if (z < 0) + return f((a - b) * zc / 2 + a, (b - a) * zc / 2); + else + return f((a - b) * zc / 2 + b, (b - a) * zc / 2); + }; + Real diff = (b - a)*half(); + Real left_min_complement = tools::min_value() * 4; + Real right_min_complement = tools::min_value() * 4; + decltype(std::declval()(std::declval(), std::declval())) Q = diff*m_imp->integrate(u, zero, norm, error, L1, function, left_min_complement, right_min_complement, tolerance, levels); + + if (L1) + { + *L1 *= diff; + } + if (error) + { + *error *= diff; + } + return Q; + } + return detail::norm_quadrature_error(zero, policies::raise_domain_error(function, "The domain of integration is not sensible; please check the bounds.", a, Policy()), error, L1, levels); +} + +template +template +auto tanh_sinh::integrate(const F f, const decltype(std::declval()(std::declval()))& zero, Norm norm, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(static_cast(norm(std::declval()(std::declval()))), std::declval()(std::declval())) +{ + using BOOST_MATH_NAMESPACE::quadrature::detail::tanh_sinh_detail; + static const char* function = "tanh_sinh<%1%>::integrate"; + Real min_complement = tools::epsilon(); + return m_imp->integrate([&](const Real& arg, const Real&) { return f(arg); }, zero, norm, error, L1, function, min_complement, min_complement, tolerance, levels); } + +template +template +auto tanh_sinh::integrate(const F f, const decltype(std::declval()(std::declval(), std::declval()))& zero, Norm norm, Real tolerance, Real* error, Real* L1, std::size_t* levels) const ->decltype(static_cast(norm(std::declval()(std::declval(), std::declval()))), std::declval()(std::declval(), std::declval())) +{ + using BOOST_MATH_NAMESPACE::quadrature::detail::tanh_sinh_detail; + static const char* function = "tanh_sinh<%1%>::integrate"; + Real min_complement = tools::min_value() * 4; + return m_imp->integrate(f, zero, norm, error, L1, function, min_complement, min_complement, tolerance, levels); } } +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/quadrature/trapezoidal.hpp b/include/boost/math/quadrature/trapezoidal.hpp index 8190fb66ae..e6c60fd7bd 100644 --- a/include/boost/math/quadrature/trapezoidal.hpp +++ b/include/boost/math/quadrature/trapezoidal.hpp @@ -15,35 +15,38 @@ #ifndef BOOST_MATH_QUADRATURE_TRAPEZOIDAL_HPP #define BOOST_MATH_QUADRATURE_TRAPEZOIDAL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #include +#include #include #include #include -namespace boost{ namespace math{ namespace quadrature { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { -template +BOOST_MATH_EXPORT template auto trapezoidal(F f, Real a, Real b, Real tol, std::size_t max_refinements, Real* error_estimate, Real* L1, const Policy& pol)->decltype(std::declval()(std::declval())) { static const char* function = "boost::math::quadrature::trapezoidal<%1%>(F, %1%, %1%, %1%)"; using std::abs; - using boost::math::constants::half; + using BOOST_MATH_NAMESPACE::constants::half; // In many math texts, K represents the field of real or complex numbers. // Too bad we can't put blackboard bold into C++ source! typedef decltype(f(a)) K; static_assert(!std::is_integral::value, "The return type cannot be integral, it must be either a real or complex floating point type."); - if (!(boost::math::isfinite)(a)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(a)) { - return static_cast(boost::math::policies::raise_domain_error(function, "Left endpoint of integration must be finite for adaptive trapezoidal integration but got a = %1%.\n", a, pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Left endpoint of integration must be finite for adaptive trapezoidal integration but got a = %1%.\n", a, pol)); } - if (!(boost::math::isfinite)(b)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(b)) { - return static_cast(boost::math::policies::raise_domain_error(function, "Right endpoint of integration must be finite for adaptive trapezoidal integration but got b = %1%.\n", b, pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Right endpoint of integration must be finite for adaptive trapezoidal integration but got b = %1%.\n", b, pol)); } if (a == b) @@ -115,11 +118,108 @@ auto trapezoidal(F f, Real a, Real b, Real tol, std::size_t max_refinements, Rea return static_cast(I1); } -template -auto trapezoidal(F f, Real a, Real b, Real tol = boost::math::tools::root_epsilon(), std::size_t max_refinements = 12, Real* error_estimate = nullptr, Real* L1 = nullptr)->decltype(std::declval()(std::declval())) +BOOST_MATH_EXPORT template +auto trapezoidal(F f, Real a, Real b, Real tol = BOOST_MATH_NAMESPACE::tools::root_epsilon(), std::size_t max_refinements = 12, Real* error_estimate = nullptr, Real* L1 = nullptr)->decltype(std::declval()(std::declval())) +{ + return trapezoidal(f, a, b, tol, max_refinements, error_estimate, L1, BOOST_MATH_NAMESPACE::policies::policy<>()); +} + +BOOST_MATH_EXPORT template +auto trapezoidal(F f, Real a, Real b, const decltype(f(a))& zero, Norm norm, Real tol, std::size_t max_refinements, Real* error_estimate, Real* L1, const Policy& pol)->decltype(static_cast(norm(f(a))), f(a)) +{ + static const char* function = "boost::math::quadrature::trapezoidal<%1%>(F, %1%, %1%, %1%)"; + const auto magnitude = [&](const decltype(f(a))& value) -> Real { return static_cast(norm(value)); }; + using BOOST_MATH_NAMESPACE::constants::half; + // In many math texts, K represents the field of real or complex numbers. + // Too bad we can't put blackboard bold into C++ source! + typedef decltype(f(a)) K; + static_assert(!std::is_integral::value, + "The return type cannot be integral, it must be either a real or complex floating point type."); + if (!(BOOST_MATH_NAMESPACE::isfinite)(a)) + { + return detail::norm_quadrature_error(zero, BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Left endpoint of integration must be finite for adaptive trapezoidal integration but got a = %1%.\n", a, pol), error_estimate, L1); + } + if (!(BOOST_MATH_NAMESPACE::isfinite)(b)) + { + return detail::norm_quadrature_error(zero, BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Right endpoint of integration must be finite for adaptive trapezoidal integration but got b = %1%.\n", b, pol), error_estimate, L1); + } + + if (a == b) + { + if (error_estimate) *error_estimate = Real(0); + if (L1) *L1 = Real(0); + return zero; + } + if(a > b) + { + return -trapezoidal(f, b, a, zero, norm, tol, max_refinements, error_estimate, L1, pol); + } + + + K ya = f(a); + K yb = f(b); + Real h = (b - a)*half(); + K I0 = (ya + yb)*h; + Real IL0 = (magnitude(ya) + magnitude(yb))*h; + + K yh = f(a + h); + K I1 = zero; + I1 = I0*half() + yh*h; + Real IL1 = IL0*half() + magnitude(yh)*h; + + // The recursion is: + // I_k = 1/2 I_{k-1} + 1/2^k \sum_{j=1; j odd, j < 2^k} f(a + j(b-a)/2^k) + std::size_t k = 2; + // We want to go through at least 5 levels so we have sampled the function at least 20 times. + // Otherwise, we could terminate prematurely and miss essential features. + // This is of course possible anyway, but 20 samples seems to be a reasonable compromise. + Real error = magnitude(I0 - I1); + // I take k < 5, rather than k < 4, or some other smaller minimum number, + // because I hit a truly exceptional bug where the k = 2 and k =3 refinement were bitwise equal, + // but the quadrature had not yet converged. + while (k < 5 || (k < max_refinements && error > tol*IL1) ) + { + I0 = I1; + IL0 = IL1; + + I1 = I0*half(); + IL1 = IL0*half(); + std::size_t p = static_cast(1u) << k; + h *= half(); + K sum = zero; + Real absum = 0; + + for(std::size_t j = 1; j < p; j += 2) + { + K y = f(a + j*h); + sum += y; + absum += magnitude(y); + } + + I1 += sum*h; + IL1 += absum*h; + ++k; + error = magnitude(I0 - I1); + } + + if (error_estimate) + { + *error_estimate = error; + } + + if (L1) + { + *L1 = IL1; + } + + return static_cast(I1); +} + +BOOST_MATH_EXPORT template +auto trapezoidal(F f, Real a, Real b, const decltype(f(a))& zero, Norm norm, Real tol = BOOST_MATH_NAMESPACE::tools::root_epsilon(), std::size_t max_refinements = 12, Real* error_estimate = nullptr, Real* L1 = nullptr)->decltype(static_cast(norm(f(a))), f(a)) { - return trapezoidal(f, a, b, tol, max_refinements, error_estimate, L1, boost::math::policies::policy<>()); + return trapezoidal(f, a, b, zero, norm, tol, max_refinements, error_estimate, L1, BOOST_MATH_NAMESPACE::policies::policy<>()); } -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/quadrature/van_den_bos_unit_square.hpp b/include/boost/math/quadrature/van_den_bos_unit_square.hpp new file mode 100644 index 0000000000..aeb6430b0c --- /dev/null +++ b/include/boost/math/quadrature/van_den_bos_unit_square.hpp @@ -0,0 +1,269 @@ +// Copyright 2026 Nicholas Thompson and Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_MATH_QUADRATURE_VAN_DEN_BOS_UNIT_SQUARE_HPP +#define BOOST_MATH_QUADRATURE_VAN_DEN_BOS_UNIT_SQUARE_HPP + +#include + +#ifdef BOOST_MATH_NO_CXX17_IF_CONSTEXPR +#error "The header requires C++17 or later." +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_MATH_INSTRUMENT +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { + +namespace detail { + +struct van_den_bos_unit_square_level_view +{ + std::array const* node_indices; + double const* weights; + std::size_t size; + + std::array point(const std::size_t index) const + { + const std::array& node = node_indices[index]; + return {{ + van_den_bos_unit_square_coordinates[node[0]], + van_den_bos_unit_square_coordinates[node[1]]}}; + } +}; + +inline van_den_bos_unit_square_level_view +van_den_bos_unit_square_level(const std::size_t level) +{ + if (level >= van_den_bos_unit_square_level_count) + { + BOOST_MATH_THROW_EXCEPTION(std::out_of_range( + "van_den_bos_unit_square: requested level exceeds " + "the precomputed hierarchy.")); + } + + return { + van_den_bos_unit_square_node_indices.data(), + van_den_bos_unit_square_weights[level], + van_den_bos_unit_square_sizes[level]}; +} + +} // namespace detail + +/* + * Adaptive positive cubature on the reference square [0,1]^2. + * + * The quadrature nodes are a strictly nested immutable hierarchy generated + * offline in higher precision. The generator starts from tensor-product + * endpoint-free Fejer type-II rules for continuous uniform (Lebesgue) + * measure and applies protected-node van-den-Bos reduction. This differs + * from the equal-weight + * empirical sample measure used in the paper, while retaining its positive + * nullspace reduction and nested-node construction. + * + * For a parallelogram, the caller is responsible for the affine map from + * [0,1]^2 to physical coordinates and for multiplying by its Jacobian. + * The rules contain no boundary nodes. + * + * Runtime performs no rule construction and mutates no shared state. + * Independent invocations are therefore thread-safe. + * Convergence requires two consecutive adjacent-level differences to satisfy + * the requested tolerance, guarding against an isolated cancellation. + */ +template +auto van_den_bos_unit_square( + F const& f, + const double tolerance, + double* error_estimate = nullptr, + double* L1 = nullptr, + std::size_t* evaluations = nullptr) + -> decltype(f(std::declval(), std::declval())) +{ + using std::abs; + using result_type = decltype(f(std::declval(), std::declval())); + + static_assert(!std::is_integral::value, + "The return type cannot be integral, it must be either a real or " + "complex floating point type."); + + using magnitude_type = std::decay_t()))>; + + if (!(tolerance > 0)) + { + BOOST_MATH_THROW_EXCEPTION(std::domain_error( + "van_den_bos_unit_square: tolerance must be positive.")); + } + + std::vector orbit_sums; + std::vector orbit_absolute_sums; + + result_type previous = result_type(0); + result_type current = result_type(0); + + double current_l1 = 0; + double current_error = + (std::numeric_limits::infinity)(); + + std::size_t evaluation_count = 0; + bool have_previous = false; + bool previous_estimate_satisfied = false; + + for (std::size_t level_index = 0; + level_index < detail::van_den_bos_unit_square_level_count; + ++level_index) + { + const detail::van_den_bos_unit_square_level_view level = + detail::van_den_bos_unit_square_level(level_index); + + // Generator invariant: the previous level is an exact prefix. + // Therefore only the new suffix requires function evaluations. + orbit_sums.reserve(level.size); + orbit_absolute_sums.reserve(level.size); + while (orbit_sums.size() < level.size) + { + const std::array point = + level.point(orbit_sums.size()); + result_type orbit_sum = result_type(0); + magnitude_type orbit_absolute_sum = magnitude_type(0); + const auto accumulate = [&](double x, double y) + { + const result_type value = f(x, y); + orbit_sum += value; + orbit_absolute_sum += abs(value); + ++evaluation_count; + }; + + const double x = point[0]; + const double y = point[1]; + if (x == 0.5) + { + accumulate(x, y); + if (y != 0.5) + { + accumulate(y, x); + accumulate(x, 1 - y); + accumulate(1 - y, x); + } + } + else if (x == y) + { + accumulate(x, x); + accumulate(1 - x, x); + accumulate(x, 1 - x); + accumulate(1 - x, 1 - x); + } + else + { + accumulate(x, y); + accumulate(y, x); + accumulate(1 - x, y); + accumulate(y, 1 - x); + accumulate(x, 1 - y); + accumulate(1 - y, x); + accumulate(1 - x, 1 - y); + accumulate(1 - y, 1 - x); + } + orbit_sums.push_back(orbit_sum); + orbit_absolute_sums.push_back(orbit_absolute_sum); + } + + current = result_type(0); + current_l1 = 0; + + for (std::size_t j = 0; j < level.size; ++j) + { + current += level.weights[j] * orbit_sums[j]; + current_l1 += level.weights[j] * orbit_absolute_sums[j]; + } + +#ifdef BOOST_MATH_INSTRUMENT + std::cout + << std::setprecision( + std::numeric_limits::max_digits10) + << "VDB_LEVEL" + << ",level=" << level_index + << ",nodes=" << level.size + << ",evaluations=" << evaluation_count + << ",value=" << current; +#endif + + if (have_previous) + { + const double delta = abs(current - previous); + const double scale = + (std::max)(1.0, static_cast(abs(current))); + + // Paper Sec. 2.3: adjacent nested-rule difference. The floor + // prevents reporting a meaningless zero below the accumulator's + // precision. + const double roundoff_floor = + 8 * static_cast( + (std::numeric_limits::epsilon)()) * scale; + current_error = (std::max)(delta, roundoff_floor); + +#ifdef BOOST_MATH_INSTRUMENT + std::cout + << ",delta=" << delta + << ",error_estimate=" << current_error + << '\n'; +#endif + + const bool estimate_satisfied = + current_error <= tolerance * scale; + + // One accidentally small adjacent difference is not reliable for + // non-monotone convergence. Require confirmation by the next + // nested rule before stopping. + if (estimate_satisfied && previous_estimate_satisfied) + { + break; + } + previous_estimate_satisfied = estimate_satisfied; + } + else + { +#ifdef BOOST_MATH_INSTRUMENT + std::cout << ",delta=nan,error_estimate=nan\n"; +#endif + have_previous = true; + } + + previous = current; + } + + if (error_estimate) + { + *error_estimate = current_error; + } + if (L1) + { + *L1 = current_l1; + } + if (evaluations) + { + *evaluations = evaluation_count; + } + + return current; +} + +} BOOST_MATH_NAMESPACE_END + +#endif diff --git a/include/boost/math/quadrature/wavelet_transforms.hpp b/include/boost/math/quadrature/wavelet_transforms.hpp index 7c811d5caf..60016ee4c7 100644 --- a/include/boost/math/quadrature/wavelet_transforms.hpp +++ b/include/boost/math/quadrature/wavelet_transforms.hpp @@ -9,9 +9,9 @@ #include #include -namespace boost::math::quadrature { +BOOST_MATH_NAMESPACE_BEGIN namespace quadrature { -template +BOOST_MATH_EXPORT template class daubechies_wavelet_transform { public: @@ -19,7 +19,7 @@ class daubechies_wavelet_transform int max_refinements = 12) : f_{f}, psi_(grid_refinements), tol_{tol}, max_refinements_{max_refinements} {} - daubechies_wavelet_transform(F f, boost::math::daubechies_wavelet wavelet, Real tol = 100*std::numeric_limits::epsilon(), + daubechies_wavelet_transform(F f, BOOST_MATH_NAMESPACE::daubechies_wavelet wavelet, Real tol = 100*std::numeric_limits::epsilon(), int max_refinements = 12) : f_{f}, psi_{wavelet}, tol_{tol}, max_refinements_{max_refinements} {} @@ -27,7 +27,7 @@ class daubechies_wavelet_transform { using std::sqrt; using std::abs; - using boost::math::quadrature::trapezoidal; + using BOOST_MATH_NAMESPACE::quadrature::trapezoidal; auto g = [&] (Real u) { return f_(s*u+t)*psi_(u); }; @@ -37,11 +37,11 @@ class daubechies_wavelet_transform private: F f_; - boost::math::daubechies_wavelet psi_; + BOOST_MATH_NAMESPACE::daubechies_wavelet psi_; Real tol_; int max_refinements_; }; -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/quaternion.hpp b/include/boost/math/quaternion.hpp index 831dd92bef..10d7f5df23 100644 --- a/include/boost/math/quaternion.hpp +++ b/include/boost/math/quaternion.hpp @@ -12,22 +12,25 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include // for the "<<" operator +#endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include // for the "<<" and ">>" operators #include // for the "<<" operator +#endif #include // for the Sinus cardinal #include // for the Hyperbolic Sinus cardinal #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -46,20 +49,18 @@ namespace boost struct is_trivial_arithmetic_type : public is_trivial_arithmetic_type_imp::type {}; } -#ifndef BOOST_MATH_NO_CXX14_CONSTEXPR namespace constexpr_detail { template - constexpr void swap(T& a, T& b) + BOOST_MATH_CXX14_CONSTEXPR void swap(T& a, T& b) { T t(a); a = b; b = t; } } -#endif - template + BOOST_MATH_EXPORT template class quaternion { public: @@ -177,11 +178,7 @@ namespace boost BOOST_MATH_CXX14_CONSTEXPR void swap(quaternion& o) { -#ifndef BOOST_MATH_NO_CXX14_CONSTEXPR using constexpr_detail::swap; -#else - using std::swap; -#endif swap(a, o.a); swap(b, o.b); swap(c, o.c); @@ -424,84 +421,84 @@ namespace boost }; // swap: -template +BOOST_MATH_EXPORT template BOOST_MATH_CXX14_CONSTEXPR void swap(quaternion& a, quaternion& b) { a.swap(b); } // operator+ -template +BOOST_MATH_EXPORT template inline constexpr typename std::enable_if::value, quaternion >::type operator + (const quaternion& a, const T2& b) { return quaternion(static_cast(a.R_component_1() + b), a.R_component_2(), a.R_component_3(), a.R_component_4()); } -template +BOOST_MATH_EXPORT template inline constexpr typename std::enable_if::value, quaternion >::type operator + (const T1& a, const quaternion& b) { return quaternion(static_cast(b.R_component_1() + a), b.R_component_2(), b.R_component_3(), b.R_component_4()); } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR typename std::enable_if::value, quaternion >::type operator + (const quaternion& a, const std::complex& b) { return quaternion(a.R_component_1() + std::real(b), a.R_component_2() + std::imag(b), a.R_component_3(), a.R_component_4()); } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR typename std::enable_if::value, quaternion >::type operator + (const std::complex& a, const quaternion& b) { return quaternion(b.R_component_1() + std::real(a), b.R_component_2() + std::imag(a), b.R_component_3(), b.R_component_4()); } -template +BOOST_MATH_EXPORT template inline constexpr quaternion operator + (const quaternion& a, const quaternion& b) { return quaternion(a.R_component_1() + b.R_component_1(), a.R_component_2() + b.R_component_2(), a.R_component_3() + b.R_component_3(), a.R_component_4() + b.R_component_4()); } // operator- -template +BOOST_MATH_EXPORT template inline constexpr typename std::enable_if::value, quaternion >::type operator - (const quaternion& a, const T2& b) { return quaternion(static_cast(a.R_component_1() - b), a.R_component_2(), a.R_component_3(), a.R_component_4()); } -template +BOOST_MATH_EXPORT template inline constexpr typename std::enable_if::value, quaternion >::type operator - (const T1& a, const quaternion& b) { return quaternion(static_cast(a - b.R_component_1()), -b.R_component_2(), -b.R_component_3(), -b.R_component_4()); } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR typename std::enable_if::value, quaternion >::type operator - (const quaternion& a, const std::complex& b) { return quaternion(a.R_component_1() - std::real(b), a.R_component_2() - std::imag(b), a.R_component_3(), a.R_component_4()); } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR typename std::enable_if::value, quaternion >::type operator - (const std::complex& a, const quaternion& b) { return quaternion(std::real(a) - b.R_component_1(), std::imag(a) - b.R_component_2(), -b.R_component_3(), -b.R_component_4()); } -template +BOOST_MATH_EXPORT template inline constexpr quaternion operator - (const quaternion& a, const quaternion& b) { return quaternion(a.R_component_1() - b.R_component_1(), a.R_component_2() - b.R_component_2(), a.R_component_3() - b.R_component_3(), a.R_component_4() - b.R_component_4()); } // operator* -template +BOOST_MATH_EXPORT template inline constexpr typename std::enable_if::value, quaternion >::type operator * (const quaternion& a, const T2& b) { return quaternion(static_cast(a.R_component_1() * b), a.R_component_2() * b, a.R_component_3() * b, a.R_component_4() * b); } -template +BOOST_MATH_EXPORT template inline constexpr typename std::enable_if::value, quaternion >::type operator * (const T1& a, const quaternion& b) { return quaternion(static_cast(a * b.R_component_1()), a * b.R_component_2(), a * b.R_component_3(), a * b.R_component_4()); } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR typename std::enable_if::value, quaternion >::type operator * (const quaternion& a, const std::complex& b) { @@ -509,7 +506,7 @@ operator * (const quaternion& a, const std::complex& b) result *= b; return result; } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR typename std::enable_if::value, quaternion >::type operator * (const std::complex& a, const quaternion& b) { @@ -517,7 +514,7 @@ operator * (const std::complex& a, const quaternion& b) result *= b; return result; } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator * (const quaternion& a, const quaternion& b) { quaternion result(a); @@ -526,13 +523,13 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator * (const quaternion& } // operator/ -template +BOOST_MATH_EXPORT template inline constexpr typename std::enable_if::value, quaternion >::type operator / (const quaternion& a, const T2& b) { return quaternion(a.R_component_1() / b, a.R_component_2() / b, a.R_component_3() / b, a.R_component_4() / b); } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR typename std::enable_if::value, quaternion >::type operator / (const T1& a, const quaternion& b) { @@ -540,7 +537,7 @@ operator / (const T1& a, const quaternion& b) result /= b; return result; } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR typename std::enable_if::value, quaternion >::type operator / (const quaternion& a, const std::complex& b) { @@ -548,7 +545,7 @@ operator / (const quaternion& a, const std::complex& b) result /= b; return result; } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR typename std::enable_if::value, quaternion >::type operator / (const std::complex& a, const quaternion& b) { @@ -556,7 +553,7 @@ operator / (const std::complex& a, const quaternion& b) result /= b; return result; } -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& a, const quaternion& b) { quaternion result(a); @@ -565,21 +562,21 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline constexpr const quaternion& operator + (quaternion const & q) { return q; } - template + BOOST_MATH_EXPORT template inline constexpr quaternion operator - (quaternion const & q) { return(quaternion(-q.R_component_1(),-q.R_component_2(),-q.R_component_3(),-q.R_component_4())); } - template + BOOST_MATH_EXPORT template inline constexpr typename std::enable_if::value, bool>::type operator == (R const & lhs, quaternion const & rhs) { return ( @@ -591,14 +588,14 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline constexpr typename std::enable_if::value, bool>::type operator == (quaternion const & lhs, R const & rhs) { return rhs == lhs; } - template + BOOST_MATH_EXPORT template inline constexpr bool operator == (::std::complex const & lhs, quaternion const & rhs) { return ( @@ -610,14 +607,14 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline constexpr bool operator == (quaternion const & lhs, ::std::complex const & rhs) { return rhs == lhs; } - template + BOOST_MATH_EXPORT template inline constexpr bool operator == (quaternion const & lhs, quaternion const & rhs) { return ( @@ -639,7 +636,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& // a // (a), (a,b), (a,b,c), (a,b,c,d) // (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b),(c,d)) - template + BOOST_MATH_EXPORT template ::std::basic_istream & operator >> ( ::std::basic_istream & is, quaternion & q) { @@ -858,7 +855,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template ::std::basic_ostream & operator << ( ::std::basic_ostream & os, quaternion const & q) { @@ -879,20 +876,20 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& // values - template + BOOST_MATH_EXPORT template inline constexpr T real(quaternion const & q) { return(q.real()); } - template + BOOST_MATH_EXPORT template inline constexpr quaternion unreal(quaternion const & q) { return(q.unreal()); } - template + BOOST_MATH_EXPORT template inline T sup(quaternion const & q) { using ::std::abs; @@ -900,7 +897,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline T l1(quaternion const & q) { using ::std::abs; @@ -908,7 +905,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline T abs(quaternion const & q) { using ::std::abs; @@ -943,14 +940,14 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& // Note: This is the Cayley norm, not the Euclidean norm... - template + BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR T norm(quaternionconst & q) { return(real(q*conj(q))); } - template + BOOST_MATH_EXPORT template inline constexpr quaternion conj(quaternion const & q) { return(quaternion( +q.R_component_1(), @@ -960,7 +957,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline quaternion spherical( T const & rho, T const & theta, T const & phi1, @@ -991,7 +988,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline quaternion semipolar( T const & rho, T const & alpha, T const & theta1, @@ -1009,7 +1006,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline quaternion multipolar( T const & rho1, T const & theta1, T const & rho2, @@ -1027,7 +1024,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline quaternion cylindrospherical( T const & t, T const & radius, T const & longitude, @@ -1046,7 +1043,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline quaternion cylindrical(T const & r, T const & angle, T const & h1, @@ -1066,13 +1063,13 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& // (please see the documentation) - template + BOOST_MATH_EXPORT template inline quaternion exp(quaternion const & q) { using ::std::exp; using ::std::cos; - using ::boost::math::sinc_pi; + using ::BOOST_MATH_NAMESPACE::sinc_pi; T u = exp(real(q)); @@ -1086,14 +1083,14 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline quaternion cos(quaternion const & q) { using ::std::sin; using ::std::cos; using ::std::cosh; - using ::boost::math::sinhc_pi; + using ::BOOST_MATH_NAMESPACE::sinhc_pi; T z = abs(unreal(q)); @@ -1105,14 +1102,14 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline quaternion sin(quaternion const & q) { using ::std::sin; using ::std::cos; using ::std::cosh; - using ::boost::math::sinhc_pi; + using ::BOOST_MATH_NAMESPACE::sinhc_pi; T z = abs(unreal(q)); @@ -1124,35 +1121,35 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& } - template + BOOST_MATH_EXPORT template inline quaternion tan(quaternion const & q) { return(sin(q)/cos(q)); } - template + BOOST_MATH_EXPORT template inline quaternion cosh(quaternion const & q) { return((exp(+q)+exp(-q))/static_cast(2)); } - template + BOOST_MATH_EXPORT template inline quaternion sinh(quaternion const & q) { return((exp(+q)-exp(-q))/static_cast(2)); } - template + BOOST_MATH_EXPORT template inline quaternion tanh(quaternion const & q) { return(sinh(q)/cosh(q)); } - template + BOOST_MATH_EXPORT template quaternion pow(quaternion const & q, int n) { @@ -1184,7 +1181,6 @@ inline BOOST_MATH_CXX14_CONSTEXPR quaternion operator / (const quaternion& return(pow(quaternion(static_cast(1))/q,-n)); } } - } -} + BOOST_MATH_NAMESPACE_END #endif /* BOOST_QUATERNION_HPP */ diff --git a/include/boost/math/special_functions.hpp b/include/boost/math/special_functions.hpp index d3aa95c5c1..3275ab3d2b 100644 --- a/include/boost/math/special_functions.hpp +++ b/include/boost/math/special_functions.hpp @@ -79,6 +79,7 @@ #include #include #include +#include #ifndef BOOST_MATH_NO_EXCEPTIONS #include #endif diff --git a/include/boost/math/special_functions/acosh.hpp b/include/boost/math/special_functions/acosh.hpp index 63e8e2dff0..9a0c5de581 100644 --- a/include/boost/math/special_functions/acosh.hpp +++ b/include/boost/math/special_functions/acosh.hpp @@ -15,7 +15,9 @@ #pragma once #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include @@ -25,10 +27,7 @@ // This is the inverse of the hyperbolic cosine function. -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template @@ -36,7 +35,7 @@ namespace boost { BOOST_MATH_STD_USING - if((x < 1) || (boost::math::isnan)(x)) + if((x < 1) || (BOOST_MATH_NAMESPACE::isnan)(x)) { return policies::raise_domain_error("boost::math::acosh<%1%>(%1%)", "acosh requires x >= 1, but got x = %1%.", x, pol); } @@ -53,7 +52,7 @@ namespace boost // This is just a rearrangement of the standard form below // devised to minimise loss of precision when x ~ 1: T y = x - 1; - return boost::math::log1p(y + sqrt(y * y + 2 * y), pol); + return BOOST_MATH_NAMESPACE::log1p(y + sqrt(y * y + 2 * y), pol); } else { @@ -73,7 +72,7 @@ namespace boost } } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type acosh(T x, const Policy&) { typedef typename tools::promote_args::type result_type; @@ -88,14 +87,13 @@ namespace boost detail::acosh_imp(static_cast(x), forwarding_policy()), "boost::math::acosh<%1%>(%1%)"); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type acosh(T x) { - return boost::math::acosh(x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::acosh(x, policies::policy<>()); } - } -} + BOOST_MATH_NAMESPACE_END #endif /* BOOST_ACOSH_HPP */ diff --git a/include/boost/math/special_functions/airy.hpp b/include/boost/math/special_functions/airy.hpp index 4219e5286e..746c6864eb 100644 --- a/include/boost/math/special_functions/airy.hpp +++ b/include/boost/math/special_functions/airy.hpp @@ -17,35 +17,126 @@ #include #include #include +#include #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ +// Whether Ai, Bi and their derivatives at zero are available as correctly rounded constants: +template +BOOST_MATH_GPU_ENABLED constexpr bool airy_has_exact_zero_values() +{ + return BOOST_MATH_NAMESPACE::numeric_limits::radix != 10 && BOOST_MATH_NAMESPACE::tools::digits() <= 390; +} + +// Ai(0), Bi(0), Ai'(0) and Bi'(0). Types of up to 390 bits get constants to 120 digits (from Arb), +// evaluating them via tgamma loses a few bits as the arguments 1/3 and 2/3 are not exact: +template +BOOST_MATH_GPU_ENABLED T airy_ai_zero_value(const Policy& pol) +{ + BOOST_MATH_STD_USING + BOOST_MATH_IF_CONSTEXPR(airy_has_exact_zero_values()) + return BOOST_MATH_BIG_CONSTANT(T, 390, 0.355028053887817239260063186004183176397979174199177240583326510300810042450126712957174246054040271688420448730349495840); + else + return 1 / (pow(T(3), constants::twothirds()) * BOOST_MATH_NAMESPACE::tgamma(constants::twothirds(), pol)); +} + +template +BOOST_MATH_GPU_ENABLED T airy_bi_zero_value(const Policy& pol) +{ + BOOST_MATH_STD_USING + BOOST_MATH_IF_CONSTEXPR(airy_has_exact_zero_values()) + return BOOST_MATH_BIG_CONSTANT(T, 390, 0.614926627446000735150922369093613553594728188648596505040878753014296519305520640529387343345267569240728438782242516725); + else + return 1 / (sqrt(BOOST_MATH_NAMESPACE::cbrt(T(3), pol)) * BOOST_MATH_NAMESPACE::tgamma(constants::twothirds(), pol)); +} + +// Returns -Ai'(0): +template +BOOST_MATH_GPU_ENABLED T airy_ai_prime_zero_value(const Policy& pol) +{ + BOOST_MATH_STD_USING + BOOST_MATH_IF_CONSTEXPR(airy_has_exact_zero_values()) + return BOOST_MATH_BIG_CONSTANT(T, 390, 0.258819403792806798405183560189203963479091138354934582210001813856102772676790280654196405827275384313371193211789133381); + else + return 1 / (BOOST_MATH_NAMESPACE::cbrt(T(3), pol) * BOOST_MATH_NAMESPACE::tgamma(constants::third(), pol)); +} + +template +BOOST_MATH_GPU_ENABLED T airy_bi_prime_zero_value(const Policy& pol) +{ + BOOST_MATH_STD_USING + BOOST_MATH_IF_CONSTEXPR(airy_has_exact_zero_values()) + return BOOST_MATH_BIG_CONSTANT(T, 390, 0.448288357353826357914823710398828390866226799212262061082808778372330755009780647185046574400736362878496329249031699774); + else + return sqrt(BOOST_MATH_NAMESPACE::cbrt(T(3), pol)) / BOOST_MATH_NAMESPACE::tgamma(constants::third(), pol); +} + +// Terms of the Maclaurin series of Ai and Bi, which are combinations of +// f(x) = 1 + x^3 / 6 + ..., g(x) = x + x^4 / 12 + ... and their derivatives +// f'(x) = x^2 / 2 + ..., g'(x) = 1 + x^3 / 3 + ... +// with each term being the previous one times x^3 / ((3k + a)(3k + b)): +// +template +struct airy_maclaurin_series +{ + typedef T result_type; + BOOST_MATH_GPU_ENABLED airy_maclaurin_series(T first, T x, int a_, int b_) + : term(first), x3(x * x * x), a(a_), b(b_), k(0) {} + BOOST_MATH_GPU_ENABLED T operator()() + { + T result = term; + ++k; + term *= x3 / (T(3 * k + a) * T(3 * k + b)); + return result; + } +private: + T term, x3; + int a, b, k; +}; + +template +BOOST_MATH_GPU_ENABLED T airy_maclaurin_sum(T first, T x, int a, int b, const Policy& pol) +{ + airy_maclaurin_series series(first, x, a, b); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + T result = tools::sum_series(series, policies::get_epsilon(), max_iter); + policies::check_series_iterations("boost::math::airy<%1%>(%1%)", max_iter, pol); + return result; +} + +template +BOOST_MATH_GPU_ENABLED T airy_f(T x, const Policy& pol) { return airy_maclaurin_sum(T(1), x, -1, 0, pol); } +template +BOOST_MATH_GPU_ENABLED T airy_g(T x, const Policy& pol) { return airy_maclaurin_sum(x, x, 0, 1, pol); } +template +BOOST_MATH_GPU_ENABLED T airy_f_prime(T x, const Policy& pol) { return airy_maclaurin_sum(T(x * x / 2), x, 0, 2, pol); } +template +BOOST_MATH_GPU_ENABLED T airy_g_prime(T x, const Policy& pol) { return airy_maclaurin_sum(T(1), x, -2, 0, pol); } + template BOOST_MATH_GPU_ENABLED T airy_ai_imp(T x, const Policy& pol) { BOOST_MATH_STD_USING + if(x > -3 && x < 0.5f) + { + return airy_ai_zero_value(pol) * airy_f(x, pol) - airy_ai_prime_zero_value(pol) * airy_g(x, pol); + } + if(x < 0) { T p = (-x * sqrt(-x) * 2) / 3; T v = T(1) / 3; - T j1 = boost::math::cyl_bessel_j(v, p, pol); - T j2 = boost::math::cyl_bessel_j(-v, p, pol); + T j1 = BOOST_MATH_NAMESPACE::cyl_bessel_j(v, p, pol); + T j2 = BOOST_MATH_NAMESPACE::cyl_bessel_j(-v, p, pol); T ai = sqrt(-x) * (j1 + j2) / 3; //T bi = sqrt(-x / 3) * (j2 - j1); return ai; } - else if(fabs(x * x * x) / 6 < tools::epsilon()) - { - T tg = boost::math::tgamma(constants::twothirds(), pol); - T ai = 1 / (pow(T(3), constants::twothirds()) * tg); - //T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg); - return ai; - } else { T p = 2 * x * sqrt(x) / 3; @@ -56,7 +147,7 @@ BOOST_MATH_GPU_ENABLED T airy_ai_imp(T x, const Policy& pol) // Note that although we can calculate ai from j1 and j2, the accuracy is horrible // as we're subtracting two very large values, so use the Bessel K relation instead: // - T ai = cyl_bessel_k(v, p, pol) * sqrt(x / 3) / boost::math::constants::pi(); //sqrt(x) * (j1 - j2) / 3; + T ai = cyl_bessel_k(v, p, pol) * sqrt(x / 3) / BOOST_MATH_NAMESPACE::constants::pi(); //sqrt(x) * (j1 - j2) / 3; //T bi = sqrt(x / 3) * (j1 + j2); return ai; } @@ -67,29 +158,27 @@ BOOST_MATH_GPU_ENABLED T airy_bi_imp(T x, const Policy& pol) { BOOST_MATH_STD_USING + if(x > -3 && x < 8) + { + return airy_bi_zero_value(pol) * airy_f(x, pol) + airy_bi_prime_zero_value(pol) * airy_g(x, pol); + } + if(x < 0) { T p = (-x * sqrt(-x) * 2) / 3; T v = T(1) / 3; - T j1 = boost::math::cyl_bessel_j(v, p, pol); - T j2 = boost::math::cyl_bessel_j(-v, p, pol); + T j1 = BOOST_MATH_NAMESPACE::cyl_bessel_j(v, p, pol); + T j2 = BOOST_MATH_NAMESPACE::cyl_bessel_j(-v, p, pol); //T ai = sqrt(-x) * (j1 + j2) / 3; T bi = sqrt(-x / 3) * (j2 - j1); return bi; } - else if(fabs(x * x * x) / 6 < tools::epsilon()) - { - T tg = boost::math::tgamma(constants::twothirds(), pol); - //T ai = 1 / (pow(T(3), constants::twothirds()) * tg); - T bi = 1 / (sqrt(boost::math::cbrt(T(3), pol)) * tg); - return bi; - } else { T p = 2 * x * sqrt(x) / 3; T v = T(1) / 3; - T j1 = boost::math::cyl_bessel_i(-v, p, pol); - T j2 = boost::math::cyl_bessel_i(v, p, pol); + T j1 = BOOST_MATH_NAMESPACE::cyl_bessel_i(-v, p, pol); + T j2 = BOOST_MATH_NAMESPACE::cyl_bessel_i(v, p, pol); T bi = sqrt(x / 3) * (j1 + j2); return bi; } @@ -100,21 +189,20 @@ BOOST_MATH_GPU_ENABLED T airy_ai_prime_imp(T x, const Policy& pol) { BOOST_MATH_STD_USING + if(x > -3 && x < 0.5f) + { + return airy_ai_zero_value(pol) * airy_f_prime(x, pol) - airy_ai_prime_zero_value(pol) * airy_g_prime(x, pol); + } + if(x < 0) { T p = (-x * sqrt(-x) * 2) / 3; T v = T(2) / 3; - T j1 = boost::math::cyl_bessel_j(v, p, pol); - T j2 = boost::math::cyl_bessel_j(-v, p, pol); + T j1 = BOOST_MATH_NAMESPACE::cyl_bessel_j(v, p, pol); + T j2 = BOOST_MATH_NAMESPACE::cyl_bessel_j(-v, p, pol); T aip = -x * (j1 - j2) / 3; return aip; } - else if(fabs(x * x) / 2 < tools::epsilon()) - { - T tg = boost::math::tgamma(constants::third(), pol); - T aip = 1 / (boost::math::cbrt(T(3), pol) * tg); - return -aip; - } else { T p = 2 * x * sqrt(x) / 3; @@ -125,7 +213,7 @@ BOOST_MATH_GPU_ENABLED T airy_ai_prime_imp(T x, const Policy& pol) // Note that although we can calculate ai from j1 and j2, the accuracy is horrible // as we're subtracting two very large values, so use the Bessel K relation instead: // - T aip = -cyl_bessel_k(v, p, pol) * x / (boost::math::constants::root_three() * boost::math::constants::pi()); + T aip = -cyl_bessel_k(v, p, pol) * x / (BOOST_MATH_NAMESPACE::constants::root_three() * BOOST_MATH_NAMESPACE::constants::pi()); return aip; } } @@ -135,28 +223,27 @@ BOOST_MATH_GPU_ENABLED T airy_bi_prime_imp(T x, const Policy& pol) { BOOST_MATH_STD_USING + if(x > -3 && x < 8) + { + return airy_bi_zero_value(pol) * airy_f_prime(x, pol) + airy_bi_prime_zero_value(pol) * airy_g_prime(x, pol); + } + if(x < 0) { T p = (-x * sqrt(-x) * 2) / 3; T v = T(2) / 3; - T j1 = boost::math::cyl_bessel_j(v, p, pol); - T j2 = boost::math::cyl_bessel_j(-v, p, pol); + T j1 = BOOST_MATH_NAMESPACE::cyl_bessel_j(v, p, pol); + T j2 = BOOST_MATH_NAMESPACE::cyl_bessel_j(-v, p, pol); T aip = -x * (j1 + j2) / constants::root_three(); return aip; } - else if(fabs(x * x) / 2 < tools::epsilon()) - { - T tg = boost::math::tgamma(constants::third(), pol); - T bip = sqrt(boost::math::cbrt(T(3), pol)) / tg; - return bip; - } else { T p = 2 * x * sqrt(x) / 3; T v = T(2) / 3; - T j1 = boost::math::cyl_bessel_i(-v, p, pol); - T j2 = boost::math::cyl_bessel_i(v, p, pol); - T aip = x * (j1 + j2) / boost::math::constants::root_three(); + T j1 = BOOST_MATH_NAMESPACE::cyl_bessel_i(-v, p, pol); + T j2 = BOOST_MATH_NAMESPACE::cyl_bessel_i(v, p, pol); + T aip = x * (j1 + j2) / BOOST_MATH_NAMESPACE::constants::root_three(); return aip; } } @@ -181,7 +268,7 @@ BOOST_MATH_GPU_ENABLED T airy_ai_zero_imp(int m, const Policy& pol) } // Set up the initial guess for the upcoming root-finding. - const T guess_root = boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess(m, pol); + const T guess_root = BOOST_MATH_NAMESPACE::detail::airy_zero::airy_ai_zero_detail::initial_guess(m, pol); // Select the maximum allowed iterations based on the number // of decimal digits in the numeric type T, being at least 12. @@ -201,8 +288,8 @@ BOOST_MATH_GPU_ENABLED T airy_ai_zero_imp(int m, const Policy& pol) // Perform the root-finding using Newton-Raphson iteration from Boost.Math. const T am = - boost::math::tools::newton_raphson_iterate( - boost::math::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime(pol), + BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate( + BOOST_MATH_NAMESPACE::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime(pol), guess_root, T(guess_root - tolerance), T(guess_root + tolerance), @@ -233,7 +320,7 @@ BOOST_MATH_GPU_ENABLED T airy_bi_zero_imp(int m, const Policy& pol) "The requested rank of the zero is %1%, but must be 1 or more !", static_cast(m), pol); } // Set up the initial guess for the upcoming root-finding. - const T guess_root = boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess(m, pol); + const T guess_root = BOOST_MATH_NAMESPACE::detail::airy_zero::airy_bi_zero_detail::initial_guess(m, pol); // Select the maximum allowed iterations based on the number // of decimal digits in the numeric type T, being at least 12. @@ -253,8 +340,8 @@ BOOST_MATH_GPU_ENABLED T airy_bi_zero_imp(int m, const Policy& pol) // Perform the root-finding using Newton-Raphson iteration from Boost.Math. const T bm = - boost::math::tools::newton_raphson_iterate( - boost::math::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime(pol), + BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate( + BOOST_MATH_NAMESPACE::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime(pol), guess_root, T(guess_root - tolerance), T(guess_root + tolerance), @@ -268,7 +355,7 @@ BOOST_MATH_GPU_ENABLED T airy_bi_zero_imp(int m, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_ai(T x, const Policy&) { BOOST_FPU_EXCEPTION_GUARD @@ -284,13 +371,13 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_ai(T x, return policies::checked_narrowing_cast(detail::airy_ai_imp(static_cast(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_ai(T x) { return airy_ai(x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_bi(T x, const Policy&) { BOOST_FPU_EXCEPTION_GUARD @@ -306,13 +393,13 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_bi(T x, return policies::checked_narrowing_cast(detail::airy_bi_imp(static_cast(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_bi(T x) { return airy_bi(x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_ai_prime(T x, const Policy&) { BOOST_FPU_EXCEPTION_GUARD @@ -328,13 +415,13 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_ai_prim return policies::checked_narrowing_cast(detail::airy_ai_prime_imp(static_cast(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_ai_prime(T x) { return airy_ai_prime(x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_bi_prime(T x, const Policy&) { BOOST_FPU_EXCEPTION_GUARD @@ -350,13 +437,13 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_bi_prim return policies::checked_narrowing_cast(detail::airy_bi_prime_imp(static_cast(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type airy_bi_prime(T x) { return airy_bi_prime(x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T airy_ai_zero(int m, const Policy& /*pol*/) { BOOST_FPU_EXCEPTION_GUARD @@ -376,13 +463,13 @@ BOOST_MATH_GPU_ENABLED inline T airy_ai_zero(int m, const Policy& /*pol*/) return policies::checked_narrowing_cast(detail::airy_ai_zero_imp(m, forwarding_policy()), "boost::math::airy_ai_zero<%1%>(unsigned)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T airy_ai_zero(int m) { return airy_ai_zero(m, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline OutputIterator airy_ai_zero( int start_index, unsigned number_of_zeros, @@ -398,13 +485,13 @@ BOOST_MATH_GPU_ENABLED inline OutputIterator airy_ai_zero( for(unsigned i = 0; i < number_of_zeros; ++i) { - *out_it = boost::math::airy_ai_zero(start_index + i, pol); + *out_it = BOOST_MATH_NAMESPACE::airy_ai_zero(start_index + i, pol); ++out_it; } return out_it; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline OutputIterator airy_ai_zero( int start_index, unsigned number_of_zeros, @@ -413,7 +500,7 @@ BOOST_MATH_GPU_ENABLED inline OutputIterator airy_ai_zero( return airy_ai_zero(start_index, number_of_zeros, out_it, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T airy_bi_zero(int m, const Policy& /*pol*/) { BOOST_FPU_EXCEPTION_GUARD @@ -433,13 +520,13 @@ BOOST_MATH_GPU_ENABLED inline T airy_bi_zero(int m, const Policy& /*pol*/) return policies::checked_narrowing_cast(detail::airy_bi_zero_imp(m, forwarding_policy()), "boost::math::airy_bi_zero<%1%>(unsigned)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T airy_bi_zero(int m) { return airy_bi_zero(m, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline OutputIterator airy_bi_zero( int start_index, unsigned number_of_zeros, @@ -455,13 +542,13 @@ BOOST_MATH_GPU_ENABLED inline OutputIterator airy_bi_zero( for(unsigned i = 0; i < number_of_zeros; ++i) { - *out_it = boost::math::airy_bi_zero(start_index + i, pol); + *out_it = BOOST_MATH_NAMESPACE::airy_bi_zero(start_index + i, pol); ++out_it; } return out_it; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline OutputIterator airy_bi_zero( int start_index, unsigned number_of_zeros, @@ -470,6 +557,6 @@ BOOST_MATH_GPU_ENABLED inline OutputIterator airy_bi_zero( return airy_bi_zero(start_index, number_of_zeros, out_it, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_AIRY_HPP diff --git a/include/boost/math/special_functions/asinh.hpp b/include/boost/math/special_functions/asinh.hpp index 52362dd294..098c90fdf6 100644 --- a/include/boost/math/special_functions/asinh.hpp +++ b/include/boost/math/special_functions/asinh.hpp @@ -16,7 +16,9 @@ #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include @@ -26,17 +28,14 @@ // This is the inverse of the hyperbolic sine function. -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template inline T asinh_imp(const T x, const Policy& pol) { BOOST_MATH_STD_USING - if((boost::math::isnan)(x)) + if((BOOST_MATH_NAMESPACE::isnan)(x)) { return policies::raise_domain_error("boost::math::asinh<%1%>(%1%)", "asinh requires a finite argument, but got x = %1%.", x, pol); } @@ -51,7 +50,7 @@ namespace boost else if(x < 0.5f) { // As below, but rearranged to preserve digits: - return boost::math::log1p(x + boost::math::sqrt1pm1(x * x, pol), pol); + return BOOST_MATH_NAMESPACE::log1p(x + BOOST_MATH_NAMESPACE::sqrt1pm1(x * x, pol), pol); } else { @@ -82,12 +81,12 @@ namespace boost } } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type asinh(T x) { - return boost::math::asinh(x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::asinh(x, policies::policy<>()); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type asinh(T x, const Policy&) { typedef typename tools::promote_args::type result_type; @@ -103,8 +102,7 @@ namespace boost "boost::math::asinh<%1%>(%1%)"); } - } -} + BOOST_MATH_NAMESPACE_END #endif /* BOOST_ASINH_HPP */ diff --git a/include/boost/math/special_functions/atanh.hpp b/include/boost/math/special_functions/atanh.hpp index 9d73e568c0..5251d589cd 100644 --- a/include/boost/math/special_functions/atanh.hpp +++ b/include/boost/math/special_functions/atanh.hpp @@ -24,10 +24,7 @@ // This is the inverse of the hyperbolic tangent function. -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // This is the main fare @@ -46,7 +43,7 @@ namespace boost { return policies::raise_domain_error(function, "atanh requires x <= 1, but got x = %1%.", x, pol); } - else if((boost::math::isnan)(x)) + else if((BOOST_MATH_NAMESPACE::isnan)(x)) { return policies::raise_domain_error(function, "atanh requires -1 <= x <= 1, but got x = %1%.", x, pol); } @@ -64,7 +61,7 @@ namespace boost { // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/ if(abs(x) < 0.5f) - return (boost::math::log1p(x, pol) - boost::math::log1p(-x, pol)) / 2; + return (BOOST_MATH_NAMESPACE::log1p(x, pol) - BOOST_MATH_NAMESPACE::log1p(-x, pol)) / 2; return(log( (1 + x) / (1 - x) ) / 2); } else @@ -86,7 +83,7 @@ namespace boost } } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type atanh(T x, const Policy&) { typedef typename tools::promote_args::type result_type; @@ -101,14 +98,13 @@ namespace boost detail::atanh_imp(static_cast(x), forwarding_policy()), "boost::math::atanh<%1%>(%1%)"); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type atanh(T x) { - return boost::math::atanh(x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::atanh(x, policies::policy<>()); } - } -} + BOOST_MATH_NAMESPACE_END #endif /* BOOST_ATANH_HPP */ diff --git a/include/boost/math/special_functions/bernoulli.hpp b/include/boost/math/special_functions/bernoulli.hpp index 102b49399e..eb112fbbf2 100644 --- a/include/boost/math/special_functions/bernoulli.hpp +++ b/include/boost/math/special_functions/bernoulli.hpp @@ -15,7 +15,7 @@ #include #include -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -58,7 +58,7 @@ OutputIterator bernoulli_number_imp(OutputIterator out, std::size_t start, std:: } // namespace detail -template +BOOST_MATH_EXPORT template inline T bernoulli_b2n(const int i, const Policy &pol) { using tag_type = std::integral_constant::value>; @@ -68,17 +68,17 @@ inline T bernoulli_b2n(const int i, const Policy &pol) } T result {}; - boost::math::detail::bernoulli_number_imp(&result, static_cast(i), 1u, pol, tag_type()); + BOOST_MATH_NAMESPACE::detail::bernoulli_number_imp(&result, static_cast(i), 1u, pol, tag_type()); return result; } -template +BOOST_MATH_EXPORT template inline T bernoulli_b2n(const int i) { - return boost::math::bernoulli_b2n(i, policies::policy<>()); + return BOOST_MATH_NAMESPACE::bernoulli_b2n(i, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline OutputIterator bernoulli_b2n(const int start_index, const unsigned number_of_bernoullis_b2n, OutputIterator out_it, @@ -91,18 +91,18 @@ inline OutputIterator bernoulli_b2n(const int start_index, return ++out_it; // LCOV_EXCL_LINE we don't reach here, previous line throws. } - return boost::math::detail::bernoulli_number_imp(out_it, start_index, number_of_bernoullis_b2n, pol, tag_type()); + return BOOST_MATH_NAMESPACE::detail::bernoulli_number_imp(out_it, start_index, number_of_bernoullis_b2n, pol, tag_type()); } -template +BOOST_MATH_EXPORT template inline OutputIterator bernoulli_b2n(const int start_index, const unsigned number_of_bernoullis_b2n, OutputIterator out_it) { - return boost::math::bernoulli_b2n(start_index, number_of_bernoullis_b2n, out_it, policies::policy<>()); + return BOOST_MATH_NAMESPACE::bernoulli_b2n(start_index, number_of_bernoullis_b2n, out_it, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline T tangent_t2n(const int i, const Policy &pol) { if(i < 0) @@ -111,17 +111,17 @@ inline T tangent_t2n(const int i, const Policy &pol) } T result {}; - boost::math::detail::get_bernoulli_numbers_cache().copy_tangent_numbers(&result, i, 1, pol); + BOOST_MATH_NAMESPACE::detail::get_bernoulli_numbers_cache().copy_tangent_numbers(&result, i, 1, pol); return result; } -template +BOOST_MATH_EXPORT template inline T tangent_t2n(const int i) { - return boost::math::tangent_t2n(i, policies::policy<>()); + return BOOST_MATH_NAMESPACE::tangent_t2n(i, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline OutputIterator tangent_t2n(const int start_index, const unsigned number_of_tangent_t2n, OutputIterator out_it, @@ -133,17 +133,17 @@ inline OutputIterator tangent_t2n(const int start_index, return ++out_it; // LCOV_EXCL_LINE we don't reach here, previous line throws. } - return boost::math::detail::get_bernoulli_numbers_cache().copy_tangent_numbers(out_it, start_index, number_of_tangent_t2n, pol); + return BOOST_MATH_NAMESPACE::detail::get_bernoulli_numbers_cache().copy_tangent_numbers(out_it, start_index, number_of_tangent_t2n, pol); } -template +BOOST_MATH_EXPORT template inline OutputIterator tangent_t2n(const int start_index, const unsigned number_of_tangent_t2n, OutputIterator out_it) { - return boost::math::tangent_t2n(start_index, number_of_tangent_t2n, out_it, policies::policy<>()); + return BOOST_MATH_NAMESPACE::tangent_t2n(start_index, number_of_tangent_t2n, out_it, policies::policy<>()); } -} } // namespace boost::math +BOOST_MATH_NAMESPACE_END #endif // _BOOST_BERNOULLI_B2N_2013_05_30_HPP_ diff --git a/include/boost/math/special_functions/bessel.hpp b/include/boost/math/special_functions/bessel.hpp index 0cf9b63764..210c230f00 100644 --- a/include/boost/math/special_functions/bessel.hpp +++ b/include/boost/math/special_functions/bessel.hpp @@ -45,7 +45,7 @@ # pragma warning(disable: 6326) // potential comparison of a constant with another constant #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -61,11 +61,11 @@ struct sph_bessel_j_small_z_series_term mult = x / 2; if(v + 3 > max_factorial::value) { - term = v * log(mult) - boost::math::lgamma(v+1+T(0.5f), Policy()); + term = v * log(mult) - BOOST_MATH_NAMESPACE::lgamma(v+1+T(0.5f), Policy()); term = exp(term); } else - term = pow(mult, T(v)) / boost::math::tgamma(v+1+T(0.5f), Policy()); + term = pow(mult, T(v)) / BOOST_MATH_NAMESPACE::tgamma(v+1+T(0.5f), Policy()); mult *= -mult; } BOOST_MATH_GPU_ENABLED T operator()() @@ -87,9 +87,9 @@ BOOST_MATH_GPU_ENABLED inline T sph_bessel_j_small_z_series(unsigned v, T x, con { BOOST_MATH_STD_USING // ADL of std names sph_bessel_j_small_z_series_term s(v, x); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); policies::check_series_iterations("boost::math::sph_bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol); return result * sqrt(constants::pi() / 4); @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline T sph_bessel_j_imp(unsigned n, T x, const Policy& // Special case, n == 0 resolves down to the sinus cardinal of x: // if(n == 0) - return (boost::math::isinf)(x) ? T(0) : boost::math::sinc_pi(x, pol); + return (BOOST_MATH_NAMESPACE::isinf)(x) ? T(0) : BOOST_MATH_NAMESPACE::sinc_pi(x, pol); // // Special case for x == 0: // @@ -216,7 +216,7 @@ BOOST_MATH_GPU_ENABLED T cyl_bessel_i_imp_final(T v, T x, const Policy& pol) } return sqrt(2 / (x * constants::pi())) * sinh(x); } - if((policies::digits() <= 113) && (boost::math::numeric_limits::digits <= 113) && (boost::math::numeric_limits::radix == 2)) + if((policies::digits() <= 113) && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 113) && (BOOST_MATH_NAMESPACE::numeric_limits::radix == 2)) { if(v == 0) { @@ -320,7 +320,7 @@ BOOST_MATH_GPU_ENABLED inline T cyl_neumann_imp(T v, T x, const bessel_no_int_ta // can occur when x is small and v is large, in which case the result // is -INF: // - if(!(boost::math::isfinite)(y)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(y)) return -policies::raise_overflow_error(function, nullptr, pol); // LCOV_EXCL_LINE defensive programming? Might be dead code now... return y; } @@ -381,10 +381,10 @@ BOOST_MATH_GPU_ENABLED inline T cyl_bessel_j_zero_imp(T v, int m, const Policy& constexpr auto function = "boost::math::cyl_bessel_j_zero<%1%>(%1%, int)"; - const T half_epsilon(boost::math::tools::epsilon() / 2U); + const T half_epsilon(BOOST_MATH_NAMESPACE::tools::epsilon() / 2U); // Handle non-finite order. - if (!(boost::math::isfinite)(v) ) + if (!(BOOST_MATH_NAMESPACE::isfinite)(v) ) { return policies::raise_domain_error(function, "Order argument is %1%, but must be finite >= 0 !", v, pol); } @@ -427,17 +427,17 @@ BOOST_MATH_GPU_ENABLED inline T cyl_bessel_j_zero_imp(T v, int m, const Policy& // Set up the initial guess for the upcoming root-finding. // If the order is a negative integer, then use the corresponding // positive integer for the order. - const T guess_root = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess((order_is_integer ? vv : v), m, pol); + const T guess_root = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess((order_is_integer ? vv : v), m, pol); // Select the maximum allowed iterations from the policy. - boost::math::uintmax_t number_of_iterations = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t number_of_iterations = policies::get_max_root_iterations(); const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U)); // Perform the root-finding using Newton-Raphson iteration from Boost.Math. const T jvm = - boost::math::tools::newton_raphson_iterate( - boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv_and_jv_prime((order_is_integer ? vv : v), order_is_zero, pol), + BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate( + BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv_and_jv_prime((order_is_integer ? vv : v), order_is_zero, pol), guess_root, T(guess_root - delta_lo), T(guess_root + 0.2F), @@ -460,7 +460,7 @@ BOOST_MATH_GPU_ENABLED inline T cyl_neumann_zero_imp(T v, int m, const Policy& p constexpr auto function = "boost::math::cyl_neumann_zero<%1%>(%1%, int)"; // Handle non-finite order. - if (!(boost::math::isfinite)(v) ) + if (!(BOOST_MATH_NAMESPACE::isfinite)(v) ) { return policies::raise_domain_error(function, "Order argument is %1%, but must be finite >= 0 !", v, pol); } @@ -471,7 +471,7 @@ BOOST_MATH_GPU_ENABLED inline T cyl_neumann_zero_imp(T v, int m, const Policy& p return policies::raise_domain_error(function, "Requested the %1%'th zero, but the rank must be positive !", static_cast(m), pol); } - const T half_epsilon(boost::math::tools::epsilon() / 2U); + const T half_epsilon(BOOST_MATH_NAMESPACE::tools::epsilon() / 2U); // Get the absolute value of the order. const bool order_is_negative = (v < 0); @@ -481,7 +481,7 @@ BOOST_MATH_GPU_ENABLED inline T cyl_neumann_zero_imp(T v, int m, const Policy& p // For negative integers, use reflection to positive integer order. if(order_is_negative && order_is_integer) - return boost::math::detail::cyl_neumann_zero_imp(vv, m, pol); + return BOOST_MATH_NAMESPACE::detail::cyl_neumann_zero_imp(vv, m, pol); // Check if the order is very close to a negative half-integer. const T delta_half_integer(vv - (floor(vv) + 0.5F)); @@ -500,22 +500,22 @@ BOOST_MATH_GPU_ENABLED inline T cyl_neumann_zero_imp(T v, int m, const Policy& p // For negative half-integers, use the corresponding // spherical Bessel function of positive half-integer order. if(order_is_negative_half_integer) - return boost::math::detail::cyl_bessel_j_zero_imp(vv, m, pol); + return BOOST_MATH_NAMESPACE::detail::cyl_bessel_j_zero_imp(vv, m, pol); // Set up the initial guess for the upcoming root-finding. // If the order is a negative integer, then use the corresponding // positive integer for the order. - const T guess_root = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(v, m, pol); + const T guess_root = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(v, m, pol); // Select the maximum allowed iterations from the policy. - boost::math::uintmax_t number_of_iterations = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t number_of_iterations = policies::get_max_root_iterations(); const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U)); // Perform the root-finding using Newton-Raphson iteration from Boost.Math. const T yvm = - boost::math::tools::newton_raphson_iterate( - boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv_and_yv_prime(v, pol), + BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate( + BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv_and_yv_prime(v, pol), guess_root, T(guess_root - delta_lo), T(guess_root + 0.2F), @@ -532,7 +532,7 @@ BOOST_MATH_GPU_ENABLED inline T cyl_neumann_zero_imp(T v, int m, const Policy& p } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::result_type cyl_bessel_j(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -548,13 +548,13 @@ BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::re return policies::checked_narrowing_cast(detail::cyl_bessel_j_imp(v, static_cast(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_j<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits >::result_type cyl_bessel_j(T1 v, T2 x) { return cyl_bessel_j(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::result_type sph_bessel(unsigned v, T x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -569,13 +569,13 @@ BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::resu return policies::checked_narrowing_cast(detail::sph_bessel_j_imp(v, static_cast(x), forwarding_policy()), "boost::math::sph_bessel<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits >::result_type sph_bessel(unsigned v, T x) { return sph_bessel(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::result_type cyl_bessel_i(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -590,13 +590,13 @@ BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::re return policies::checked_narrowing_cast(detail::cyl_bessel_i_imp(static_cast(v), static_cast(x), forwarding_policy()), "boost::math::cyl_bessel_i<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits >::result_type cyl_bessel_i(T1 v, T2 x) { return cyl_bessel_i(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::result_type cyl_bessel_k(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -612,13 +612,13 @@ BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::re return policies::checked_narrowing_cast(detail::cyl_bessel_k_imp(v, static_cast(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_k<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits >::result_type cyl_bessel_k(T1 v, T2 x) { return cyl_bessel_k(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::result_type cyl_neumann(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -634,13 +634,13 @@ BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::re return policies::checked_narrowing_cast(detail::cyl_neumann_imp(v, static_cast(x), tag_type(), forwarding_policy()), "boost::math::cyl_neumann<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits >::result_type cyl_neumann(T1 v, T2 x) { return cyl_neumann(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::result_type sph_neumann(unsigned v, T x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -655,13 +655,13 @@ BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::resu return policies::checked_narrowing_cast(detail::sph_neumann_imp(v, static_cast(x), forwarding_policy()), "boost::math::sph_neumann<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits >::result_type sph_neumann(unsigned v, T x) { return sph_neumann(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::result_type cyl_bessel_j_zero(T v, int m, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -674,46 +674,46 @@ BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::resu policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; - static_assert( false == boost::math::numeric_limits::is_specialized - || ( true == boost::math::numeric_limits::is_specialized - && false == boost::math::numeric_limits::is_integer), + static_assert( false == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + || ( true == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + && false == BOOST_MATH_NAMESPACE::numeric_limits::is_integer), "Order must be a floating-point type."); return policies::checked_narrowing_cast(detail::cyl_bessel_j_zero_imp(v, m, forwarding_policy()), "boost::math::cyl_bessel_j_zero<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits >::result_type cyl_bessel_j_zero(T v, int m) { - static_assert( false == boost::math::numeric_limits::is_specialized - || ( true == boost::math::numeric_limits::is_specialized - && false == boost::math::numeric_limits::is_integer), + static_assert( false == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + || ( true == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + && false == BOOST_MATH_NAMESPACE::numeric_limits::is_integer), "Order must be a floating-point type."); return cyl_bessel_j_zero >(v, m, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_bessel_j_zero(T v, int start_index, unsigned number_of_zeros, OutputIterator out_it, const Policy& pol) { - static_assert( false == boost::math::numeric_limits::is_specialized - || ( true == boost::math::numeric_limits::is_specialized - && false == boost::math::numeric_limits::is_integer), + static_assert( false == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + || ( true == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + && false == BOOST_MATH_NAMESPACE::numeric_limits::is_integer), "Order must be a floating-point type."); for(int i = 0; i < static_cast(number_of_zeros); ++i) { - *out_it = boost::math::cyl_bessel_j_zero(v, start_index + i, pol); + *out_it = BOOST_MATH_NAMESPACE::cyl_bessel_j_zero(v, start_index + i, pol); ++out_it; } return out_it; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_bessel_j_zero(T v, int start_index, unsigned number_of_zeros, @@ -722,7 +722,7 @@ BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_bessel_j_zero(T v, return cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::result_type cyl_neumann_zero(T v, int m, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -735,46 +735,46 @@ BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits::resu policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; - static_assert( false == boost::math::numeric_limits::is_specialized - || ( true == boost::math::numeric_limits::is_specialized - && false == boost::math::numeric_limits::is_integer), + static_assert( false == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + || ( true == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + && false == BOOST_MATH_NAMESPACE::numeric_limits::is_integer), "Order must be a floating-point type."); return policies::checked_narrowing_cast(detail::cyl_neumann_zero_imp(v, m, forwarding_policy()), "boost::math::cyl_neumann_zero<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits >::result_type cyl_neumann_zero(T v, int m) { - static_assert( false == boost::math::numeric_limits::is_specialized - || ( true == boost::math::numeric_limits::is_specialized - && false == boost::math::numeric_limits::is_integer), + static_assert( false == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + || ( true == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + && false == BOOST_MATH_NAMESPACE::numeric_limits::is_integer), "Order must be a floating-point type."); return cyl_neumann_zero >(v, m, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_neumann_zero(T v, int start_index, unsigned number_of_zeros, OutputIterator out_it, const Policy& pol) { - static_assert( false == boost::math::numeric_limits::is_specialized - || ( true == boost::math::numeric_limits::is_specialized - && false == boost::math::numeric_limits::is_integer), + static_assert( false == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + || ( true == BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + && false == BOOST_MATH_NAMESPACE::numeric_limits::is_integer), "Order must be a floating-point type."); for(int i = 0; i < static_cast(number_of_zeros); ++i) { - *out_it = boost::math::cyl_neumann_zero(v, start_index + i, pol); + *out_it = BOOST_MATH_NAMESPACE::cyl_neumann_zero(v, start_index + i, pol); ++out_it; } return out_it; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_neumann_zero(T v, int start_index, unsigned number_of_zeros, @@ -783,8 +783,7 @@ BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_neumann_zero(T v, return cyl_neumann_zero(v, start_index, number_of_zeros, out_it, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER # pragma warning(pop) diff --git a/include/boost/math/special_functions/bessel_iterators.hpp b/include/boost/math/special_functions/bessel_iterators.hpp index 7e0de2f865..ea56d505c2 100644 --- a/include/boost/math/special_functions/bessel_iterators.hpp +++ b/include/boost/math/special_functions/bessel_iterators.hpp @@ -11,17 +11,16 @@ #include #include -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template struct bessel_jy_recurrence { - bessel_jy_recurrence(T v, T z) : v(v), z(z) {} - boost::math::tuple operator()(int k) + bessel_jy_recurrence(T v_, T z_) : v(v_), z(z_) {} + BOOST_MATH_NAMESPACE::tuple operator()(int k) { - return boost::math::tuple(1, -2 * (v + k) / z, 1); + return BOOST_MATH_NAMESPACE::tuple(1, -2 * (v + k) / z, 1); } T v, z; @@ -29,17 +28,17 @@ namespace boost { template struct bessel_ik_recurrence { - bessel_ik_recurrence(T v, T z) : v(v), z(z) {} - boost::math::tuple operator()(int k) + bessel_ik_recurrence(T v_, T z_) : v(v_), z(z_) {} + BOOST_MATH_NAMESPACE::tuple operator()(int k) { - return boost::math::tuple(1, -2 * (v + k) / z, -1); + return BOOST_MATH_NAMESPACE::tuple(1, -2 * (v + k) / z, -1); } T v, z; }; } // namespace detail - template > + BOOST_MATH_EXPORT template > struct bessel_j_backwards_iterator { typedef std::ptrdiff_t difference_type; @@ -49,23 +48,42 @@ namespace boost { typedef std::input_iterator_tag iterator_category; bessel_j_backwards_iterator(const T& v, const T& x) - : it(detail::bessel_jy_recurrence(v, x), boost::math::cyl_bessel_j(v, x, Policy())) + : it(detail::bessel_jy_recurrence(v, x), BOOST_MATH_NAMESPACE::cyl_bessel_j(v, x, Policy())) { if(v < 0) - boost::math::policies::raise_domain_error("bessel_j_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_j_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); } bessel_j_backwards_iterator(const T& v, const T& x, const T& J_v) : it(detail::bessel_jy_recurrence(v, x), J_v) { if(v < 0) - boost::math::policies::raise_domain_error("bessel_j_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_j_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); } bessel_j_backwards_iterator(const T& v, const T& x, const T& J_v_plus_1, const T& J_v) : it(detail::bessel_jy_recurrence(v, x), J_v_plus_1, J_v) { if (v < -1) - boost::math::policies::raise_domain_error("bessel_j_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_j_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); + } + // + // As above, but starting from order v + k: the orders v + k, v + k - 1, ... are then each computed + // with a single rounding, rather than by stepping down from a rounded v + k. + // + bessel_j_backwards_iterator(const T& v, const T& x, BOOST_MATH_NAMESPACE::tools::recurrence_offset k) + : bessel_j_backwards_iterator(v, x, BOOST_MATH_NAMESPACE::cyl_bessel_j(T(v + k.value), x, Policy()), k) {} + + bessel_j_backwards_iterator(const T& v, const T& x, const T& J_v_plus_k, BOOST_MATH_NAMESPACE::tools::recurrence_offset k) + : it(detail::bessel_jy_recurrence(v, x), J_v_plus_k, k) + { + if(v + k.value < 0) + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_j_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", T(v + k.value), Policy()); + } + bessel_j_backwards_iterator(const T& v, const T& x, const T& J_v_plus_k_plus_1, const T& J_v_plus_k, BOOST_MATH_NAMESPACE::tools::recurrence_offset k) + : it(detail::bessel_jy_recurrence(v, x), J_v_plus_k_plus_1, J_v_plus_k, k) + { + if (v + k.value < -1) + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_j_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", T(v + k.value), Policy()); } bessel_j_backwards_iterator& operator++() @@ -84,10 +102,10 @@ namespace boost { T operator*() { return *it; } private: - boost::math::tools::backward_recurrence_iterator< detail::bessel_jy_recurrence > it; + BOOST_MATH_NAMESPACE::tools::backward_recurrence_iterator< detail::bessel_jy_recurrence > it; }; - template > + template > struct bessel_i_backwards_iterator { typedef std::ptrdiff_t difference_type; @@ -97,22 +115,41 @@ namespace boost { typedef std::input_iterator_tag iterator_category; bessel_i_backwards_iterator(const T& v, const T& x) - : it(detail::bessel_ik_recurrence(v, x), boost::math::cyl_bessel_i(v, x, Policy())) + : it(detail::bessel_ik_recurrence(v, x), BOOST_MATH_NAMESPACE::cyl_bessel_i(v, x, Policy())) { if(v < -1) - boost::math::policies::raise_domain_error("bessel_i_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); } bessel_i_backwards_iterator(const T& v, const T& x, const T& I_v) : it(detail::bessel_ik_recurrence(v, x), I_v) { if(v < -1) - boost::math::policies::raise_domain_error("bessel_i_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); } bessel_i_backwards_iterator(const T& v, const T& x, const T& I_v_plus_1, const T& I_v) : it(detail::bessel_ik_recurrence(v, x), I_v_plus_1, I_v) { if(v < -1) - boost::math::policies::raise_domain_error("bessel_i_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", v, Policy()); + } + // + // As above, but starting from order v + k: the orders v + k, v + k - 1, ... are then each computed + // with a single rounding, rather than by stepping down from a rounded v + k. + // + bessel_i_backwards_iterator(const T& v, const T& x, BOOST_MATH_NAMESPACE::tools::recurrence_offset k) + : bessel_i_backwards_iterator(v, x, BOOST_MATH_NAMESPACE::cyl_bessel_i(T(v + k.value), x, Policy()), k) {} + + bessel_i_backwards_iterator(const T& v, const T& x, const T& I_v_plus_k, BOOST_MATH_NAMESPACE::tools::recurrence_offset k) + : it(detail::bessel_ik_recurrence(v, x), I_v_plus_k, k) + { + if(v + k.value < -1) + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", T(v + k.value), Policy()); + } + bessel_i_backwards_iterator(const T& v, const T& x, const T& I_v_plus_k_plus_1, const T& I_v_plus_k, BOOST_MATH_NAMESPACE::tools::recurrence_offset k) + : it(detail::bessel_ik_recurrence(v, x), I_v_plus_k_plus_1, I_v_plus_k, k) + { + if(v + k.value < -1) + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_backwards_iterator<%1%>", "Order must be > 0 stable backwards recurrence but got %1%", T(v + k.value), Policy()); } bessel_i_backwards_iterator& operator++() @@ -131,10 +168,10 @@ namespace boost { T operator*() { return *it; } private: - boost::math::tools::backward_recurrence_iterator< detail::bessel_ik_recurrence > it; + BOOST_MATH_NAMESPACE::tools::backward_recurrence_iterator< detail::bessel_ik_recurrence > it; }; - template > + BOOST_MATH_EXPORT template > struct bessel_i_forwards_iterator { typedef std::ptrdiff_t difference_type; @@ -144,22 +181,41 @@ namespace boost { typedef std::input_iterator_tag iterator_category; bessel_i_forwards_iterator(const T& v, const T& x) - : it(detail::bessel_ik_recurrence(v, x), boost::math::cyl_bessel_i(v, x, Policy())) + : it(detail::bessel_ik_recurrence(v, x), BOOST_MATH_NAMESPACE::cyl_bessel_i(v, x, Policy())) { if(v > 1) - boost::math::policies::raise_domain_error("bessel_i_forwards_iterator<%1%>", "Order must be < 0 stable forwards recurrence but got %1%", v, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_forwards_iterator<%1%>", "Order must be < 0 stable forwards recurrence but got %1%", v, Policy()); } bessel_i_forwards_iterator(const T& v, const T& x, const T& I_v) : it(detail::bessel_ik_recurrence(v, x), I_v) { if (v > 1) - boost::math::policies::raise_domain_error("bessel_i_forwards_iterator<%1%>", "Order must be < 0 stable forwards recurrence but got %1%", v, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_forwards_iterator<%1%>", "Order must be < 0 stable forwards recurrence but got %1%", v, Policy()); } bessel_i_forwards_iterator(const T& v, const T& x, const T& I_v_minus_1, const T& I_v) : it(detail::bessel_ik_recurrence(v, x), I_v_minus_1, I_v) { if (v > 1) - boost::math::policies::raise_domain_error("bessel_i_forwards_iterator<%1%>", "Order must be < 0 stable forwards recurrence but got %1%", v, Policy()); + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_forwards_iterator<%1%>", "Order must be < 0 stable forwards recurrence but got %1%", v, Policy()); + } + // + // As above, but starting from order v + k: the orders v + k, v + k + 1, ... are then each computed + // with a single rounding, rather than by stepping up from a rounded v + k. + // + bessel_i_forwards_iterator(const T& v, const T& x, BOOST_MATH_NAMESPACE::tools::recurrence_offset k) + : bessel_i_forwards_iterator(v, x, BOOST_MATH_NAMESPACE::cyl_bessel_i(T(v + k.value), x, Policy()), k) {} + + bessel_i_forwards_iterator(const T& v, const T& x, const T& I_v_plus_k, BOOST_MATH_NAMESPACE::tools::recurrence_offset k) + : it(detail::bessel_ik_recurrence(v, x), I_v_plus_k, k) + { + if (v + k.value > 1) + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_forwards_iterator<%1%>", "Order must be < 0 stable forwards recurrence but got %1%", T(v + k.value), Policy()); + } + bessel_i_forwards_iterator(const T& v, const T& x, const T& I_v_plus_k_minus_1, const T& I_v_plus_k, BOOST_MATH_NAMESPACE::tools::recurrence_offset k) + : it(detail::bessel_ik_recurrence(v, x), I_v_plus_k_minus_1, I_v_plus_k, k) + { + if (v + k.value > 1) + BOOST_MATH_NAMESPACE::policies::raise_domain_error("bessel_i_forwards_iterator<%1%>", "Order must be < 0 stable forwards recurrence but got %1%", T(v + k.value), Policy()); } bessel_i_forwards_iterator& operator++() @@ -178,10 +234,9 @@ namespace boost { T operator*() { return *it; } private: - boost::math::tools::forward_recurrence_iterator< detail::bessel_ik_recurrence > it; + BOOST_MATH_NAMESPACE::tools::forward_recurrence_iterator< detail::bessel_ik_recurrence > it; }; - } -} // namespaces + BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_ITERATORS_HPP diff --git a/include/boost/math/special_functions/bessel_prime.hpp b/include/boost/math/special_functions/bessel_prime.hpp index ba71562885..9bfec608b9 100644 --- a/include/boost/math/special_functions/bessel_prime.hpp +++ b/include/boost/math/special_functions/bessel_prime.hpp @@ -16,7 +16,7 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -29,7 +29,7 @@ inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol) // Prevent complex result: // if ((x < 0) && (floor(v) != v)) - return boost::math::policies::raise_domain_error(function, "Got x = %1%, but function requires x >= 0", x, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Got x = %1%, but function requires x >= 0", x, pol); // // Special cases for x == 0: // @@ -42,13 +42,13 @@ inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol) else if (floor(v) == v || v > 1) return 0; else - return boost::math::policies::raise_domain_error(function, "Got x = %1%, but function is indeterminate for this order", x, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Got x = %1%, but function is indeterminate for this order", x, pol); } // // Special case for large x: use asymptotic expansion: // - if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x)) - return boost::math::detail::asymptotic_bessel_j_derivative_large_x_2(v, x, pol); + if (BOOST_MATH_NAMESPACE::detail::asymptotic_bessel_derivative_large_x_limit(v, x)) + return BOOST_MATH_NAMESPACE::detail::asymptotic_bessel_j_derivative_large_x_2(v, x, pol); // // Special case for small x: use Taylor series: // @@ -61,18 +61,18 @@ inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol) if (itrunc(v, pol) & 1) inversed = true; } - T r = boost::math::detail::bessel_j_derivative_small_z_series(v, x, pol); + T r = BOOST_MATH_NAMESPACE::detail::bessel_j_derivative_small_z_series(v, x, pol); return inversed ? T(-r) : r; } // // Special case for v == 0: // if (v == 0) - return -boost::math::detail::cyl_bessel_j_imp(1, x, Tag(), pol); + return -BOOST_MATH_NAMESPACE::detail::cyl_bessel_j_imp(1, x, Tag(), pol); // // Default case: // - return boost::math::detail::bessel_j_derivative_linear(v, x, Tag(), pol); + return BOOST_MATH_NAMESPACE::detail::bessel_j_derivative_linear(v, x, Tag(), pol); } template @@ -83,22 +83,22 @@ inline T sph_bessel_j_prime_imp(unsigned v, T x, const Policy& pol) // Prevent complex result: // if (x < 0) - return boost::math::policies::raise_domain_error(function, "Got x = %1%, but function requires x >= 0.", x, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Got x = %1%, but function requires x >= 0.", x, pol); // // Special case for v == 0: // if (v == 0) - return (x == 0) ? boost::math::policies::raise_overflow_error(function, nullptr, pol) - : static_cast(-boost::math::detail::sph_bessel_j_imp(1, x, pol)); + return (x == 0) ? BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol) + : static_cast(-BOOST_MATH_NAMESPACE::detail::sph_bessel_j_imp(1, x, pol)); // // Special case for x == 0 and v > 0: // if (x == 0) - return boost::math::policies::raise_domain_error(function, "Got x = %1%, but function is indeterminate for this order", x, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Got x = %1%, but function is indeterminate for this order", x, pol); // // Default case: // - return boost::math::detail::sph_bessel_j_derivative_linear(v, x, pol); + return BOOST_MATH_NAMESPACE::detail::sph_bessel_j_derivative_linear(v, x, pol); } template @@ -110,7 +110,7 @@ inline T cyl_bessel_i_prime_imp(T v, T x, const Policy& pol) // Prevent complex result: // if (x < 0 && floor(v) != v) - return boost::math::policies::raise_domain_error(function, "Got x = %1%, but function requires x >= 0", x, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Got x = %1%, but function requires x >= 0", x, pol); // // Special cases for x == 0: // @@ -121,17 +121,17 @@ inline T cyl_bessel_i_prime_imp(T v, T x, const Policy& pol) else if (floor(v) == v || v > 1) return 0; else - return boost::math::policies::raise_domain_error(function, "Got x = %1%, but function is indeterminate for this order", x, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Got x = %1%, but function is indeterminate for this order", x, pol); } // // Special case for v == 0: // if (v == 0) - return boost::math::detail::cyl_bessel_i_imp(1, x, pol); + return BOOST_MATH_NAMESPACE::detail::cyl_bessel_i_imp(1, x, pol); // // Default case: // - return boost::math::detail::bessel_i_derivative_linear(v, x, pol); + return BOOST_MATH_NAMESPACE::detail::bessel_i_derivative_linear(v, x, pol); } template @@ -141,16 +141,16 @@ inline T cyl_bessel_k_prime_imp(T v, T x, const Policy& pol) // Prevent complex and indeterminate results: // if (x <= 0) - return boost::math::policies::raise_domain_error("boost::math::cyl_bessel_k_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0", x, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error("boost::math::cyl_bessel_k_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0", x, pol); // // Special case for v == 0: // if (v == 0) - return -boost::math::detail::cyl_bessel_k_imp(1, x, Tag(), pol); + return -BOOST_MATH_NAMESPACE::detail::cyl_bessel_k_imp(1, x, Tag(), pol); // // Default case: // - return boost::math::detail::bessel_k_derivative_linear(v, x, Tag(), pol); + return BOOST_MATH_NAMESPACE::detail::bessel_k_derivative_linear(v, x, Tag(), pol); } template @@ -161,30 +161,30 @@ inline T cyl_neumann_prime_imp(T v, T x, const Policy& pol) // Prevent complex and indeterminate results: // if (x <= 0) - return boost::math::policies::raise_domain_error("boost::math::cyl_neumann_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0", x, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error("boost::math::cyl_neumann_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0", x, pol); // // Special case for large x: use asymptotic expansion: // - if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x)) - return boost::math::detail::asymptotic_bessel_y_derivative_large_x_2(v, x, pol); + if (BOOST_MATH_NAMESPACE::detail::asymptotic_bessel_derivative_large_x_limit(v, x)) + return BOOST_MATH_NAMESPACE::detail::asymptotic_bessel_y_derivative_large_x_2(v, x, pol); // // Special case for small x: use Taylor series: // if (v > 0 && floor(v) != v) { - const T eps = boost::math::policies::get_epsilon(); + const T eps = BOOST_MATH_NAMESPACE::policies::get_epsilon(); if (log(eps / 2) > v * log((x * x) / (v * 4))) - return boost::math::detail::bessel_y_derivative_small_z_series(v, x, pol); + return BOOST_MATH_NAMESPACE::detail::bessel_y_derivative_small_z_series(v, x, pol); } // // Special case for v == 0: // if (v == 0) - return -boost::math::detail::cyl_neumann_imp(1, x, Tag(), pol); + return -BOOST_MATH_NAMESPACE::detail::cyl_neumann_imp(1, x, Tag(), pol); // // Default case: // - return boost::math::detail::bessel_y_derivative_linear(v, x, Tag(), pol); + return BOOST_MATH_NAMESPACE::detail::bessel_y_derivative_linear(v, x, Tag(), pol); } template @@ -194,21 +194,21 @@ inline T sph_neumann_prime_imp(unsigned v, T x, const Policy& pol) // Prevent complex and indeterminate result: // if (x <= 0) - return boost::math::policies::raise_domain_error("boost::math::sph_neumann_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0.", x, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error("boost::math::sph_neumann_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0.", x, pol); // // Special case for v == 0: // if (v == 0) - return -boost::math::detail::sph_neumann_imp(1, x, pol); + return -BOOST_MATH_NAMESPACE::detail::sph_neumann_imp(1, x, pol); // // Default case: // - return boost::math::detail::sph_neumann_derivative_linear(v, x, pol); + return BOOST_MATH_NAMESPACE::detail::sph_neumann_derivative_linear(v, x, pol); } } // namespace detail -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits::result_type cyl_bessel_j_prime(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -224,13 +224,13 @@ inline typename detail::bessel_traits::result_type cyl_bessel_j_ return policies::checked_narrowing_cast(detail::cyl_bessel_j_prime_imp(static_cast(v), static_cast(x), forwarding_policy()), "boost::math::cyl_bessel_j_prime<%1%,%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits >::result_type cyl_bessel_j_prime(T1 v, T2 x) { return cyl_bessel_j_prime(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits::result_type sph_bessel_prime(unsigned v, T x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -245,13 +245,13 @@ inline typename detail::bessel_traits::result_type sph_bessel_prim return policies::checked_narrowing_cast(detail::sph_bessel_j_prime_imp(v, static_cast(x), forwarding_policy()), "boost::math::sph_bessel_j_prime<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits >::result_type sph_bessel_prime(unsigned v, T x) { return sph_bessel_prime(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits::result_type cyl_bessel_i_prime(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -266,13 +266,13 @@ inline typename detail::bessel_traits::result_type cyl_bessel_i_ return policies::checked_narrowing_cast(detail::cyl_bessel_i_prime_imp(static_cast(v), static_cast(x), forwarding_policy()), "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits >::result_type cyl_bessel_i_prime(T1 v, T2 x) { return cyl_bessel_i_prime(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits::result_type cyl_bessel_k_prime(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -288,13 +288,13 @@ inline typename detail::bessel_traits::result_type cyl_bessel_k_ return policies::checked_narrowing_cast(detail::cyl_bessel_k_prime_imp(static_cast(v), static_cast(x), forwarding_policy()), "boost::math::cyl_bessel_k_prime<%1%,%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits >::result_type cyl_bessel_k_prime(T1 v, T2 x) { return cyl_bessel_k_prime(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits::result_type cyl_neumann_prime(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -310,13 +310,13 @@ inline typename detail::bessel_traits::result_type cyl_neumann_p return policies::checked_narrowing_cast(detail::cyl_neumann_prime_imp(static_cast(v), static_cast(x), forwarding_policy()), "boost::math::cyl_neumann_prime<%1%,%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits >::result_type cyl_neumann_prime(T1 v, T2 x) { return cyl_neumann_prime(v, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits::result_type sph_neumann_prime(unsigned v, T x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -331,13 +331,12 @@ inline typename detail::bessel_traits::result_type sph_neumann_pri return policies::checked_narrowing_cast(detail::sph_neumann_prime_imp(v, static_cast(x), forwarding_policy()), "boost::math::sph_neumann_prime<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename detail::bessel_traits >::result_type sph_neumann_prime(unsigned v, T x) { return sph_neumann_prime(v, x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_DERIVATIVES_HPP diff --git a/include/boost/math/special_functions/beta.hpp b/include/boost/math/special_functions/beta.hpp index 5c3a762ca0..998b0a6495 100644 --- a/include/boost/math/special_functions/beta.hpp +++ b/include/boost/math/special_functions/beta.hpp @@ -31,9 +31,10 @@ #include #include #include +#include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -109,7 +110,7 @@ BOOST_MATH_GPU_ENABLED T beta_imp(T a, T b, const Lanczos&, const Policy& pol) { // Special case where the base of the power term is close to 1 // compute (1+x)^y instead: - result *= exp(ambh * boost::math::log1p(-b / cgh, pol)); + result *= exp(ambh * BOOST_MATH_NAMESPACE::log1p(-b / cgh, pol)); } else { @@ -120,7 +121,7 @@ BOOST_MATH_GPU_ENABLED T beta_imp(T a, T b, const Lanczos&, const Policy& pol) result *= pow((agh / cgh) * (bgh / cgh), b); else result *= pow((agh * bgh) / (cgh * cgh), b); - result *= sqrt(boost::math::constants::e() / bgh); + result *= sqrt(BOOST_MATH_NAMESPACE::constants::e() / bgh); // If a and b were originally less than 1 we need to scale the result: result *= prefix; @@ -179,12 +180,18 @@ BOOST_MATH_GPU_ENABLED T beta_imp(T a, T b, const lanczos::undefined_lanczos& l, } else if ((a < 1) && (b < 1)) { - return boost::math::tgamma(a, pol) * (boost::math::tgamma(b, pol) / boost::math::tgamma(c)); + return BOOST_MATH_NAMESPACE::tgamma(a, pol) * (BOOST_MATH_NAMESPACE::tgamma(b, pol) / BOOST_MATH_NAMESPACE::tgamma(c)); } else if(a < 1) - return boost::math::tgamma(a, pol) * boost::math::tgamma_delta_ratio(b, a, pol); + return BOOST_MATH_NAMESPACE::tgamma(a, pol) * BOOST_MATH_NAMESPACE::tgamma_delta_ratio(b, a, pol); else if(b < 1) - return boost::math::tgamma(b, pol) * boost::math::tgamma_delta_ratio(a, b, pol); + return BOOST_MATH_NAMESPACE::tgamma(b, pol) * BOOST_MATH_NAMESPACE::tgamma_delta_ratio(a, b, pol); + else if(c < ::BOOST_MATH_NAMESPACE::max_factorial::value) + { + // The recursion below rounds ~2 (shift_a + shift_b) times and raises a / c and b / c to powers + // above min_sterling, which costs ~30 eps at 113 bits; tgamma is good to about 1 eps and can't overflow here: + return BOOST_MATH_NAMESPACE::tgamma(a, pol) * (BOOST_MATH_NAMESPACE::tgamma(b, pol) / BOOST_MATH_NAMESPACE::tgamma(c, pol)); + } else { T result = beta_imp(T(a + shift_a), T(b + shift_b), l, pol); @@ -205,6 +212,234 @@ BOOST_MATH_GPU_ENABLED T beta_imp(T a, T b, const lanczos::undefined_lanczos& l, } // template T beta_imp(T a, T b, const lanczos::undefined_lanczos& l) #endif +// +// Logarithm of Beta(a,b), from the same Lanczos approximation as beta_imp. +// With a >= b, c = a + b and xgh = x + g - 0.5, the log of beta_imp's product is +// +// log(S(a) S(b) / S(c)) + (a - 0.5) log1p(-b / cgh) + b log(bgh / cgh) + (1 - log(bgh)) / 2, +// +// where S is the scaled Lanczos sum, using agh = cgh - b to merge beta_imp's two powers. +// No large terms cancel, unlike lgamma(a) + lgamma(b) - lgamma(a + b) when one argument is large, +// and nothing underflows, unlike log(beta(a, b)) when both are. +// +template +BOOST_MATH_GPU_ENABLED T lbeta_imp(T a, T b, const Lanczos&, const Policy& pol) +{ + BOOST_MATH_STD_USING // for ADL of std names + + // Reject NaN before any comparison sends it down a branch meant for ordered arguments: + if((BOOST_MATH_NAMESPACE::isnan)(a) || (BOOST_MATH_NAMESPACE::isnan)(b)) + return policies::raise_domain_error("boost::math::lbeta<%1%>(%1%,%1%)", "The arguments to the beta function must not be NaN (got %1%).", (BOOST_MATH_NAMESPACE::isnan)(a) ? a : b, pol); + if(a <= 0) + return policies::raise_domain_error("boost::math::lbeta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got a=%1%).", a, pol); + if(b <= 0) + return policies::raise_domain_error("boost::math::lbeta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got b=%1%).", b, pol); + // log(beta(a, b)) tends to -infinity when either argument does: + if((BOOST_MATH_NAMESPACE::isinf)(a) || (BOOST_MATH_NAMESPACE::isinf)(b)) + return -policies::raise_overflow_error("boost::math::lbeta<%1%>(%1%,%1%)", nullptr, pol); + + T c = a + b; + + // Special cases, as in beta_imp. For tiny b, log(beta) = -log(b) - b digamma(a) + O(b); unlike in + // beta_imp, the b term is not negligible next to -log(b) when a is huge, and log(a) is close enough to + // digamma(a) wherever c == a: + if((c == a) && (b < tools::epsilon())) + return -log(b) - b * log(a); + else if((c == b) && (a < tools::epsilon())) + return -log(a) - a * log(b); + if(b == 1) + return -log(a); + else if(a == 1) + return -log(b); + else if(c < tools::epsilon()) + return log(c) - log(a) - log(b); + + if(a < b) + { + BOOST_MATH_GPU_SAFE_SWAP(a, b); + } + + T bgh = static_cast(b + Lanczos::g() - 0.5f); + T cgh = static_cast(c + Lanczos::g() - 0.5f); + T result = log(Lanczos::lanczos_sum_expG_scaled(a) * (Lanczos::lanczos_sum_expG_scaled(b) / Lanczos::lanczos_sum_expG_scaled(c))); + result += (a - T(0.5)) * BOOST_MATH_NAMESPACE::log1p(-b / cgh, pol); + result += b * log(bgh / cgh); + result += (1 - log(bgh)) / 2; + return result; +} // template lbeta_imp(T a, T b, const Lanczos&) + +// +// Logarithm of the generic Beta(a,b) without Lanczos approximation support: +// +#ifndef BOOST_MATH_HAS_GPU_SUPPORT +template +BOOST_MATH_GPU_ENABLED T lbeta_imp(T a, T b, const lanczos::undefined_lanczos& l, const Policy& pol) +{ + BOOST_MATH_STD_USING + + // Reject NaN before any comparison sends it down a branch meant for ordered arguments: + if((BOOST_MATH_NAMESPACE::isnan)(a) || (BOOST_MATH_NAMESPACE::isnan)(b)) + return policies::raise_domain_error("boost::math::lbeta<%1%>(%1%,%1%)", "The arguments to the beta function must not be NaN (got %1%).", (BOOST_MATH_NAMESPACE::isnan)(a) ? a : b, pol); + if(a <= 0) + return policies::raise_domain_error("boost::math::lbeta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got a=%1%).", a, pol); + if(b <= 0) + return policies::raise_domain_error("boost::math::lbeta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got b=%1%).", b, pol); + // log(beta(a, b)) tends to -infinity when either argument does: + if((BOOST_MATH_NAMESPACE::isinf)(a) || (BOOST_MATH_NAMESPACE::isinf)(b)) + return -policies::raise_overflow_error("boost::math::lbeta<%1%>(%1%,%1%)", nullptr, pol); + + // Fix the argument order so that lbeta(a, b) == lbeta(b, a) exactly: + if (a < b) + { + BOOST_MATH_GPU_SAFE_SWAP(a, b); + } + const T c = a + b; + + // Special cases, as in the Lanczos version: + if ((c == a) && (b < tools::epsilon())) + return -log(b) - b * log(a); + else if ((c == b) && (a < tools::epsilon())) + return -log(a) - a * log(b); + if (b == 1) + return -log(a); + else if (a == 1) + return -log(b); + else if (c < tools::epsilon()) + return log(c) - log(a) - log(b); + + // Regular cases start here: + const T min_sterling = minimum_argument_for_bernoulli_recursion(); + + long shift_a = 0; + long shift_b = 0; + + if(a < min_sterling) + shift_a = 1 + ltrunc(min_sterling - a); + if(b < min_sterling) + shift_b = 1 + ltrunc(min_sterling - b); + long shift_c = shift_a + shift_b; + + if ((shift_a == 0) && (shift_b == 0)) + { + // log of pow(a / c, a) * pow(b / c, b), with log1p for the larger argument, whose ratio is near one: + T power_terms = a < b ? a * log(a / c) + b * BOOST_MATH_NAMESPACE::log1p(-a / c, pol) : a * BOOST_MATH_NAMESPACE::log1p(-b / c, pol) + b * log(b / c); + return power_terms + log(scaled_tgamma_no_lanczos(a, pol) * (scaled_tgamma_no_lanczos(b, pol) / scaled_tgamma_no_lanczos(c, pol))); + } + else if ((a < 1) && (b < 1)) + { + return BOOST_MATH_NAMESPACE::lgamma(a, pol) + (BOOST_MATH_NAMESPACE::lgamma(b, pol) - BOOST_MATH_NAMESPACE::lgamma(c, pol)); + } + else if((a < 1) || (b < 1) || (shift_a == 0) || (shift_b == 0)) + { + // One argument, say a, is small: log(gamma(a) gamma(b) / gamma(a + b)) directly, since shifting + // a up and back would cancel terms of size shift_a * log(c) when b is large. The ratio of gammas + // is about b^-a, which only a narrow exponent range can underflow; then fall back to recursion. + T small_arg = a < b ? a : b; + T large_arg = a < b ? b : a; + T ratio = BOOST_MATH_NAMESPACE::tgamma_delta_ratio(large_arg, small_arg, pol); + if ((ratio >= tools::min_value()) || (small_arg < 1)) + return BOOST_MATH_NAMESPACE::lgamma(small_arg, pol) + log(ratio); + } + else + { + // Both arguments lie in [1, min_sterling), so beta itself can neither overflow nor underflow, + // and its recursion multiplies rather than cancels: taking the log only reduces its relative error. + return log(beta_imp(a, b, l, pol)); + } + { + // Only reached when one argument is huge and the gamma ratio above underflows. + T result = lbeta_imp(T(a + shift_a), T(b + shift_b), l, pol); + // + // Recursion, summed as logs: as a product it overflows when one argument is huge: + // + for (long i = 0; i < shift_c; ++i) + { + T ratio = c + i; + if (i < shift_a) + ratio /= a + i; + if (i < shift_b) + ratio /= b + i; + result += log(ratio); + } + return result; + } + +} // template T lbeta_imp(T a, T b, const lanczos::undefined_lanczos& l) +#endif + +// +// The bases of the power terms minus one, l1 = x cgh / agh - 1 and l2 = y cgh / bgh - 1, where +// agh = a + gh, bgh = b + gh and cgh = a + b + gh (gh = 0 for no shift). +// The larger of x and y = 1 - x has been rounded, and near the mode x b and y a nearly +// cancel, so ((x b - y a) - y gh) / agh has an absolute error of about +// eps max(a, b) min(x, y) / agh, which the exponent a multiplies. Instead use only the +// smaller of x and y, carry the rounding errors of a + gh and a + b + gh, and form the +// products with fma: +// +template +BOOST_MATH_GPU_ENABLED inline void ibeta_power_bases(T a, T b, T x, T y, T gh, T agh, T bgh, T cgh, T& l1, T& l2) +{ + #ifndef BOOST_MATH_HAS_GPU_SUPPORT + using std::fma; + #endif + T c = a + b; + T agh_err = two_sum_error(a, gh, agh); + T bgh_err = two_sum_error(b, gh, bgh); + T cgh_err = two_sum_error(c, gh, cgh) + two_sum_error(a, b, c); + if(x <= y) + { + l1 = (fma(x, cgh, -agh) + (x * cgh_err - agh_err)) / agh; + // y cgh - bgh = a - x cgh: + l2 = -(fma(x, cgh, -a) + x * cgh_err) / bgh; + } + else + { + // x cgh - agh = b - y cgh: + l1 = -(fma(y, cgh, -b) + y * cgh_err) / agh; + l2 = (fma(y, cgh, -bgh) + (y * cgh_err - bgh_err)) / bgh; + } +} + +// +// a log1p(l1) + b log1p(l2) for bases from ibeta_power_bases with max(|l1|, |l2|) < 0.5, +// returned as l + l_err: +// +template +BOOST_MATH_GPU_ENABLED inline T ibeta_power_log_near_mean(T a, T b, T l1, T l2, T gh, T bgh, const Policy& pol, T& l_err) +{ + #ifndef BOOST_MATH_HAS_GPU_SUPPORT + using std::fma; + #endif + T bgh_err = two_sum_error(b, gh, bgh); + // + // Both bases are near 1, and when a and b are large the two terms of the exponent + // a log1p(l1) + b log1p(l2) nearly cancel. Since agh (1 + l1) + bgh (1 + l2) = cgh, + // a l1 + b l2 = gh (l1 (a - b) - b) / bgh, which leaves terms that don't cancel: + // + // a log1p(l1) + b log1p(l2) = gh (l1 (a - b) - b) / bgh + a log1pmx(l1) + b log1pmx(l2) + // + // The first term is about -gh, so rounding it costs as much as eps gh / 2 of relative error in + // the result. Carry it as a sum of two doubles: gh (l1 (a - b) - b) / bgh, with every operation's + // rounding error found with fma, is lh + ll, and the rounding of lh + the rest is added back below. + // + T ab = a - b; + T ab_err = two_sum_error(a, T(-b), ab); + T ph = fma(l1, ab, T(0)); // fma(x, y, 0) so that the product is not contracted into a later sum + T pl = fma(l1, ab, -ph) + l1 * ab_err; + T nh = ph - b; + T nl = pl + two_sum_error(ph, T(-b), nh); + T wh = nh / bgh; + T wl = (fma(-wh, bgh, nh) + (nl - wh * bgh_err)) / bgh; + T lh = fma(gh, wh, T(0)); + T ll = fma(gh, wh, -lh) + gh * wl; + T rest = ll + + a * BOOST_MATH_NAMESPACE::log1pmx(l1, pol) + + b * BOOST_MATH_NAMESPACE::log1pmx(l2, pol); + T l = lh + rest; + l_err = two_sum_error(lh, rest, l); + return l; +} + // // Compute the leading power terms in the incomplete Beta: // @@ -252,14 +487,38 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, result *= prefix; BOOST_MATH_INSTRUMENT_VARIABLE(result); // combine with the leftover terms from the Lanczos approximation: - result *= sqrt(bgh / boost::math::constants::e()); + result *= sqrt(bgh / BOOST_MATH_NAMESPACE::constants::e()); result *= sqrt(agh / cgh); BOOST_MATH_INSTRUMENT_VARIABLE(result); - // l1 and l2 are the base of the exponents minus one: - T l1 = ((x * b - y * a) - y * gh) / agh; - T l2 = ((y * a - x * b) - x * gh) / bgh; - if((BOOST_MATH_GPU_SAFE_MIN(fabs(l1), fabs(l2)) < 0.2)) + // l1 and l2 are the bases of the exponents minus one: + #ifndef BOOST_MATH_HAS_GPU_SUPPORT + using std::fma; + #endif + T l1, l2; + ibeta_power_bases(a, b, x, y, gh, agh, bgh, cgh, l1, l2); + BOOST_MATH_INSTRUMENT_VARIABLE(l1); + BOOST_MATH_INSTRUMENT_VARIABLE(l2); + if(BOOST_MATH_GPU_SAFE_MAX(fabs(l1), fabs(l2)) < 0.5) + { + T l_err; + T l = ibeta_power_log_near_mean(a, b, l1, l2, gh, bgh, pol, l_err); + if((l <= tools::log_min_value()) || (l >= tools::log_max_value())) + { + l += l_err; + l += log(result); + if(l >= tools::log_max_value()) + return policies::raise_overflow_error(function, nullptr, pol); // LCOV_EXCL_LINE we can probably never get here, probably! + result = exp(l); + } + else + { + result *= exp(l); + result = fma(result, l_err, result); + } + BOOST_MATH_INSTRUMENT_VARIABLE(result); + } + else if((BOOST_MATH_GPU_SAFE_MIN(fabs(l1), fabs(l2)) < 0.2)) { // when the base of the exponent is very near 1 we get really // gross errors unless extra care is taken: @@ -280,7 +539,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, // if(fabs(l1) < 0.1) { - result *= exp(a * boost::math::log1p(l1, pol)); + result *= exp(a * BOOST_MATH_NAMESPACE::log1p(l1, pol)); BOOST_MATH_INSTRUMENT_VARIABLE(result); } else @@ -290,7 +549,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, } if(fabs(l2) < 0.1) { - result *= exp(b * boost::math::log1p(l2, pol)); + result *= exp(b * BOOST_MATH_NAMESPACE::log1p(l2, pol)); BOOST_MATH_INSTRUMENT_VARIABLE(result); } else @@ -299,50 +558,10 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, BOOST_MATH_INSTRUMENT_VARIABLE(result); } } - else if(BOOST_MATH_GPU_SAFE_MAX(fabs(l1), fabs(l2)) < 0.5) - { - // - // Both exponents are near one and both the exponents are - // greater than one and further these two - // power terms tend in opposite directions (one towards zero, - // the other towards infinity), so we have to combine the terms - // to avoid any risk of overflow or underflow. - // - // We do this by moving one power term inside the other, we have: - // - // (1 + l1)^a * (1 + l2)^b - // = ((1 + l1)*(1 + l2)^(b/a))^a - // = (1 + l1 + l3 + l1*l3)^a ; l3 = (1 + l2)^(b/a) - 1 - // = exp((b/a) * log(1 + l2)) - 1 - // - // The tricky bit is deciding which term to move inside :-) - // By preference we move the larger term inside, so that the - // size of the largest exponent is reduced. However, that can - // only be done as long as l3 (see above) is also small. - // - bool small_a = a < b; - T ratio = b / a; - if((small_a && (ratio * l2 < 0.1)) || (!small_a && (l1 / ratio > 0.1))) - { - T l3 = boost::math::expm1(ratio * boost::math::log1p(l2, pol), pol); - l3 = l1 + l3 + l3 * l1; - l3 = a * boost::math::log1p(l3, pol); - result *= exp(l3); - BOOST_MATH_INSTRUMENT_VARIABLE(result); - } - else - { - T l3 = boost::math::expm1(boost::math::log1p(l1, pol) / ratio, pol); - l3 = l2 + l3 + l3 * l2; - l3 = b * boost::math::log1p(l3, pol); - result *= exp(l3); - BOOST_MATH_INSTRUMENT_VARIABLE(result); - } - } else if(fabs(l1) < fabs(l2)) { // First base near 1 only: - T l = a * boost::math::log1p(l1, pol) + T l = a * BOOST_MATH_NAMESPACE::log1p(l1, pol) + b * log((y * cgh) / bgh); if((l <= tools::log_min_value()) || (l >= tools::log_max_value())) { @@ -358,7 +577,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, else { // Second base near 1 only: - T l = b * boost::math::log1p(l2, pol) + T l = b * BOOST_MATH_NAMESPACE::log1p(l2, pol) + a * log((x * cgh) / agh); if((l <= tools::log_min_value()) || (l >= tools::log_max_value())) { @@ -443,7 +662,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, return result; // true zero LCOV_EXCL_LINE we can probably never get here if ((b > 1) && (y == 0)) return result; // true zero LCOV_EXCL_LINE we can probably never get here - return boost::math::policies::raise_underflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::policies::raise_underflow_error(function, nullptr, pol); } return result; @@ -467,7 +686,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, T b, T x, T y, - const boost::math::lanczos::undefined_lanczos& l, + const BOOST_MATH_NAMESPACE::lanczos::undefined_lanczos& l, bool normalised, const Policy& pol, T prefix = 1, @@ -493,11 +712,30 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, if ((shift_a == 0) && (shift_b == 0)) { + T scale = prefix * scaled_tgamma_no_lanczos(c, pol) / (scaled_tgamma_no_lanczos(a, pol) * scaled_tgamma_no_lanczos(b, pol)); + // + // Near the mean the bases x c / a and y c / b are close to 1, and pow of them rounds to a relative + // error of about eps max(a, b), O(1) once a, b ~ 1 / eps. With d = x c - a = b - y c, found exactly + // from the smaller of x and y and the rounding error of c, the bases are 1 + d / a and 1 - d / b, + // and the d terms of the exponent cancel exactly, leaving a log1pmx(d / a) + b log1pmx(-d / b): + // + T c_err = two_sum_error(a, b, c); + T ph, pl; + two_product product; + product(x <= y ? x : y, c, ph, pl); // ph is fma(x, c, 0), which contraction can't fuse into ph - a + T d = x <= y ? T((ph - a) + (pl + x * c_err)) : T(-((ph - b) + (pl + y * c_err))); + T u1 = d / a; + T u2 = -d / b; + if (BOOST_MATH_GPU_SAFE_MAX(fabs(u1), fabs(u2)) < 0.5) + { + T log_term = a * BOOST_MATH_NAMESPACE::log1pmx(u1, pol) + b * BOOST_MATH_NAMESPACE::log1pmx(u2, pol); + return log_term > tools::log_min_value() ? T(exp(log_term) * scale) : T(exp(log_term + log(scale))); + } T power1, power2; bool need_logs = false; if (a < b) { - BOOST_MATH_IF_CONSTEXPR(boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR(BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { power1 = pow((x * y * c * c) / (a * b), a); power2 = pow((y * c) / b, b - a); @@ -520,7 +758,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, } else { - BOOST_MATH_IF_CONSTEXPR(boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR(BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { power1 = pow((x * y * c * c) / (a * b), b); power2 = pow((x * c) / a, a - b); @@ -539,76 +777,31 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, need_logs = true; } } - BOOST_MATH_IF_CONSTEXPR(boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR(BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - if (!(boost::math::isnormal)(power1) || !(boost::math::isnormal)(power2)) + if (!(BOOST_MATH_NAMESPACE::isnormal)(power1) || !(BOOST_MATH_NAMESPACE::isnormal)(power2)) { need_logs = true; } } if (need_logs) { - // - // We want: - // - // (xc / a)^a (yc / b)^b - // - // But we know that one or other term will over / underflow and combining the logs will be next to useless as that will cause significant cancellation. - // If we assume b > a and express z ^ b as(z ^ b / a) ^ a with z = (yc / b) then we can move one power term inside the other : - // - // ((xc / a) * (yc / b)^(b / a))^a - // - // However, we're not quite there yet, as the term being exponentiated is quite likely to be close to unity, so let: - // - // xc / a = 1 + (xb - ya) / a - // - // analogously let : - // - // 1 + p = (yc / b) ^ (b / a) = 1 + expm1((b / a) * log1p((ya - xb) / b)) - // - // so putting the two together we have : - // - // exp(a * log1p((xb - ya) / a + p + p(xb - ya) / a)) - // - // Analogously, when a > b we can just swap all the terms around. - // - // Finally, there are a few cases (x or y is unity) when the above logic can't be used - // or where there is no logarithmic cancellation and accuracy is better just using - // the regular formula: - // - T xc_a = x * c / a; - T yc_b = y * c / b; - if ((x == 1) || (y == 1) || (fabs(xc_a - 1) > 0.25) || (fabs(yc_b - 1) > 0.25)) - { - // The above logic fails, the result is almost certainly zero: - power1 = exp(log(xc_a) * a + log(yc_b) * b); - power2 = 1; - } - else if (b > a) - { - T p = boost::math::expm1((b / a) * boost::math::log1p((y * a - x * b) / b)); - power1 = exp(a * boost::math::log1p((x * b - y * a) / a + p * (x * c / a))); - power2 = 1; - } - else - { - T p = boost::math::expm1((a / b) * boost::math::log1p((x * b - y * a) / a)); - power1 = exp(b * boost::math::log1p((y * a - x * b) / b + p * (y * c / b))); - power2 = 1; - } + // Away from the mean (handled above) there is no logarithmic cancellation to avoid: + power1 = exp(log(x * c / a) * a + log(y * c / b) * b); + power2 = 1; } - return prefix * power1 * power2 * scaled_tgamma_no_lanczos(c, pol) / (scaled_tgamma_no_lanczos(a, pol) * scaled_tgamma_no_lanczos(b, pol)); + return power1 * power2 * scale; } T power1 = pow(x, a); T power2 = pow(y, b); T bet = beta_imp(a, b, l, pol); - if(!(boost::math::isnormal)(power1) || !(boost::math::isnormal)(power2) || !(boost::math::isnormal)(bet)) + if(!(BOOST_MATH_NAMESPACE::isnormal)(power1) || !(BOOST_MATH_NAMESPACE::isnormal)(power2) || !(BOOST_MATH_NAMESPACE::isnormal)(bet)) { int shift_c = shift_a + shift_b; T result = ibeta_power_terms(T(a + shift_a), T(b + shift_b), x, y, l, normalised, pol, prefix); - if ((boost::math::isnormal)(result)) + if ((BOOST_MATH_NAMESPACE::isnormal)(result)) { for (int i = 0; i < shift_c; ++i) { @@ -629,10 +822,10 @@ BOOST_MATH_GPU_ENABLED T ibeta_power_terms(T a, else { T log_result = log(x) * a + log(y) * b + log(prefix); - if ((boost::math::isnormal)(bet)) + if ((BOOST_MATH_NAMESPACE::isnormal)(bet)) log_result -= log(bet); else - log_result += boost::math::lgamma(c, pol) - boost::math::lgamma(a, pol) - boost::math::lgamma(b, pol); + log_result += BOOST_MATH_NAMESPACE::lgamma(c, pol) - BOOST_MATH_NAMESPACE::lgamma(a, pol) - BOOST_MATH_NAMESPACE::lgamma(b, pol); return exp(log_result); } } @@ -662,6 +855,30 @@ struct ibeta_series_t int n; }; +// +// Sum the series s0 + s() + s() + ... with Neumaier compensated summation. +// The series is often started from s0 = -1 (to evaluate the complement), where the running sum +// sits on a coarse grid (|sum| >= 1/2) and plain accumulation loses several eps to rounding. +// The compensation term keeps the error of the whole sum to about one rounding. +// +template +BOOST_MATH_GPU_ENABLED T ibeta_series_sum(ibeta_series_t& s, T s0, BOOST_MATH_NAMESPACE::uintmax_t& max_iter, const Policy&) +{ + BOOST_MATH_STD_USING + const T factor = BOOST_MATH_NAMESPACE::policies::get_epsilon(); + BOOST_MATH_NAMESPACE::uintmax_t counter = max_iter; + compensated_sum sum(s0); + T term; + do + { + term = s(); + sum.add(term); + } + while ((abs(factor * sum.sum) < abs(term)) && --counter); + max_iter = max_iter - counter; + return sum.value(); +} + template BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const Lanczos&, bool normalised, T* p_derivative, T y, const Policy& pol) { @@ -692,7 +909,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const Lanczos&, bool result = l1 / (l2 * l3); } - if (!(boost::math::isfinite)(result)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(result)) result = 0; // LCOV_EXCL_LINE we can probably never get here, covered already above? T l1 = log(cgh / bgh) * (b - 0.5f); @@ -706,11 +923,11 @@ BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const Lanczos&, bool && (l2 < tools::log_max_value())) { if(a * b < bgh * 10) - result *= exp((b - 0.5f) * boost::math::log1p(a / bgh, pol)); + result *= exp((b - 0.5f) * BOOST_MATH_NAMESPACE::log1p(a / bgh, pol)); else result *= pow(cgh / bgh, T(b - T(0.5))); result *= pow(x * cgh / agh, a); - result *= sqrt(agh / boost::math::constants::e()); + result *= sqrt(agh / BOOST_MATH_NAMESPACE::constants::e()); if(p_derivative) { @@ -740,8 +957,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const Lanczos&, bool if(result < tools::min_value()) return s0; // Safeguard: series can't cope with denorms. ibeta_series_t s(a, b, x, result); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); - result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter, s0); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + result = ibeta_series_sum(s, s0, max_iter, pol); policies::check_series_iterations("boost::math::ibeta<%1%>(%1%, %1%, %1%) in ibeta_series (with lanczos)", max_iter, pol); return result; } @@ -750,7 +967,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const Lanczos&, bool // #ifndef BOOST_MATH_HAS_GPU_SUPPORT template -BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const boost::math::lanczos::undefined_lanczos& l, bool normalised, T* p_derivative, T y, const Policy& pol) +BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const BOOST_MATH_NAMESPACE::lanczos::undefined_lanczos& l, bool normalised, T* p_derivative, T y, const Policy& pol) { BOOST_MATH_STD_USING @@ -776,14 +993,14 @@ BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const boost::math::la result = pow(x * c / a, a) * pow(c / b, b) * scaled_tgamma_no_lanczos(c, pol) / (scaled_tgamma_no_lanczos(a, pol) * scaled_tgamma_no_lanczos(b, pol)); } else if ((a < 1) && (b > 1)) - result = pow(x, a) / (boost::math::tgamma(a, pol) * boost::math::tgamma_delta_ratio(b, a, pol)); + result = pow(x, a) / (BOOST_MATH_NAMESPACE::tgamma(a, pol) * BOOST_MATH_NAMESPACE::tgamma_delta_ratio(b, a, pol)); else { T power = pow(x, a); T bet = beta_imp(a, b, l, pol); - if (!(boost::math::isnormal)(power) || !(boost::math::isnormal)(bet)) + if (!(BOOST_MATH_NAMESPACE::isnormal)(power) || !(BOOST_MATH_NAMESPACE::isnormal)(bet)) { - result = exp(a * log(x) + boost::math::lgamma(c, pol) - boost::math::lgamma(a, pol) - boost::math::lgamma(b, pol)); + result = exp(a * log(x) + BOOST_MATH_NAMESPACE::lgamma(c, pol) - BOOST_MATH_NAMESPACE::lgamma(a, pol) - BOOST_MATH_NAMESPACE::lgamma(b, pol)); } else result = power / bet; @@ -802,8 +1019,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const boost::math::la if(result < tools::min_value()) return s0; // Safeguard: series can't cope with denorms. ibeta_series_t s(a, b, x, result); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); - result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter, s0); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + result = ibeta_series_sum(s, s0, max_iter, pol); policies::check_series_iterations("boost::math::ibeta<%1%>(%1%, %1%, %1%) in ibeta_series (without lanczos)", max_iter, pol); return result; } @@ -814,22 +1031,26 @@ BOOST_MATH_GPU_ENABLED T ibeta_series(T a, T b, T x, T s0, const boost::math::la template struct ibeta_fraction2_t { - typedef boost::math::pair result_type; + typedef BOOST_MATH_NAMESPACE::pair result_type; BOOST_MATH_GPU_ENABLED ibeta_fraction2_t(T a_, T b_, T x_, T y_) : a(a_), b(b_), x(x_), y(y_), m(0) {} BOOST_MATH_GPU_ENABLED result_type operator()() { - T denom = (a + 2 * m - 1); - T aN = (m * (a + m - 1) / denom) * ((a + b + m - 1) / denom) * (b - m) * x * x; + return term(m++); + } - T bN = static_cast(m); - bN += (m * (b - m) * x) / (a + 2*m - 1); - bN += ((a + m) * (a * y - b * x + 1 + m *(2 - x))) / (a + 2*m + 1); + // The n'th numerator and denominator of the fraction: + BOOST_MATH_GPU_ENABLED result_type term(int n) const + { + T denom = (a + 2 * n - 1); + T aN = (n * (a + n - 1) / denom) * ((a + b + n - 1) / denom) * (b - n) * x * x; - ++m; + T bN = static_cast(n); + bN += (n * (b - n) * x) / (a + 2*n - 1); + bN += ((a + n) * (a * y - b * x + 1 + n *(2 - x))) / (a + 2*n + 1); - return boost::math::make_pair(aN, bN); + return BOOST_MATH_NAMESPACE::make_pair(aN, bN); } private: @@ -837,6 +1058,34 @@ struct ibeta_fraction2_t int m; }; // +// Value of the continued fraction, and the number of terms used in max_terms. The forward (Lentz) +// evaluation multiplies together one factor per term and their rounding errors add up to several eps, and +// it stops as soon as one factor is within eps of one, which can leave a tail of several eps when the +// fraction converges slowly. So once we know how many terms are needed, evaluate again from the tail, +// from twice as many terms, which damps the rounding errors. +// +template +BOOST_MATH_GPU_ENABLED inline T ibeta_fraction2_value(T a, T b, T x, T y, BOOST_MATH_NAMESPACE::uintmax_t& max_terms, const Policy&) +{ + ibeta_fraction2_t f(a, b, x, y); + BOOST_MATH_NAMESPACE::uintmax_t limit = max_terms; + T fract = BOOST_MATH_NAMESPACE::tools::continued_fraction_b(f, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_terms); + if(max_terms < limit / 2) + { + BOOST_MATH_NAMESPACE::uintmax_t terms = 2 * max_terms; + T tail = 0; + for(BOOST_MATH_NAMESPACE::uintmax_t m = terms; m > 0; --m) + { + BOOST_MATH_NAMESPACE::pair t = f.term(static_cast(m)); + tail = t.first / (t.second + tail); + } + T refined = f.term(0).second + tail; + if((BOOST_MATH_NAMESPACE::isfinite)(refined)) + fract = refined; + } + return fract; +} +// // Evaluate the incomplete beta via the continued fraction representation: // template @@ -853,15 +1102,31 @@ BOOST_MATH_GPU_ENABLED inline T ibeta_fraction2(T a, T b, T x, T y, const Policy if(result == 0) return result; - ibeta_fraction2_t f(a, b, x, y); - boost::math::uintmax_t max_terms = boost::math::policies::get_max_series_iterations(); - T fract = boost::math::tools::continued_fraction_b(f, boost::math::policies::get_epsilon(), max_terms); - boost::math::policies::check_series_iterations("boost::math::ibeta", max_terms, pol); + BOOST_MATH_NAMESPACE::uintmax_t max_terms = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T fract = ibeta_fraction2_value(a, b, x, y, max_terms, pol); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::ibeta", max_terms, pol); BOOST_MATH_INSTRUMENT_VARIABLE(fract); BOOST_MATH_INSTRUMENT_VARIABLE(result); return result / fract; } // +// The complement of ibeta_series: (normalised ? 1 : beta(a, b)) - ibeta_series(a, b, x). The series has +// the rounding error of its prefix, a few eps, which the subtraction multiplies by S / (1 - S). So when +// S > 1/2 and x is not small, compute the complement itself, from the continued fraction for the same +// function with a and b (and x and y) exchanged. Its rounding errors grow like 1 / sqrt(x) as that +// fraction becomes degenerate at y = 1 - x near 1, which is why it is only used for x >= 0.02, where +// it takes about 60 terms. +// +template +BOOST_MATH_GPU_ENABLED T ibeta_series_complement(T a, T b, T x, bool normalised, T* p_derivative, T y, const Policy& pol) +{ + typedef typename lanczos::lanczos::type lanczos_type; + T s = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol); + if(normalised && (s > 0.5f) && (x >= 0.02f)) + return ibeta_fraction2(b, a, y, x, pol, true, static_cast(nullptr)); + return (normalised ? T(1) : BOOST_MATH_NAMESPACE::beta(a, b, pol)) - s; +} +// // Computes the difference between ibeta(a,b,x) and ibeta(a+k,b,x): // template @@ -933,10 +1198,10 @@ struct Pn_size // but it's hard to quantify exactly: #ifndef BOOST_MATH_HAS_NVRTC static constexpr unsigned value = - ::boost::math::max_factorial::value >= 100 ? 50 - : ::boost::math::max_factorial::value >= ::boost::math::max_factorial::value ? 30 - : ::boost::math::max_factorial::value >= ::boost::math::max_factorial::value ? 15 : 1; - static_assert(::boost::math::max_factorial::value >= ::boost::math::max_factorial::value, "Type does not provide for 35-50 digits of accuracy."); + ::BOOST_MATH_NAMESPACE::max_factorial::value >= 100 ? 50 + : ::BOOST_MATH_NAMESPACE::max_factorial::value >= ::BOOST_MATH_NAMESPACE::max_factorial::value ? 30 + : ::BOOST_MATH_NAMESPACE::max_factorial::value >= ::BOOST_MATH_NAMESPACE::max_factorial::value ? 15 : 1; + static_assert(::BOOST_MATH_NAMESPACE::max_factorial::value >= ::BOOST_MATH_NAMESPACE::max_factorial::value, "Type does not provide for 35-50 digits of accuracy."); #else static constexpr unsigned value = 0; // Will never be called #endif @@ -946,7 +1211,7 @@ struct Pn_size { static constexpr unsigned value = 15; // ~8-15 digit accuracy #ifndef BOOST_MATH_HAS_GPU_SUPPORT - static_assert(::boost::math::max_factorial::value >= 30, "Type does not provide for 8-15 digits of accuracy."); + static_assert(::BOOST_MATH_NAMESPACE::max_factorial::value >= 30, "Type does not provide for 8-15 digits of accuracy."); #endif }; template <> @@ -954,7 +1219,7 @@ struct Pn_size { static constexpr unsigned value = 30; // 16-20 digit accuracy #ifndef BOOST_MATH_HAS_GPU_SUPPORT - static_assert(::boost::math::max_factorial::value >= 60, "Type does not provide for 16-20 digits of accuracy."); + static_assert(::BOOST_MATH_NAMESPACE::max_factorial::value >= 60, "Type does not provide for 16-20 digits of accuracy."); #endif }; template <> @@ -962,7 +1227,7 @@ struct Pn_size { static constexpr unsigned value = 50; // ~35-50 digit accuracy #ifndef BOOST_MATH_HAS_GPU_SUPPORT - static_assert(::boost::math::max_factorial::value >= 100, "Type does not provide for ~35-50 digits of accuracy"); + static_assert(::BOOST_MATH_NAMESPACE::max_factorial::value >= 100, "Type does not provide for ~35-50 digits of accuracy"); #endif }; @@ -980,7 +1245,7 @@ BOOST_MATH_GPU_ENABLED T beta_small_b_large_a_series(T a, T b, T x, T y, T s0, T T t = a + bm1 / 2; T lx, u; // LCOV_EXCL_LINE if(y < 0.35) - lx = boost::math::log1p(-y, pol); + lx = BOOST_MATH_NAMESPACE::log1p(-y, pol); else lx = log(x); u = -t * lx; @@ -991,7 +1256,7 @@ BOOST_MATH_GPU_ENABLED T beta_small_b_large_a_series(T a, T b, T x, T y, T s0, T return s0; if(normalised) { - prefix = h / boost::math::tgamma_delta_ratio(a, b, pol); + prefix = h / BOOST_MATH_NAMESPACE::tgamma_delta_ratio(a, b, pol); prefix /= pow(t, b); } else @@ -1004,15 +1269,18 @@ BOOST_MATH_GPU_ENABLED T beta_small_b_large_a_series(T a, T b, T x, T y, T s0, T // recursively, and requires a full history of all the previous values // so no choice but to declare a big table and hope it's big enough... // - T p[ ::boost::math::detail::Pn_size::value ] = { 1 }; // see 9.3. + T p[ ::BOOST_MATH_NAMESPACE::detail::Pn_size::value ] = { 1 }; // see 9.3. // // Now an initial value for J, see 9.6: // - T j = boost::math::gamma_q(b, u, pol) / h; + T j = BOOST_MATH_NAMESPACE::gamma_q(b, u, pol) / h; // // Now we can start to pull things together and evaluate the sum in Eq 9: // - T sum = s0 + prefix * j; // Value at N = 0 + // The sum is often started from s0 = -1, when the first term is of order one and each later term + // is rounded onto a coarse grid, so keep their rounding errors in comp (Neumaier summation): + compensated_sum sum(s0); + sum.add(prefix * j); // Value at N = 0 // some variables we'll need: unsigned tnp1 = 1; // 2*N+1 T lx2 = lx / 2; @@ -1044,11 +1312,11 @@ BOOST_MATH_GPU_ENABLED T beta_small_b_large_a_series(T a, T b, T x, T y, T s0, T for(unsigned m = 1; m < n; ++m) { mbn = m * b - n; - p[n] += mbn * p[n-m] / boost::math::unchecked_factorial(tmp1); + p[n] += mbn * p[n-m] / BOOST_MATH_NAMESPACE::unchecked_factorial(tmp1); tmp1 += 2; } p[n] /= n; - p[n] += bm1 / boost::math::unchecked_factorial(tnp1); + p[n] += bm1 / BOOST_MATH_NAMESPACE::unchecked_factorial(tnp1); // // Now we want Jn from Jn-1 using Eq 9.6: // @@ -1059,13 +1327,13 @@ BOOST_MATH_GPU_ENABLED T beta_small_b_large_a_series(T a, T b, T x, T y, T s0, T // pull it together with Eq 9: // T r = prefix * p[n] * j; - sum += r; + sum.add(r); // r is always small: BOOST_MATH_ASSERT(tools::max_value() * tools::epsilon() > fabs(r)); - if(fabs(r / tools::epsilon()) < fabs(sum)) + if(fabs(r / tools::epsilon()) < fabs(sum.sum)) break; } - return sum; + return sum.value(); } // template T beta_small_b_large_a_series(T a, T b, T x, T y, T s0, T mult, const Lanczos& l, bool normalised) // @@ -1077,7 +1345,11 @@ BOOST_MATH_GPU_ENABLED T binomial_ccdf(T n, T k, T x, T y, const Policy& pol) { BOOST_MATH_STD_USING // ADL of std names - T result = pow(x, n); + // + // When x is close to 1 it is y = 1 - x that is known accurately, and + // pow(x, n) would amplify the rounding error in x by a factor of n: + // + T result = (y < T(0.5)) ? T(exp(n * BOOST_MATH_NAMESPACE::log1p(-y, pol))) : T(pow(x, n)); if(result > tools::min_value()) { @@ -1095,17 +1367,26 @@ BOOST_MATH_GPU_ENABLED T binomial_ccdf(T n, T k, T x, T y, const Policy& pol) int start = itrunc(n * x); if(start <= k + 1) start = itrunc(k + 2); - result = static_cast(pow(x, T(start)) * pow(y, n - T(start)) * boost::math::binomial_coefficient(itrunc(n), itrunc(start), pol)); + // + // The term x^i y^(n-i) C(n, i). The binomial coefficient is large and the power of y is not very + // small (n - i < b), but x^i can underflow, or be denormal and have lost most of its digits, while + // the term is still a normal number. So split x^i in two, and multiply the coefficient in between: + // + auto binomial_term = [&](unsigned i) + { + return static_cast(pow(x, T(i / 2)) * (pow(y, n - T(i)) * BOOST_MATH_NAMESPACE::binomial_coefficient(itrunc(n), i, pol)) * pow(x, T(i - i / 2))); + }; + result = binomial_term(start); if(result == 0) { // OK, starting slightly above the mode didn't work, - // we'll have to sum the terms the old fashioned way. + // we'll have to sum all the terms the old fashioned way. // Very hard to get here, possibly only when exponent // range is very limited (as with type float): // LCOV_EXCL_START - for(unsigned i = start - 1; i > k; --i) + for(unsigned i = itrunc(n); i > k; --i) { - result += static_cast(pow(x, static_cast(i)) * pow(y, n - i) * boost::math::binomial_coefficient(itrunc(n), itrunc(i), pol)); + result += binomial_term(i); } // LCOV_EXCL_STOP } @@ -1191,9 +1472,9 @@ BOOST_MATH_GPU_ENABLED T ibeta_large_ab(T a, T b, T x, T y, bool invert, bool no */ T mul = 1; if (!normalised) - mul = boost::math::beta(a, b, pol); + mul = BOOST_MATH_NAMESPACE::beta(a, b, pol); // T log_erf_remainder = -0.5 * log(2 * constants::pi() * (a+b)) + a * log(x / x0) + b * log((1-x) / (1-x0)) + log(abs(1/nu - sqrt(x0 * (1-x0)) / (x-x0))); - return mul * ((invert ? (1 + boost::math::erf(-nu * sqrt((a + b) / 2), pol)) / 2 : boost::math::erfc(-nu * sqrt((a + b) / 2), pol) / 2)); + return mul * ((invert ? (1 + BOOST_MATH_NAMESPACE::erf(-nu * sqrt((a + b) / 2), pol)) / 2 : BOOST_MATH_NAMESPACE::erfc(-nu * sqrt((a + b) / 2), pol) / 2)); } @@ -1224,9 +1505,9 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b BOOST_MATH_ASSERT((p_derivative == 0) || normalised); - if(!(boost::math::isfinite)(a)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(a)) return policies::raise_domain_error(function, "The argument a to the incomplete beta function must be finite (got a=%1%).", a, pol); - if(!(boost::math::isfinite)(b)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(b)) return policies::raise_domain_error(function, "The argument b to the incomplete beta function must be finite (got b=%1%).", b, pol); if (!(0 <= x && x <= 1)) return policies::raise_domain_error(function, "The argument x to the incomplete beta function must be in [0,1] (got x=%1%).", x, pol); @@ -1268,7 +1549,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b { *p_derivative = (a == 1) ? (T)1 : (a < 1) ? T(tools::max_value() / 2) : T(tools::min_value() * 2); } - return (invert ? (normalised ? T(1) : boost::math::beta(a, b, pol)) : T(0)); + return (invert ? (normalised ? T(1) : BOOST_MATH_NAMESPACE::beta(a, b, pol)) : T(0)); } if(x == 1) { @@ -1276,7 +1557,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b { *p_derivative = (b == 1) ? T(1) : (b < 1) ? T(tools::max_value() / 2) : T(tools::min_value() * 2); } - return (invert == 0 ? (normalised ? 1 : boost::math::beta(a, b, pol)) : 0); + return (invert == 0 ? (normalised ? 1 : BOOST_MATH_NAMESPACE::beta(a, b, pol)) : 0); } if((a == 0.5f) && (b == 0.5f)) { @@ -1285,7 +1566,15 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b { *p_derivative = 1 / (constants::pi() * sqrt(y * x)); } - T p = invert ? asin(sqrt(y)) / constants::half_pi() : asin(sqrt(x)) / constants::half_pi(); + T p; // LCOV_EXCL_LINE + if (invert) + { + p = (y < 0.75) ? T(asin(sqrt(y)) / constants::half_pi()) : T(1 - asin(sqrt(x)) / constants::half_pi()); + } + else + { + p = (x > 0.75) ? T(1 - asin(sqrt(y)) / constants::half_pi()) : T(asin(sqrt(x)) / constants::half_pi()); + } if(!normalised) p *= constants::pi(); return p; @@ -1310,13 +1599,14 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b if(p_derivative) { - *p_derivative = a * pow(x, a - 1); + // As for p below: x may be 1 - y with y too small to survive the rounding. + *p_derivative = y < 0.5 ? T(a * exp((a - 1) * BOOST_MATH_NAMESPACE::log1p(-y, pol))) : T(a * pow(x, a - 1)); } T p; // LCOV_EXCL_LINE if(y < 0.5) - p = invert ? T(-boost::math::expm1(a * boost::math::log1p(-y, pol), pol)) : T(exp(a * boost::math::log1p(-y, pol))); + p = invert ? T(-BOOST_MATH_NAMESPACE::expm1(a * BOOST_MATH_NAMESPACE::log1p(-y, pol), pol)) : T(exp(a * BOOST_MATH_NAMESPACE::log1p(-y, pol))); else - p = invert ? T(-boost::math::powm1(x, a, pol)) : T(pow(x, a)); + p = invert ? T(-BOOST_MATH_NAMESPACE::powm1(x, a, pol)) : T(pow(x, a)); if(!normalised) p /= a; return p; @@ -1343,9 +1633,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } else { - fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; - fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); + fract = ibeta_series_complement(a, b, x, normalised, p_derivative, y, pol); BOOST_MATH_INSTRUMENT_VARIABLE(fract); } } @@ -1363,9 +1652,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } else { - fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; - fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); + fract = ibeta_series_complement(a, b, x, normalised, p_derivative, y, pol); BOOST_MATH_INSTRUMENT_VARIABLE(fract); } } @@ -1389,7 +1677,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } else { - fract -= (normalised ? 1 : boost::math::beta(a, b, pol)); + fract -= (normalised ? 1 : BOOST_MATH_NAMESPACE::beta(a, b, pol)); invert = false; fract = -beta_small_b_large_a_series(T(a + 20), b, x, y, fract, prefix, pol, normalised); BOOST_MATH_INSTRUMENT_VARIABLE(fract); @@ -1409,9 +1697,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } else { - fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; - fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); + fract = ibeta_series_complement(a, b, x, normalised, p_derivative, y, pol); BOOST_MATH_INSTRUMENT_VARIABLE(fract); } } @@ -1430,9 +1717,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } else { - fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; - fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); + fract = ibeta_series_complement(a, b, x, normalised, p_derivative, y, pol); BOOST_MATH_INSTRUMENT_VARIABLE(fract); } } @@ -1445,7 +1731,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } else { - fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); + fract = -(normalised ? 1 : BOOST_MATH_NAMESPACE::beta(a, b, pol)); invert = false; fract = -beta_small_b_large_a_series(a, b, x, y, fract, T(1), pol, normalised); BOOST_MATH_INSTRUMENT_VARIABLE(fract); @@ -1472,7 +1758,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } else { - fract -= (normalised ? 1 : boost::math::beta(a, b, pol)); + fract -= (normalised ? 1 : BOOST_MATH_NAMESPACE::beta(a, b, pol)); invert = false; fract = -beta_small_b_large_a_series(T(a + 20), b, x, y, fract, prefix, pol, normalised); BOOST_MATH_INSTRUMENT_VARIABLE(fract); @@ -1503,14 +1789,14 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b if(b < 40) { - if((floor(a) == a) && (floor(b) == b) && (a < static_cast((boost::math::numeric_limits::max)() - 100)) && (y != 1)) + if((floor(a) == a) && (floor(b) == b) && (a < static_cast((BOOST_MATH_NAMESPACE::numeric_limits::max)() - 100)) && (y != 1)) { // relate to the binomial distribution and use a finite sum: T k = a - 1; T n = b + k; fract = binomial_ccdf(n, k, x, y, pol); if(!normalised) - fract *= boost::math::beta(a, b, pol); + fract *= BOOST_MATH_NAMESPACE::beta(a, b, pol); BOOST_MATH_INSTRUMENT_VARIABLE(fract); } else if(b * x <= 0.7) @@ -1522,38 +1808,19 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } else { - fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); + fract = -(normalised ? 1 : BOOST_MATH_NAMESPACE::beta(a, b, pol)); invert = false; fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); BOOST_MATH_INSTRUMENT_VARIABLE(fract); } } - else if(a > 15) + else if((a <= 15) && normalised && (lanczos_type::value > 53) && (lanczos_type::value < lanczos::undefined_lanczos::value)) { - // sidestep so we can use the series representation: - int n = itrunc(T(floor(b)), pol); - if(n == b) - --n; - T bbar = b - n; - T prefix; // LCOV_EXCL_LINE - if(!normalised) - { - prefix = rising_factorial_ratio(T(a+bbar), bbar, n); - } - else - { - prefix = 1; - } - fract = ibeta_a_step(bbar, a, y, x, n, pol, normalised, static_cast(nullptr)); - fract = beta_small_b_large_a_series(a, bbar, x, y, fract, T(1), pol, normalised); - fract /= prefix; - BOOST_MATH_INSTRUMENT_VARIABLE(fract); - } - else if(normalised) - { - // The formula here for the non-normalised case is tricky to figure - // out (for me!!), and requires two pochhammer calculations rather - // than one, so leave it for now and only use this in the normalized case.... + // With a Lanczos approximation above double precision, the continued fraction's prefix + // (ibeta_power_terms) carries the rounding of three Lanczos sums, ~10 eps at 113 bits, and with + // a <= 15 that is no better than sidestepping to the series, and 2x worse well below the mean, + // so keep the sidestep there. The formula for the non-normalised case requires two pochhammer + // calculations rather than one, so the sidestep is only used in the normalised case: int n = itrunc(T(floor(b)), pol); T bbar = b - n; if(bbar <= 0) @@ -1575,6 +1842,13 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } else { + // The continued fraction is accurate to within the error of its prefix and, evaluated from the + // tail, its own rounding errors. Sidestepping to the series with ibeta_a_step and + // beta_small_b_large_a_series lost up to 250 eps near the mean for a > 15, and 10-90 eps for + // 3 <= b < 40. Since x <= a / (a + b) the fraction converges quickly (at most ~80 terms in + // double), and compared with that sidestep, measured against 50 digits near the mean, it has + // the same or smaller maximum error for every b >= 1 (b ~ 1: 4.6 vs 7.1 eps for a >= 15, + // 12.6 vs 14.5 for a < 15) and takes 0.6-0.8 times as long: fract = ibeta_fraction2(a, b, x, y, pol, normalised, p_derivative); BOOST_MATH_INSTRUMENT_VARIABLE(fract); } @@ -1598,7 +1872,6 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b // fraction will not converge. If this occurs, we fall back to the `erf` // approximation. Simply using `ibeta_fraction2` will cause an evaluation // error to be thrown and we won't be able to use the `erf` approximation. - typedef typename lanczos::lanczos::type lanczos_type; T local_result = ibeta_power_terms(a, b, x, y, lanczos_type(), normalised, pol); if (p_derivative) { @@ -1607,10 +1880,9 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } if (local_result != 0) { - ibeta_fraction2_t f(a, b, x, y); - boost::math::uintmax_t max_terms = boost::math::policies::get_max_series_iterations(); - T local_fract = boost::math::tools::continued_fraction_b(f, boost::math::policies::get_epsilon(), max_terms); - if (max_terms >= boost::math::policies::get_max_series_iterations()) + BOOST_MATH_NAMESPACE::uintmax_t max_terms = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T local_fract = ibeta_fraction2_value(a, b, x, y, max_terms, pol); + if (max_terms >= BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()) { // Continued fraction failed, fall back to asymptotic expansion: fract = ibeta_large_ab(a, b, x, y, invert, normalised, pol); @@ -1646,9 +1918,140 @@ BOOST_MATH_GPU_ENABLED T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, b } } } - return invert ? (normalised ? 1 : boost::math::beta(a, b, pol)) - fract : fract; + return invert ? (normalised ? 1 : BOOST_MATH_NAMESPACE::beta(a, b, pol)) - fract : fract; } // template T ibeta_imp(T a, T b, T x, const Lanczos& l, bool inv, bool normalised) +// +// Logarithm of the normalised power terms (x^a)(y^b)/Beta(a,b), for when they underflow. +// This follows ibeta_power_terms branch for branch, but never exponentiates, so it has no +// need of that function's overflow and underflow sidesteps. It is only used where the +// result is large and negative, so the remaining cancellation between the terms is mild. +// +template +BOOST_MATH_GPU_ENABLED T log_ibeta_power_terms(T a, T b, T x, T y, const Lanczos&, const Policy& pol) +{ + BOOST_MATH_STD_USING + + T c = a + b; + T gh = Lanczos::g() - 0.5f; + T agh = static_cast(a + gh); + T bgh = static_cast(b + gh); + T cgh = static_cast(c + gh); + T result = log(Lanczos::lanczos_sum_expG_scaled(c) / (Lanczos::lanczos_sum_expG_scaled(a) * Lanczos::lanczos_sum_expG_scaled(b))); + result += (log(bgh) - 1 + log(agh / cgh)) / 2; + + // l1 and l2 are the bases of the powers minus one, as in ibeta_power_terms, which near the mean also + // needs its exponent's cancellation removed: + T l1, l2; + ibeta_power_bases(a, b, x, y, gh, agh, bgh, cgh, l1, l2); + if(BOOST_MATH_GPU_SAFE_MAX(fabs(l1), fabs(l2)) < 0.5) + { + T l_err; + T l = ibeta_power_log_near_mean(a, b, l1, l2, gh, bgh, pol, l_err); + result += l + l_err; + } + else if((BOOST_MATH_GPU_SAFE_MIN(fabs(l1), fabs(l2)) < 0.2)) + { + if((l1 * l2 > 0) || (BOOST_MATH_GPU_SAFE_MIN(a, b) < 1)) + { + result += fabs(l1) < 0.1 ? T(a * BOOST_MATH_NAMESPACE::log1p(l1, pol)) : T(a * log((x * cgh) / agh)); + result += fabs(l2) < 0.1 ? T(b * BOOST_MATH_NAMESPACE::log1p(l2, pol)) : T(b * log((y * cgh) / bgh)); + } + else if(fabs(l1) < fabs(l2)) + result += a * BOOST_MATH_NAMESPACE::log1p(l1, pol) + b * log((y * cgh) / bgh); + else + result += b * BOOST_MATH_NAMESPACE::log1p(l2, pol) + a * log((x * cgh) / agh); + } + else + result += a * log((x * cgh) / agh) + b * log((y * cgh) / bgh); + return result; +} + +#ifndef BOOST_MATH_HAS_GPU_SUPPORT +template +BOOST_MATH_GPU_ENABLED T log_ibeta_power_terms(T a, T b, T x, T y, const BOOST_MATH_NAMESPACE::lanczos::undefined_lanczos& l, const Policy& pol) +{ + BOOST_MATH_STD_USING + // Only reached when the power terms underflow, which types without a Lanczos approximation, having + // wide exponent ranges, rarely do; then the terms are large and negative and barely cancel: + return a * log(x) + b * log(y) - lbeta_imp(a, b, l, pol); +} +#endif + +// +// Logarithm of the regularised incomplete beta, or of its complement when invert is true. +// +template +BOOST_MATH_GPU_ENABLED T libeta_imp(T a, T b, T x, const Policy& pol, bool invert) +{ + BOOST_MATH_STD_USING + typedef typename lanczos::lanczos::type lanczos_type; + const char* function = invert ? "boost::math::libetac<%1%>(%1%, %1%, %1%)" : "boost::math::libeta<%1%>(%1%, %1%, %1%)"; + + // These checks also reject NaN arguments: + if(!(BOOST_MATH_NAMESPACE::isfinite)(a)) + return policies::raise_domain_error(function, "The argument a to the incomplete beta function must be finite (got a=%1%).", a, pol); + if(!(BOOST_MATH_NAMESPACE::isfinite)(b)) + return policies::raise_domain_error(function, "The argument b to the incomplete beta function must be finite (got b=%1%).", b, pol); + if(!(0 <= x && x <= 1)) + return policies::raise_domain_error(function, "The argument x to the incomplete beta function must be in [0,1] (got x=%1%).", x, pol); + if(a < 0) + return policies::raise_domain_error(function, "The argument a to the incomplete beta function must be >= zero (got a=%1%).", a, pol); + if(b < 0) + return policies::raise_domain_error(function, "The argument b to the incomplete beta function must be >= zero (got b=%1%).", b, pol); + if((a == 0) && (b == 0)) + return policies::raise_domain_error(function, "The arguments a and b to the incomplete beta function cannot both be zero, with x=%1%.", x, pol); + + // Where the target is exactly zero, its log is -infinity. As in ibeta, a == 0 makes P = 1 + // and b == 0 makes P = 0 whatever x is: + bool p_is_zero = (b == 0) || ((a != 0) && (x == 0)); + bool q_is_zero = (a == 0) || ((b != 0) && (x == 1)); + bool target_is_zero = invert ? q_is_zero : p_is_zero; + if(target_is_zero) + { + // -infinity is exact here; as for every other exact infinity, the overflow policy decides: + return -policies::raise_overflow_error(function, nullptr, pol); + } + + // The underflow is ours to handle, so stop ibeta_imp from reporting it: + typedef typename policies::normalise >::type quiet_policy; + + // The target, P = ibeta or Q = ibetac, is accurate in relative terms, so log(target) is fine unless the + // target is near one, when log1p(-other) is better, or underflows. Start with whichever is likely smaller: + // the mean a / (a + b) separates them roughly evenly. + bool target_likely_small = (x * (a + b) <= a) != invert; + if(!target_likely_small) + { + T other = ibeta_imp(a, b, x, quiet_policy(), !invert, true, static_cast(nullptr)); + if(other <= 0.5f) + return BOOST_MATH_NAMESPACE::log1p(-other, pol); + } + T target = ibeta_imp(a, b, x, quiet_policy(), invert, true, static_cast(nullptr)); + if(target > 0.5f) + return BOOST_MATH_NAMESPACE::log1p(-ibeta_imp(a, b, x, quiet_policy(), !invert, true, static_cast(nullptr)), pol); + if(target >= tools::min_value()) + return log(target); + + // The target underflows, so we are far out in its tail, where the continued fraction converges: + // target = power_terms / fraction. The complement is the target with roles swapped. + T y = 1 - x; + if(invert) + { + BOOST_MATH_GPU_SAFE_SWAP(a, b); + BOOST_MATH_GPU_SAFE_SWAP(x, y); + } + if(a == 1) + { + // The fraction's first term is 0/0 here, but P = -expm1(b log1p(-x)) exactly, and since P underflows, + // the argument of expm1 is far below epsilon, so log(P) = log(b) + log(-log1p(-x)) to full precision: + return log(b) + log(-BOOST_MATH_NAMESPACE::log1p(-x, pol)); + } + BOOST_MATH_NAMESPACE::uintmax_t max_terms = policies::get_max_series_iterations(); + T fract = ibeta_fraction2_value(a, b, x, y, max_terms, pol); + policies::check_series_iterations(function, max_terms, pol); + return log_ibeta_power_terms(a, b, x, y, lanczos_type(), pol) - log(fract); +} + template BOOST_MATH_GPU_ENABLED inline T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, bool normalised) { @@ -1662,9 +2065,9 @@ BOOST_MATH_GPU_ENABLED T ibeta_derivative_imp(T a, T b, T x, const Policy& pol) // // start with the usual error checks: // - if (!(boost::math::isfinite)(a)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(a)) return policies::raise_domain_error(function, "The argument a to the incomplete beta function must be finite (got a=%1%).", a, pol); - if (!(boost::math::isfinite)(b)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(b)) return policies::raise_domain_error(function, "The argument b to the incomplete beta function must be finite (got b=%1%).", b, pol); if (!(0 <= x && x <= 1)) return policies::raise_domain_error(function, "The argument x to the incomplete beta function must be in [0,1] (got x=%1%).", x, pol); @@ -1679,12 +2082,12 @@ BOOST_MATH_GPU_ENABLED T ibeta_derivative_imp(T a, T b, T x, const Policy& pol) if(x == 0) { return (a > 1) ? 0 : - (a == 1) ? 1 / boost::math::beta(a, b, pol) : policies::raise_overflow_error(function, nullptr, pol); + (a == 1) ? 1 / BOOST_MATH_NAMESPACE::beta(a, b, pol) : policies::raise_overflow_error(function, nullptr, pol); } else if(x == 1) { return (b > 1) ? 0 : - (b == 1) ? 1 / boost::math::beta(a, b, pol) : policies::raise_overflow_error(function, nullptr, pol); + (b == 1) ? 1 / BOOST_MATH_NAMESPACE::beta(a, b, pol) : policies::raise_overflow_error(function, nullptr, pol); } // // Now the regular cases: @@ -1692,13 +2095,13 @@ BOOST_MATH_GPU_ENABLED T ibeta_derivative_imp(T a, T b, T x, const Policy& pol) typedef typename lanczos::lanczos::type lanczos_type; T y = (1 - x) * x; T f1; - if (!(boost::math::isinf)(1 / y)) + if (!(BOOST_MATH_NAMESPACE::isinf)(1 / y)) { f1 = ibeta_power_terms(a, b, x, 1 - x, lanczos_type(), true, pol, 1 / y, function); } else { - return (a > 1) ? 0 : (a == 1) ? 1 / boost::math::beta(a, b, pol) : policies::raise_overflow_error(function, nullptr, pol); + return (a > 1) ? 0 : (a == 1) ? 1 / BOOST_MATH_NAMESPACE::beta(a, b, pol) : policies::raise_overflow_error(function, nullptr, pol); } return f1; @@ -1708,7 +2111,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_derivative_imp(T a, T b, T x, const Policy& pol) // template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type - beta(RT1 a, RT2 b, const Policy&, const boost::math::true_type*) + beta(RT1 a, RT2 b, const Policy&, const BOOST_MATH_NAMESPACE::true_type*) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -1725,9 +2128,9 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type } template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type - beta(RT1 a, RT2 b, RT3 x, const boost::math::false_type*) + beta(RT1 a, RT2 b, RT3 x, const BOOST_MATH_NAMESPACE::false_type*) { - return boost::math::beta(a, b, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::beta(a, b, x, policies::policy<>()); } } // namespace detail @@ -1736,23 +2139,48 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type // which Lanczos approximation to use // and forward to the implementation functions: // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type beta(RT1 a, RT2 b, A arg) { using tag = typename policies::is_policy::type; using ReturnType = tools::promote_args_t; - return static_cast(boost::math::detail::beta(a, b, arg, static_cast(nullptr))); + return static_cast(BOOST_MATH_NAMESPACE::detail::beta(a, b, arg, static_cast(nullptr))); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type beta(RT1 a, RT2 b) { - return boost::math::beta(a, b, policies::policy<>()); + return BOOST_MATH_NAMESPACE::beta(a, b, policies::policy<>()); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type + lbeta(RT1 a, RT2 b, const Policy&) +{ + BOOST_FPU_EXCEPTION_GUARD + typedef typename tools::promote_args::type result_type; + typedef typename policies::evaluation::type value_type; + typedef typename lanczos::lanczos::type evaluation_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + return policies::checked_narrowing_cast(detail::lbeta_imp(static_cast(a), static_cast(b), evaluation_type(), forwarding_policy()), "boost::math::lbeta<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type + lbeta(RT1 a, RT2 b) +{ + return BOOST_MATH_NAMESPACE::lbeta(a, b, policies::policy<>()); +} + +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type beta(RT1 a, RT2 b, RT3 x, const Policy&) { @@ -1769,7 +2197,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::ibeta_imp(static_cast(a), static_cast(b), static_cast(x), forwarding_policy(), false, false), "boost::math::beta<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type betac(RT1 a, RT2 b, RT3 x, const Policy&) { @@ -1785,14 +2213,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::ibeta_imp(static_cast(a), static_cast(b), static_cast(x), forwarding_policy(), true, false), "boost::math::betac<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type betac(RT1 a, RT2 b, RT3 x) { - return boost::math::betac(a, b, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::betac(a, b, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibeta(RT1 a, RT2 b, RT3 x, const Policy&) { @@ -1808,14 +2236,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::ibeta_imp(static_cast(a), static_cast(b), static_cast(x), forwarding_policy(), false, true), "boost::math::ibeta<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibeta(RT1 a, RT2 b, RT3 x) { - return boost::math::ibeta(a, b, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ibeta(a, b, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibetac(RT1 a, RT2 b, RT3 x, const Policy&) { @@ -1831,14 +2259,64 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::ibeta_imp(static_cast(a), static_cast(b), static_cast(x), forwarding_policy(), true, true), "boost::math::ibetac<%1%>(%1%,%1%,%1%)"); } -template + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline tools::promote_args_t + libeta(RT1 a, RT2 b, RT3 x, const Policy&) +{ + BOOST_FPU_EXCEPTION_GUARD + typedef typename tools::promote_args::type result_type; + typedef typename policies::evaluation::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + value_type result = detail::libeta_imp(static_cast(a), static_cast(b), static_cast(x), forwarding_policy(), false); + return policies::checked_narrowing_cast(result, "boost::math::libeta<%1%>(%1%,%1%,%1%)"); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline tools::promote_args_t + libeta(RT1 a, RT2 b, RT3 x) +{ + return BOOST_MATH_NAMESPACE::libeta(a, b, x, policies::policy<>()); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline tools::promote_args_t + libetac(RT1 a, RT2 b, RT3 x, const Policy&) +{ + BOOST_FPU_EXCEPTION_GUARD + typedef typename tools::promote_args::type result_type; + typedef typename policies::evaluation::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + value_type result = detail::libeta_imp(static_cast(a), static_cast(b), static_cast(x), forwarding_policy(), true); + return policies::checked_narrowing_cast(result, "boost::math::libetac<%1%>(%1%,%1%,%1%)"); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline tools::promote_args_t + libetac(RT1 a, RT2 b, RT3 x) +{ + return BOOST_MATH_NAMESPACE::libetac(a, b, x, policies::policy<>()); +} +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibetac(RT1 a, RT2 b, RT3 x) { - return boost::math::ibetac(a, b, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ibetac(a, b, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibeta_derivative(RT1 a, RT2 b, RT3 x, const Policy&) { @@ -1854,15 +2332,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::ibeta_derivative_imp(static_cast(a), static_cast(b), static_cast(x), forwarding_policy()), "boost::math::ibeta_derivative<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibeta_derivative(RT1 a, RT2 b, RT3 x) { - return boost::math::ibeta_derivative(a, b, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ibeta_derivative(a, b, x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #include #include diff --git a/include/boost/math/special_functions/binomial.hpp b/include/boost/math/special_functions/binomial.hpp index 3c49ff30d5..19344f9c62 100644 --- a/include/boost/math/special_functions/binomial.hpp +++ b/include/boost/math/special_functions/binomial.hpp @@ -17,12 +17,12 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T binomial_coefficient(unsigned n, unsigned k, const Policy& pol) { - static_assert(!boost::math::is_integral::value, "Type T must not be an integral type"); + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value, "Type T must not be an integral type"); BOOST_MATH_STD_USING constexpr auto function = "boost::math::binomial_coefficient<%1%>(unsigned, unsigned)"; if(k > n) @@ -44,9 +44,9 @@ BOOST_MATH_GPU_ENABLED T binomial_coefficient(unsigned n, unsigned k, const Poli { // Use the beta function: if(k < n - k) - result = static_cast(k * boost::math::beta(static_cast(k), static_cast(n-k+1), pol)); + result = static_cast(k * BOOST_MATH_NAMESPACE::beta(static_cast(k), static_cast(n-k+1), pol)); else - result = static_cast((n - k) * boost::math::beta(static_cast(k+1), static_cast(n-k), pol)); + result = static_cast((n - k) * BOOST_MATH_NAMESPACE::beta(static_cast(k+1), static_cast(n-k), pol)); if(result == 0) return policies::raise_overflow_error(function, nullptr, pol); result = 1 / result; @@ -71,14 +71,13 @@ BOOST_MATH_GPU_ENABLED inline float binomial_coefficient(binomial_coefficient(n, k, forwarding_policy()), "boost::math::binomial_coefficient<%1%>(unsigned,unsigned)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T binomial_coefficient(unsigned n, unsigned k) { return binomial_coefficient(n, k, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SF_BINOMIAL_HPP diff --git a/include/boost/math/special_functions/cardinal_b_spline.hpp b/include/boost/math/special_functions/cardinal_b_spline.hpp index dfb4cf835d..8c7c910ed2 100644 --- a/include/boost/math/special_functions/cardinal_b_spline.hpp +++ b/include/boost/math/special_functions/cardinal_b_spline.hpp @@ -6,12 +6,16 @@ #ifndef BOOST_MATH_SPECIAL_CARDINAL_B_SPLINE_HPP #define BOOST_MATH_SPECIAL_CARDINAL_B_SPLINE_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif + +#include -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -30,7 +34,7 @@ namespace detail { } } -template +BOOST_MATH_EXPORT template Real cardinal_b_spline(Real x) { static_assert(!std::is_integral::value, "Does not work with integral types."); @@ -91,7 +95,7 @@ Real cardinal_b_spline(Real x) { } -template +BOOST_MATH_EXPORT template Real cardinal_b_spline_prime(Real x) { static_assert(!std::is_integral::value, "Cardinal B-splines do not work with integer types."); @@ -162,7 +166,7 @@ Real cardinal_b_spline_prime(Real x) } -template +BOOST_MATH_EXPORT template Real cardinal_b_spline_double_prime(Real x) { static_assert(!std::is_integral::value, "Cardinal B-splines do not work with integer types."); @@ -207,12 +211,12 @@ Real cardinal_b_spline_double_prime(Real x) } -template +BOOST_MATH_EXPORT template Real forward_cardinal_b_spline(Real x) { static_assert(!std::is_integral::value, "Cardinal B-splines do not work with integral types."); return cardinal_b_spline(x - (n+1)/Real(2)); } -}} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/cbrt.hpp b/include/boost/math/special_functions/cbrt.hpp index 7fdf78d014..1304e1f520 100644 --- a/include/boost/math/special_functions/cbrt.hpp +++ b/include/boost/math/special_functions/cbrt.hpp @@ -22,7 +22,7 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -71,9 +71,9 @@ BOOST_MATH_GPU_ENABLED T cbrt_imp(T z, const Policy& pol) static_cast(1.2599210498948731647672106072782), // 2^1/3 static_cast(1.5874010519681994747517056392723), // 2^2/3 }; - if((boost::math::isinf)(z) || (z == 0)) + if((BOOST_MATH_NAMESPACE::isinf)(z) || (z == 0)) return z; - if(!(boost::math::isfinite)(z)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(z)) { return policies::raise_domain_error("boost::math::cbrt<%1%>(%1%)", "Argument to function must be finite but got %1%.", z, pol); } @@ -158,7 +158,7 @@ BOOST_MATH_GPU_ENABLED T cbrt_imp(T z, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type cbrt(T z, const Policy& pol) { using result_type = typename tools::promote_args::type; @@ -166,21 +166,19 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type cbrt(T z, co return static_cast(detail::cbrt_imp(value_type(z), pol)); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type cbrt(T z) { return cbrt(z, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else // Special NVRTC handling -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED double cbrt(T x) { return ::cbrt(x); @@ -191,20 +189,19 @@ BOOST_MATH_GPU_ENABLED inline float cbrt(float x) return ::cbrtf(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED double cbrt(T x, const Policy&) { return ::cbrt(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED float cbrt(float x, const Policy&) { return ::cbrtf(x); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // NVRTC diff --git a/include/boost/math/special_functions/chebyshev.hpp b/include/boost/math/special_functions/chebyshev.hpp index df8570821f..0f27e81a75 100644 --- a/include/boost/math/special_functions/chebyshev.hpp +++ b/include/boost/math/special_functions/chebyshev.hpp @@ -5,8 +5,10 @@ #ifndef BOOST_MATH_SPECIAL_CHEBYSHEV_HPP #define BOOST_MATH_SPECIAL_CHEBYSHEV_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include #include @@ -21,9 +23,9 @@ # include #endif -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template inline tools::promote_args_t chebyshev_next(T1 const & x, T2 const & Tn, T3 const & Tn_1) { return 2*x*Tn - Tn_1; @@ -63,7 +65,7 @@ inline Real chebyshev_imp(unsigned n, Real const & x, const Policy&) using std::acosh; #define BOOST_MATH_ACOSH_POLICY #else - using boost::math::acosh; + using BOOST_MATH_NAMESPACE::acosh; #define BOOST_MATH_ACOSH_POLICY , Policy() #endif using std::cosh; @@ -110,14 +112,14 @@ inline Real chebyshev_imp(unsigned n, Real const & x, const Policy&) while(l < n) { std::swap(T0, T1); - T1 = static_cast(boost::math::chebyshev_next(x, T0, T1)); + T1 = static_cast(BOOST_MATH_NAMESPACE::chebyshev_next(x, T0, T1)); ++l; } return T1; } } // namespace detail -template +BOOST_MATH_EXPORT template inline tools::promote_args_t chebyshev_t(unsigned n, Real const & x, const Policy&) { using result_type = tools::promote_args_t; @@ -132,13 +134,13 @@ inline tools::promote_args_t chebyshev_t(unsigned n, Real const & x, const return policies::checked_narrowing_cast(detail::chebyshev_imp(n, static_cast(x), forwarding_policy()), "boost::math::chebyshev_t<%1%>(unsigned, %1%)"); } -template +BOOST_MATH_EXPORT template inline tools::promote_args_t chebyshev_t(unsigned n, Real const & x) { return chebyshev_t(n, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline tools::promote_args_t chebyshev_u(unsigned n, Real const & x, const Policy&) { using result_type = tools::promote_args_t; @@ -153,13 +155,13 @@ inline tools::promote_args_t chebyshev_u(unsigned n, Real const & x, const return policies::checked_narrowing_cast(detail::chebyshev_imp(n, static_cast(x), forwarding_policy()), "boost::math::chebyshev_u<%1%>(unsigned, %1%)"); } -template +BOOST_MATH_EXPORT template inline tools::promote_args_t chebyshev_u(unsigned n, Real const & x) { return chebyshev_u(n, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline tools::promote_args_t chebyshev_t_prime(unsigned n, Real const & x, const Policy&) { using result_type = tools::promote_args_t; @@ -177,7 +179,7 @@ inline tools::promote_args_t chebyshev_t_prime(unsigned n, Real const & x, return policies::checked_narrowing_cast(n * detail::chebyshev_imp(n - 1, static_cast(x), forwarding_policy()), "boost::math::chebyshev_t_prime<%1%>(unsigned, %1%)"); } -template +BOOST_MATH_EXPORT template inline tools::promote_args_t chebyshev_t_prime(unsigned n, Real const & x) { return chebyshev_t_prime(n, x, policies::policy<>()); @@ -191,10 +193,10 @@ inline tools::promote_args_t chebyshev_t_prime(unsigned n, Real const & x) * https://www.siam.org/books/ot99/OT99SampleChapter.pdf * However, our definition of c0 differs by a factor of 1/2, as stated in the docs. . . */ -template +BOOST_MATH_EXPORT template inline Real chebyshev_clenshaw_recurrence(const Real* const c, size_t length, const T2& x) { - using boost::math::constants::half; + using BOOST_MATH_NAMESPACE::constants::half; if (length < 2) { if (length == 0) @@ -291,7 +293,7 @@ inline Real unchecked_chebyshev_clenshaw_recurrence(const Real* const c, size_t } // namespace detail -template +BOOST_MATH_EXPORT template inline Real chebyshev_clenshaw_recurrence(const Real* const c, size_t length, const Real & a, const Real & b, const Real& x) { if (x < a || x > b) @@ -309,6 +311,6 @@ inline Real chebyshev_clenshaw_recurrence(const Real* const c, size_t length, co return detail::unchecked_chebyshev_clenshaw_recurrence(c, length, a, b, x); } -}} // Namespace boost::math +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_CHEBYSHEV_HPP diff --git a/include/boost/math/special_functions/chebyshev_transform.hpp b/include/boost/math/special_functions/chebyshev_transform.hpp index 20390be6e0..748e3bf621 100644 --- a/include/boost/math/special_functions/chebyshev_transform.hpp +++ b/include/boost/math/special_functions/chebyshev_transform.hpp @@ -5,118 +5,94 @@ #ifndef BOOST_MATH_SPECIAL_CHEBYSHEV_TRANSFORM_HPP #define BOOST_MATH_SPECIAL_CHEBYSHEV_TRANSFORM_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#include +#include +#include #include +#include +#endif #include #include +#include +#include +#include +#include -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - -#ifdef __has_include -# if __has_include() -# include -# else -# error "This feature is unavailable without fftw3 installed" -#endif -#endif - -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ -template -struct fftw_cos_transform; - -template<> -struct fftw_cos_transform +// The type II discrete cosine transform with FFTW's REDFT10 normalisation, +// +// y[k] = 2 sum_{j=0}^{n-1} x[j] cos(pi*k*(2j+1)/(2n)), +// +// computed with one real FFT of length n (Makhoul, IEEE Trans. ASSP 28(1), 1980): +// with v[j] = x[2j] and v[n-1-j] = x[2j+1], and V the DFT of v, +// y[k] = 2 Re(exp(-i*pi*k/(2n)) V[k]) and y[n-k] = -2 Im(exp(-i*pi*k/(2n)) V[k]). +template +class dct_ii { - fftw_cos_transform(int n, double* data1, double* data2) - { - plan = fftw_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE); - } - ~fftw_cos_transform() - { - fftw_destroy_plan(plan); - } - void execute(double* data1, double* data2) - { - fftw_execute_r2r(plan, data1, data2); - } - static double cos(double x) { return std::cos(x); } - static double fabs(double x) { return std::fabs(x); } -private: - fftw_plan plan; -}; +public: + using complex_type = BOOST_MATH_NAMESPACE::tools::detail::complex_from_real_t; -template<> -struct fftw_cos_transform -{ - fftw_cos_transform(int n, float* data1, float* data2) - { - plan = fftwf_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE); - } - ~fftw_cos_transform() + explicit dct_ii(std::size_t n) : m_n(n), m_fft(n), m_v(n), m_V(n / 2 + 1), m_cos(n / 2 + 1), m_sin(n / 2 + 1) { - fftwf_destroy_plan(plan); + // exp(-i*pi*k/(2n)) = cos - i sin for k in [0, n/2]; the argument k/(2n) has at most one rounding. + for (std::size_t k = 0; k <= n / 2; ++k) + { + Real x = static_cast(k) / static_cast(2 * n); + m_cos[k] = BOOST_MATH_NAMESPACE::cos_pi(x); + m_sin[k] = BOOST_MATH_NAMESPACE::sin_pi(x); + } } - void execute(float* data1, float* data2) - { - fftwf_execute_r2r(plan, data1, data2); - } - static float cos(float x) { return std::cos(x); } - static float fabs(float x) { return std::fabs(x); } -private: - fftwf_plan plan; -}; -template<> -struct fftw_cos_transform -{ - fftw_cos_transform(int n, long double* data1, long double* data2) + // In place: replaces the n values at x with their transform. + void execute(Real* x) { - plan = fftwl_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE); + execute(x, x); } - ~fftw_cos_transform() - { - fftwl_destroy_plan(plan); - } - void execute(long double* data1, long double* data2) - { - fftwl_execute_r2r(plan, data1, data2); - } - static long double cos(long double x) { return std::cos(x); } - static long double fabs(long double x) { return std::fabs(x); } -private: - fftwl_plan plan; -}; -#ifdef BOOST_HAS_FLOAT128 -template<> -struct fftw_cos_transform<__float128> -{ - fftw_cos_transform(int n, __float128* data1, __float128* data2) - { - plan = fftwq_plan_r2r_1d(n, data1, data2, FFTW_REDFT10, FFTW_ESTIMATE); - } - ~fftw_cos_transform() - { - fftwq_destroy_plan(plan); - } - void execute(__float128* data1, __float128* data2) + + // Reads n values from x and writes n values to y. x and y are either the same array (all of x is read + // into the workspace before y is written) or don't overlap. Any n > 0 works, odd or even; the constructor + // allocates all the workspace, so execute never allocates. + void execute(const Real* x, Real* y) { - fftwq_execute_r2r(plan, data1, data2); + for (std::size_t j = 0; 2 * j < m_n; ++j) + { + m_v[j] = x[2 * j]; + } + for (std::size_t j = 0; 2 * j + 1 < m_n; ++j) + { + m_v[m_n - 1 - j] = x[2 * j + 1]; + } + m_fft.transform(m_v, m_V); + for (std::size_t k = 0; k <= m_n / 2; ++k) + { + Real vr = m_V[k].real(); + Real vi = m_V[k].imag(); + // (cos - i sin)(vr + i vi) + y[k] = 2 * (m_cos[k] * vr + m_sin[k] * vi); + if (k != 0 && m_n - k != k) + { + y[m_n - k] = -2 * (m_cos[k] * vi - m_sin[k] * vr); + } + } } - static __float128 cos(__float128 x) { return cosq(x); } - static __float128 fabs(__float128 x) { return fabsq(x); } + private: - fftwq_plan plan; + std::size_t m_n; + BOOST_MATH_NAMESPACE::tools::real_fft m_fft; + std::vector m_v; + std::vector m_V; + std::vector m_cos; + std::vector m_sin; }; -#endif } -template +BOOST_MATH_EXPORT template class chebyshev_transform { public: @@ -129,9 +105,7 @@ class chebyshev_transform { throw std::domain_error("a < b is required.\n"); } - using boost::math::constants::half; - using boost::math::constants::pi; - using std::cos; + using BOOST_MATH_NAMESPACE::constants::half; using std::abs; Real bma = (b-a)*half(); Real bpa = (b+a)*half(); @@ -144,23 +118,23 @@ class chebyshev_transform vf.resize(n); m_coeffs.resize(n); - detail::fftw_cos_transform plan(static_cast(n), vf.data(), m_coeffs.data()); + detail::dct_ii dct(n); Real inv_n = 1/static_cast(n); for(size_t j = 0; j < n/2; ++j) { // Use symmetry cos((j+1/2)pi/n) = - cos((n-1-j+1/2)pi/n) - Real y = detail::fftw_cos_transform::cos(pi()*(j+half())*inv_n); + Real y = BOOST_MATH_NAMESPACE::cos_pi(static_cast(2*j+1)/static_cast(2*n)); vf[j] = f(y*bma + bpa)*inv_n; vf[n-1-j]= f(bpa-y*bma)*inv_n; } - plan.execute(vf.data(), m_coeffs.data()); + dct.execute(vf.data(), m_coeffs.data()); Real max_coeff = 0; for (auto const & coeff : m_coeffs) { - if (detail::fftw_cos_transform::fabs(coeff) > max_coeff) + if (abs(coeff) > max_coeff) { - max_coeff = detail::fftw_cos_transform::fabs(coeff); + max_coeff = abs(coeff); } } size_t j = m_coeffs.size() - 1; @@ -233,5 +207,5 @@ class chebyshev_transform Real m_b; }; -}} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/cos_pi.hpp b/include/boost/math/special_functions/cos_pi.hpp index 7c33614de7..b14b5a0ce7 100644 --- a/include/boost/math/special_functions/cos_pi.hpp +++ b/include/boost/math/special_functions/cos_pi.hpp @@ -15,15 +15,17 @@ #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include #include #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T cos_pi_imp(T x, const Policy&) @@ -39,7 +41,7 @@ BOOST_MATH_GPU_ENABLED T cos_pi_imp(T x, const Policy&) x = -x; } T rem = floor(x); - if(abs(floor(rem/2)*2 - rem) > boost::math::numeric_limits::epsilon()) + if(abs(floor(rem/2)*2 - rem) > BOOST_MATH_NAMESPACE::numeric_limits::epsilon()) { invert = !invert; } @@ -64,7 +66,7 @@ BOOST_MATH_GPU_ENABLED T cos_pi_imp(T x, const Policy&) } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type cos_pi(T x, const Policy&) { typedef typename tools::promote_args::type result_type; @@ -78,24 +80,22 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type cos_pi(T x, // We want to ignore overflows since the result is in [-1,1] and the // check slows the code down considerably. policies::overflow_error >::type forwarding_policy; - return policies::checked_narrowing_cast(boost::math::detail::cos_pi_imp(x, forwarding_policy()), "cos_pi"); + return policies::checked_narrowing_cast(BOOST_MATH_NAMESPACE::detail::cos_pi_imp(x, forwarding_policy()), "cos_pi"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type cos_pi(T x) { - return boost::math::cos_pi(x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::cos_pi(x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else // Special handling for NVRTC -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto cos_pi(T x) { return ::cospi(x); @@ -107,20 +107,19 @@ BOOST_MATH_GPU_ENABLED auto cos_pi(float x) return ::cospif(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto cos_pi(T x, const Policy&) { return ::cospi(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto cos_pi(float x, const Policy&) { return ::cospif(x); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC diff --git a/include/boost/math/special_functions/daubechies_scaling.hpp b/include/boost/math/special_functions/daubechies_scaling.hpp index fe9d7b16d1..a7d48ec303 100644 --- a/include/boost/math/special_functions/daubechies_scaling.hpp +++ b/include/boost/math/special_functions/daubechies_scaling.hpp @@ -8,6 +8,7 @@ #ifndef BOOST_MATH_SPECIAL_DAUBECHIES_SCALING_HPP #define BOOST_MATH_SPECIAL_DAUBECHIES_SCALING_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#endif #include #include #include @@ -31,14 +33,14 @@ # endif #endif -namespace boost::math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template std::vector daubechies_scaling_dyadic_grid(int64_t j_max) { using std::isnan; using std::sqrt; - auto c = boost::math::filters::daubechies_scaling_filter(); + auto c = BOOST_MATH_NAMESPACE::filters::daubechies_scaling_filter(); Real scale = sqrt(static_cast(2))*(1 << order); for (auto & x : c) { @@ -100,50 +102,6 @@ std::vector daubechies_scaling_dyadic_grid(int64_t j_max) namespace detail { -template -class matched_holder { -public: - using Real = typename RandomAccessContainer::value_type; - - matched_holder(RandomAccessContainer && y, RandomAccessContainer && dydx, int grid_refinements, Real x0) : x0_{x0}, y_{std::move(y)}, dy_{std::move(dydx)} - { - inv_h_ = (1 << grid_refinements); - Real h = 1/inv_h_; - for (auto & dy : dy_) - { - dy *= h; - } - } - - inline Real operator()(Real x) const - { - using std::floor; - using std::sqrt; - // This is the exact Holder exponent, but it's pessimistic almost everywhere! - // It's only exactly right at dyadic rationals. - //Real const alpha = 2 - log(1+sqrt(Real(3)))/log(Real(2)); - // We're gonna use alpha = 1/2, rather than 0.5500... - Real s = (x-x0_)*inv_h_; - Real ii = floor(s); - auto i = static_cast(ii); - Real t = s - ii; - Real dphi = dy_[i+1]; - Real diff = y_[i+1] - y_[i]; - return y_[i] + (2*dphi - diff)*t + 2*sqrt(t)*(diff-dphi); - } - - int64_t bytes() const - { - return 2*y_.size()*sizeof(Real) + sizeof(*this); - } - -private: - Real x0_; - Real inv_h_; - RandomAccessContainer y_; - RandomAccessContainer dy_; -}; - template class matched_holder_aos { public: @@ -187,50 +145,6 @@ class matched_holder_aos { }; -template -class linear_interpolation { -public: - using Real = typename RandomAccessContainer::value_type; - - linear_interpolation(RandomAccessContainer && y, RandomAccessContainer && dydx, int grid_refinements) : y_{std::move(y)}, dydx_{std::move(dydx)} - { - s_ = (1 << grid_refinements); - } - - inline Real operator()(Real x) const - { - using std::floor; - Real y = x*s_; - Real k = floor(y); - - int64_t kk = static_cast(k); - Real t = y - k; - return (1-t)*y_[kk] + t*y_[kk+1]; - } - - inline Real prime(Real x) const - { - using std::floor; - - Real y = x*s_; - Real k = floor(y); - - int64_t kk = static_cast(k); - Real t = y - k; - return static_cast((Real(1)-t)*dydx_[kk] + t*dydx_[kk+1]); - } - - int64_t bytes() const - { - return (1 + y_.size() + dydx_.size())*sizeof(Real) + sizeof(y_) + sizeof(dydx_); - } - -private: - Real s_; - RandomAccessContainer y_; - RandomAccessContainer dydx_; -}; - template class linear_interpolation_aos { public: @@ -322,7 +236,7 @@ struct null_interpolator } // namespace detail -template +BOOST_MATH_EXPORT template class daubechies_scaling { // // Some type manipulation so we know the type of the interpolator, and the vector type it requires: @@ -487,5 +401,5 @@ class daubechies_scaling { std::shared_ptr m_interpolator; }; -} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/daubechies_wavelet.hpp b/include/boost/math/special_functions/daubechies_wavelet.hpp index d374c84870..60141576c3 100644 --- a/include/boost/math/special_functions/daubechies_wavelet.hpp +++ b/include/boost/math/special_functions/daubechies_wavelet.hpp @@ -7,12 +7,14 @@ #ifndef BOOST_MATH_SPECIAL_DAUBECHIES_WAVELET_HPP #define BOOST_MATH_SPECIAL_DAUBECHIES_WAVELET_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include +#endif #include #include #include @@ -29,9 +31,9 @@ #endif #endif -namespace boost::math { +BOOST_MATH_NAMESPACE_BEGIN - template + BOOST_MATH_EXPORT template std::vector daubechies_wavelet_dyadic_grid(int64_t j_max) { if (j_max == 0) @@ -41,8 +43,8 @@ namespace boost::math { auto phijk = daubechies_scaling_dyadic_grid(j_max - 1); //psi_j[l] = psi(-p+1 + l/2^j) = \sum_{k=0}^{2p-1} (-1)^k c_k \phi(1-2p+k + l/2^{j-1}) //For derivatives just map c_k -> 2^order c_k. - auto d = boost::math::filters::daubechies_scaling_filter(); - Real scale = boost::math::constants::root_two() * (1 << order); + auto d = BOOST_MATH_NAMESPACE::filters::daubechies_scaling_filter(); + Real scale = BOOST_MATH_NAMESPACE::constants::root_two() * (1 << order); for (size_t i = 0; i < d.size(); ++i) { d[i] *= scale; @@ -75,7 +77,7 @@ namespace boost::math { } - template + BOOST_MATH_EXPORT template class daubechies_wavelet { // // Some type manipulation so we know the type of the interpolator, and the vector type it requires: @@ -261,6 +263,6 @@ namespace boost::math { std::shared_ptr m_interpolator; }; -} +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_DAUBECHIES_WAVELET_HPP diff --git a/include/boost/math/special_functions/detail/airy_ai_bi_zero.hpp b/include/boost/math/special_functions/detail/airy_ai_bi_zero.hpp index e518422f17..27bc72e397 100644 --- a/include/boost/math/special_functions/detail/airy_ai_bi_zero.hpp +++ b/include/boost/math/special_functions/detail/airy_ai_bi_zero.hpp @@ -18,7 +18,7 @@ #include #include - namespace boost { namespace math { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { // Forward declarations of the needed Airy function implementations. @@ -39,7 +39,7 @@ const T one_over_z (T(1) / z); const T one_over_z_squared(one_over_z * one_over_z); - const T z_pow_third (boost::math::cbrt(z, pol)); + const T z_pow_third (BOOST_MATH_NAMESPACE::cbrt(z, pol)); const T z_pow_two_thirds(z_pow_third * z_pow_third); // Implement the top line of Eq. 10.4.105. @@ -96,8 +96,8 @@ guess = T(-12.8287767528657572004); break; default: - const T t(((boost::math::constants::pi() * 3) * ((T(m) * 4) - 1)) / 8); - guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t, pol); + const T t(((BOOST_MATH_NAMESPACE::constants::pi() * 3) * ((T(m) * 4) - 1)) / 8); + guess = -BOOST_MATH_NAMESPACE::detail::airy_zero::equation_as_10_4_105(t, pol); break; } @@ -120,12 +120,12 @@ # pragma nv_diag_default 20012 #endif - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(const T& x) const + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(const T& x) const { // Return a tuple containing both Ai(x) and Ai'(x). - return boost::math::make_tuple( - boost::math::detail::airy_ai_imp (x, my_pol), - boost::math::detail::airy_ai_prime_imp(x, my_pol)); + return BOOST_MATH_NAMESPACE::make_tuple( + BOOST_MATH_NAMESPACE::detail::airy_ai_imp (x, my_pol), + BOOST_MATH_NAMESPACE::detail::airy_ai_prime_imp(x, my_pol)); } private: @@ -177,8 +177,8 @@ guess = T(-12.3864171385827387456); break; default: - const T t(((boost::math::constants::pi() * 3) * ((T(m) * 4) - 3)) / 8); - guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t, pol); + const T t(((BOOST_MATH_NAMESPACE::constants::pi() * 3) * ((T(m) * 4) - 3)) / 8); + guess = -BOOST_MATH_NAMESPACE::detail::airy_zero::equation_as_10_4_105(t, pol); break; } @@ -201,12 +201,12 @@ # pragma nv_diag_default 20012 #endif - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(const T& x) const + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(const T& x) const { // Return a tuple containing both Bi(x) and Bi'(x). - return boost::math::make_tuple( - boost::math::detail::airy_bi_imp (x, my_pol), - boost::math::detail::airy_bi_prime_imp(x, my_pol)); + return BOOST_MATH_NAMESPACE::make_tuple( + BOOST_MATH_NAMESPACE::detail::airy_bi_imp (x, my_pol), + BOOST_MATH_NAMESPACE::detail::airy_bi_prime_imp(x, my_pol)); } private: @@ -216,7 +216,6 @@ } // namespace airy_bi_zero_detail } // namespace airy_zero } // namespace detail - } // namespace math - } // namespaces boost + BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_AIRY_AI_BI_ZERO_2013_01_20_HPP_ diff --git a/include/boost/math/special_functions/detail/bernoulli_details.hpp b/include/boost/math/special_functions/detail/bernoulli_details.hpp index 3dbc9b575d..1b2e314036 100644 --- a/include/boost/math/special_functions/detail/bernoulli_details.hpp +++ b/include/boost/math/special_functions/detail/bernoulli_details.hpp @@ -13,16 +13,20 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #if defined(BOOST_MATH_HAS_THREADS) && !defined(BOOST_NO_CXX11_HDR_MUTEX) && !defined(BOOST_MATH_NO_ATOMIC_INT) +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #else # define BOOST_MATH_BERNOULLI_NOTHREADS #endif -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // // Asymptotic expansion for B2n due to // Luschny LogB3 formula (http://www.luschny.de/math/primes/bernincl.html) @@ -35,9 +39,9 @@ T b2n_asymptotic(int n) const T nx2(nx * nx); const T approximate_log_of_bernoulli_bn = - ((boost::math::constants::half() + nx) * log(nx)) - + ((boost::math::constants::half() - nx) * log(boost::math::constants::pi())) - + (((T(3) / 2) - nx) * boost::math::constants::ln_two()) + ((BOOST_MATH_NAMESPACE::constants::half() + nx) * log(nx)) + + ((BOOST_MATH_NAMESPACE::constants::half() - nx) * log(BOOST_MATH_NAMESPACE::constants::pi())) + + (((T(3) / 2) - nx) * BOOST_MATH_NAMESPACE::constants::ln_two()) + ((nx * (T(2) - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520)); return ((n / 2) & 1 ? 1 : -1) * (approximate_log_of_bernoulli_bn > tools::log_max_value() ? policies::raise_overflow_error("boost::math::bernoulli_b2n<%1%>(std::size_t)", nullptr, nx, Policy()) @@ -91,9 +95,9 @@ struct max_bernoulli_root_functor const double nx2(n * n); const double approximate_log_of_bernoulli_bn - = ((boost::math::constants::half() + n) * log(n)) - + ((boost::math::constants::half() - n) * log(boost::math::constants::pi())) - + (((static_cast(3) / 2) - n) * boost::math::constants::ln_two()) + = ((BOOST_MATH_NAMESPACE::constants::half() + n) * log(n)) + + ((BOOST_MATH_NAMESPACE::constants::half() - n) * log(BOOST_MATH_NAMESPACE::constants::pi())) + + (((static_cast(3) / 2) - n) * BOOST_MATH_NAMESPACE::constants::ln_two()) + ((n * (2 - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520)); return approximate_log_of_bernoulli_bn - target; @@ -108,11 +112,11 @@ inline std::size_t find_bernoulli_overflow_limit(const std::false_type&) // Set a limit on how large the result can ever be: static const auto max_result = static_cast((std::numeric_limits::max)() - 1000u); - unsigned long long t = static_cast(lltrunc(boost::math::tools::log_max_value())); + unsigned long long t = static_cast(lltrunc(BOOST_MATH_NAMESPACE::tools::log_max_value())); max_bernoulli_root_functor fun(t); - boost::math::tools::equal_floor tol; - std::uintmax_t max_iter = boost::math::policies::get_max_root_iterations(); - double result = boost::math::tools::toms748_solve(fun, sqrt(static_cast(t)), static_cast(t), tol, max_iter).first / 2; + BOOST_MATH_NAMESPACE::tools::equal_floor tol; + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_root_iterations(); + double result = BOOST_MATH_NAMESPACE::tools::toms748_solve(fun, sqrt(static_cast(t)), static_cast(t), tol, max_iter).first / 2; if (result > max_result) { result = max_result; @@ -226,7 +230,7 @@ class bernoulli_numbers_cache public: bernoulli_numbers_cache() : m_overflow_limit((std::numeric_limits::max)()) , m_counter(0) - , m_current_precision(boost::math::tools::digits()) + , m_current_precision(BOOST_MATH_NAMESPACE::tools::digits()) {} using container_type = fixed_vector; @@ -257,9 +261,9 @@ class bernoulli_numbers_cache for(std::size_t i = std::max(2, prev_size); i < m; i++) { bool overflow_check = false; - if(i >= min_overflow_index && (boost::math::tools::max_value() / (i-1) < m_intermediates[1]) ) + if(i >= min_overflow_index && (BOOST_MATH_NAMESPACE::tools::max_value() / (i-1) < m_intermediates[1]) ) { - std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value()); + std::fill(tn.begin() + i, tn.end(), BOOST_MATH_NAMESPACE::tools::max_value()); break; } m_intermediates[1] = m_intermediates[1] * (i-1); @@ -267,15 +271,15 @@ class bernoulli_numbers_cache { overflow_check = (i >= min_overflow_index) && ( - (boost::math::tools::max_value() / (i - j) < m_intermediates[j]) - || (boost::math::tools::max_value() / (i - j + 2) < m_intermediates[j-1]) - || (boost::math::tools::max_value() - m_intermediates[j] * (i - j) < m_intermediates[j-1] * (i - j + 2)) - || ((boost::math::isinf)(m_intermediates[j])) + (BOOST_MATH_NAMESPACE::tools::max_value() / (i - j) < m_intermediates[j]) + || (BOOST_MATH_NAMESPACE::tools::max_value() / (i - j + 2) < m_intermediates[j-1]) + || (BOOST_MATH_NAMESPACE::tools::max_value() - m_intermediates[j] * (i - j) < m_intermediates[j-1] * (i - j + 2)) + || ((BOOST_MATH_NAMESPACE::isinf)(m_intermediates[j])) ); if(overflow_check) { - std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value()); + std::fill(tn.begin() + i, tn.end(), BOOST_MATH_NAMESPACE::tools::max_value()); break; } m_intermediates[j] = m_intermediates[j] * (i - j) + m_intermediates[j-1] * (i - j + 2); @@ -391,12 +395,12 @@ class bernoulli_numbers_cache // // Single threaded code, very simple: // - if(m_current_precision < boost::math::tools::digits()) + if(m_current_precision < BOOST_MATH_NAMESPACE::tools::digits()) { bn.clear(); tn.clear(); m_intermediates.clear(); - m_current_precision = boost::math::tools::digits(); + m_current_precision = BOOST_MATH_NAMESPACE::tools::digits(); } if(start + n >= bn.size()) { @@ -420,20 +424,20 @@ class bernoulli_numbers_cache // Get the counter and see if we need to calculate more constants: // if((static_cast(m_counter.load(std::memory_order_consume)) < start + n) - || (static_cast(m_current_precision.load(std::memory_order_consume)) < boost::math::tools::digits())) + || (static_cast(m_current_precision.load(std::memory_order_consume)) < BOOST_MATH_NAMESPACE::tools::digits())) { std::lock_guard l(m_mutex); if((static_cast(m_counter.load(std::memory_order_consume)) < start + n) - || (static_cast(m_current_precision.load(std::memory_order_consume)) < boost::math::tools::digits())) + || (static_cast(m_current_precision.load(std::memory_order_consume)) < BOOST_MATH_NAMESPACE::tools::digits())) { - if(static_cast(m_current_precision.load(std::memory_order_consume)) < boost::math::tools::digits()) + if(static_cast(m_current_precision.load(std::memory_order_consume)) < BOOST_MATH_NAMESPACE::tools::digits()) { bn.clear(); tn.clear(); m_intermediates.clear(); m_counter.store(0, std::memory_order_release); - m_current_precision = boost::math::tools::digits(); + m_current_precision = BOOST_MATH_NAMESPACE::tools::digits(); } if(start + n >= bn.size()) { @@ -499,12 +503,12 @@ class bernoulli_numbers_cache // // Single threaded code, very simple: // - if(m_current_precision < boost::math::tools::digits()) + if(m_current_precision < BOOST_MATH_NAMESPACE::tools::digits()) { bn.clear(); tn.clear(); m_intermediates.clear(); - m_current_precision = boost::math::tools::digits(); + m_current_precision = BOOST_MATH_NAMESPACE::tools::digits(); } if(start + n >= bn.size()) { @@ -536,20 +540,20 @@ class bernoulli_numbers_cache // Get the counter and see if we need to calculate more constants: // if((static_cast(m_counter.load(std::memory_order_consume)) < start + n) - || (static_cast(m_current_precision.load(std::memory_order_consume)) < boost::math::tools::digits())) + || (static_cast(m_current_precision.load(std::memory_order_consume)) < BOOST_MATH_NAMESPACE::tools::digits())) { std::lock_guard l(m_mutex); if((static_cast(m_counter.load(std::memory_order_consume)) < start + n) - || (static_cast(m_current_precision.load(std::memory_order_consume)) < boost::math::tools::digits())) + || (static_cast(m_current_precision.load(std::memory_order_consume)) < BOOST_MATH_NAMESPACE::tools::digits())) { - if(static_cast(m_current_precision.load(std::memory_order_consume)) < boost::math::tools::digits()) + if(static_cast(m_current_precision.load(std::memory_order_consume)) < BOOST_MATH_NAMESPACE::tools::digits()) { bn.clear(); tn.clear(); m_intermediates.clear(); m_counter.store(0, std::memory_order_release); - m_current_precision = boost::math::tools::digits(); + m_current_precision = BOOST_MATH_NAMESPACE::tools::digits(); } if(start + n >= bn.size()) { @@ -624,6 +628,6 @@ inline typename std::enable_if::digits && (std::numeric_l return data; } -}}} +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BERNOULLI_DETAIL_HPP diff --git a/include/boost/math/special_functions/detail/bessel_derivatives_linear.hpp b/include/boost/math/special_functions/detail/bessel_derivatives_linear.hpp index ca62f38a5b..d2c126bfc9 100644 --- a/include/boost/math/special_functions/detail/bessel_derivatives_linear.hpp +++ b/include/boost/math/special_functions/detail/bessel_derivatives_linear.hpp @@ -9,40 +9,42 @@ // Linear combination for bessel derivatives are defined here #ifndef BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP #define BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #ifdef _MSC_VER #pragma once #endif -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template inline T bessel_j_derivative_linear(T v, T x, Tag tag, Policy pol) { - return (boost::math::detail::cyl_bessel_j_imp(v-1, x, tag, pol) - boost::math::detail::cyl_bessel_j_imp(v+1, x, tag, pol)) / 2; + return (BOOST_MATH_NAMESPACE::detail::cyl_bessel_j_imp(v-1, x, tag, pol) - BOOST_MATH_NAMESPACE::detail::cyl_bessel_j_imp(v+1, x, tag, pol)) / 2; } template inline T bessel_j_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol) { - return (boost::math::detail::cyl_bessel_j_imp(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_bessel_j_imp(itrunc(v+1), x, tag, pol)) / 2; + return (BOOST_MATH_NAMESPACE::detail::cyl_bessel_j_imp(itrunc(v-1), x, tag, pol) - BOOST_MATH_NAMESPACE::detail::cyl_bessel_j_imp(itrunc(v+1), x, tag, pol)) / 2; } template inline T sph_bessel_j_derivative_linear(unsigned v, T x, Policy pol) { - return (v / x) * boost::math::detail::sph_bessel_j_imp(v, x, pol) - boost::math::detail::sph_bessel_j_imp(v+1, x, pol); + return (v / x) * BOOST_MATH_NAMESPACE::detail::sph_bessel_j_imp(v, x, pol) - BOOST_MATH_NAMESPACE::detail::sph_bessel_j_imp(v+1, x, pol); } template inline T bessel_i_derivative_linear(T v, T x, Policy pol) { - T result = boost::math::detail::cyl_bessel_i_imp(v - 1, x, pol); + T result = BOOST_MATH_NAMESPACE::detail::cyl_bessel_i_imp(v - 1, x, pol); if(result >= tools::max_value()) return result; // result is infinite // Both experimentally, and based on https://www.wolframalpha.com/input?i=BesselI%5Bv%2C+x%5D%2FBesselI%5Bv%2B2%2C+x%5D // I[v + 1, x] < I[v-1, x], so this can't overflow: - T result2 = boost::math::detail::cyl_bessel_i_imp(v + 1, x, pol); + T result2 = BOOST_MATH_NAMESPACE::detail::cyl_bessel_i_imp(v + 1, x, pol); return result / 2 + result2 / 2; } @@ -50,12 +52,12 @@ inline T bessel_i_derivative_linear(T v, T x, Policy pol) template inline T bessel_k_derivative_linear(T v, T x, Tag tag, Policy pol) { - T result = boost::math::detail::cyl_bessel_k_imp(v - 1, x, tag, pol); + T result = BOOST_MATH_NAMESPACE::detail::cyl_bessel_k_imp(v - 1, x, tag, pol); if(result >= tools::max_value()) return -result; // result is infinite - T result2 = boost::math::detail::cyl_bessel_k_imp(v + 1, x, tag, pol); + T result2 = BOOST_MATH_NAMESPACE::detail::cyl_bessel_k_imp(v + 1, x, tag, pol); if(result2 >= tools::max_value() + result) - return -boost::math::policies::raise_overflow_error("cyl_bessel_k_prime<%1>", 0, pol); // result is infinite + return -BOOST_MATH_NAMESPACE::policies::raise_overflow_error("cyl_bessel_k_prime<%1>", 0, pol); // result is infinite result /= -2; result2 /= -2; return result + result2; @@ -64,12 +66,12 @@ inline T bessel_k_derivative_linear(T v, T x, Tag tag, Policy pol) template inline T bessel_k_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol) { - T result = boost::math::detail::cyl_bessel_k_imp(itrunc(v - 1), x, tag, pol); + T result = BOOST_MATH_NAMESPACE::detail::cyl_bessel_k_imp(itrunc(v - 1), x, tag, pol); if (result >= tools::max_value()) return -result; // result is infinite - T result2 = boost::math::detail::cyl_bessel_k_imp(itrunc(v + 1), x, tag, pol); + T result2 = BOOST_MATH_NAMESPACE::detail::cyl_bessel_k_imp(itrunc(v + 1), x, tag, pol); if (result2 >= tools::max_value() + result) - return -boost::math::policies::raise_overflow_error("cyl_bessel_k_prime<%1>", 0, pol); // result is infinite + return -BOOST_MATH_NAMESPACE::policies::raise_overflow_error("cyl_bessel_k_prime<%1>", 0, pol); // result is infinite result /= -2; result2 /= -2; return result + result2; @@ -87,21 +89,21 @@ inline T bessel_k_derivative_linear(T v, T x, const bessel_maybe_int_tag&, Polic template inline T bessel_y_derivative_linear(T v, T x, Tag tag, Policy pol) { - return (boost::math::detail::cyl_neumann_imp(v-1, x, tag, pol) - boost::math::detail::cyl_neumann_imp(v+1, x, tag, pol)) / 2; + return (BOOST_MATH_NAMESPACE::detail::cyl_neumann_imp(v-1, x, tag, pol) - BOOST_MATH_NAMESPACE::detail::cyl_neumann_imp(v+1, x, tag, pol)) / 2; } template inline T bessel_y_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol) { - return (boost::math::detail::cyl_neumann_imp(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_neumann_imp(itrunc(v+1), x, tag, pol)) / 2; + return (BOOST_MATH_NAMESPACE::detail::cyl_neumann_imp(itrunc(v-1), x, tag, pol) - BOOST_MATH_NAMESPACE::detail::cyl_neumann_imp(itrunc(v+1), x, tag, pol)) / 2; } template inline T sph_neumann_derivative_linear(unsigned v, T x, Policy pol) { - return (v / x) * boost::math::detail::sph_neumann_imp(v, x, pol) - boost::math::detail::sph_neumann_imp(v+1, x, pol); + return (v / x) * BOOST_MATH_NAMESPACE::detail::sph_neumann_imp(v, x, pol) - BOOST_MATH_NAMESPACE::detail::sph_neumann_imp(v+1, x, pol); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP diff --git a/include/boost/math/special_functions/detail/bessel_i0.hpp b/include/boost/math/special_functions/detail/bessel_i0.hpp index f2219cc940..fc022c7000 100644 --- a/include/boost/math/special_functions/detail/bessel_i0.hpp +++ b/include/boost/math/special_functions/detail/bessel_i0.hpp @@ -36,20 +36,20 @@ // see http://www.advanpix.com/2015/11/11/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i0-computations-double-precision // The actual coefficients used are our own, and extend Pavel's work to precision's other than double. -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T bessel_i0(const T& x); template -BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T&, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T&, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_ASSERT(0); return 0; } template -BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x < 7.75) @@ -68,7 +68,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c 1.48095934745267240e-11f }; T a = x * x / 4; - return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + return a * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) + 1; } else if(x < 50) { @@ -81,7 +81,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c 1.35614940793742178e-02f, 1.31409251787866793e-01f }; - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else { @@ -93,14 +93,14 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c 2.94835666900682535e-02f }; T ex = exp(x / 2); - T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + T result = ex * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); result *= ex; return result; } } template -BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x < 7.75) @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c 9.07926920085624812e-25 }; T a = x * x / 4; - return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + return a * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) + 1; } else if(x < 500) { @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c -3.08675715295370878e+15, 2.17587543863819074e+15 }; - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else { @@ -170,14 +170,14 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c 4.53371208762579442e-02 }; T ex = exp(x / 2); - T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + T result = ex * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); result *= ex; return result; } } template -BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x < 7.75) @@ -206,7 +206,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c }; // LCOV_EXCL_STOP T a = x * x / 4; - return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + return a * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) + 1; } else if(x < 10) { @@ -232,7 +232,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 64, 9.504921137873298402679e+05) }; // LCOV_EXCL_STOP - return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x); + return exp(x) * (BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x); } else if(x < 15) { @@ -259,7 +259,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 64, -4.727797957441040896878e+07) }; // LCOV_EXCL_STOP - return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x); + return exp(x) * (BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x); } else if(x < 50) { @@ -287,7 +287,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 64, 4.482292669974971387738e+09) }; // LCOV_EXCL_STOP - return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x); + return exp(x) * (BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x); } else { @@ -317,14 +317,14 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c }; // LCOV_EXCL_STOP T ex = exp(x / 2); - T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + T result = ex * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); result *= ex; return result; } } template -BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x < 7.75) @@ -360,7 +360,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c }; // LCOV_EXCL_STOP T a = x * x / 4; - return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + return a * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) + 1; } else if(x < 15) { @@ -400,7 +400,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c }; // LCOV_EXCL_STOP T a = x * x / 4; - return a * boost::math::tools::evaluate_polynomial(P, a) + 1; + return a * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) + 1; } else if(x < 30) { @@ -441,7 +441,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 113, -2.8809536950051955163648980306847791014734e+28) }; // LCOV_EXCL_STOP - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else if(x < 100) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 113, 5.6392664899881014534361728644608549445131e+16) }; // LCOV_EXCL_STOP - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else { @@ -504,23 +504,23 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c }; // LCOV_EXCL_STOP T ex = exp(x / 2); - T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + T result = ex * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); result *= ex; return result; } } template -BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { - if(boost::math::tools::digits() <= 24) - return bessel_i0_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 53) - return bessel_i0_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 64) - return bessel_i0_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 113) - return bessel_i0_imp(x, boost::math::integral_constant()); + if(BOOST_MATH_NAMESPACE::tools::digits() <= 24) + return bessel_i0_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 53) + return bessel_i0_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 64) + return bessel_i0_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 113) + return bessel_i0_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); BOOST_MATH_ASSERT(0); return 0; } @@ -528,23 +528,23 @@ BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_c template BOOST_MATH_GPU_ENABLED inline T bessel_i0(const T& x) { - typedef boost::math::integral_constant::digits == 0) || (boost::math::numeric_limits::radix != 2)) ? + typedef BOOST_MATH_NAMESPACE::integral_constant::digits == 0) || (BOOST_MATH_NAMESPACE::numeric_limits::radix != 2)) ? 0 : - boost::math::numeric_limits::digits <= 24 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 24 ? 24 : - boost::math::numeric_limits::digits <= 53 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 53 ? 53 : - boost::math::numeric_limits::digits <= 64 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 64 ? 64 : - boost::math::numeric_limits::digits <= 113 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 113 ? 113 : -1 > tag_type; return bessel_i0_imp(x, tag_type()); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_I0_HPP diff --git a/include/boost/math/special_functions/detail/bessel_i1.hpp b/include/boost/math/special_functions/detail/bessel_i1.hpp index 17e8389622..194e65c757 100644 --- a/include/boost/math/special_functions/detail/bessel_i1.hpp +++ b/include/boost/math/special_functions/detail/bessel_i1.hpp @@ -40,20 +40,20 @@ // minimax rational approximations on intervals, see // Blair and Edwards, Chalk River Report AECL-4928, 1974 -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T bessel_i1(const T& x); template -BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T&, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T&, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_ASSERT(0); return 0; } template -BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x < 7.75) @@ -71,8 +71,8 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c 1.331933703e-12f }; T a = x * x / 4; - T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; - return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + T Q[3] = { 1, 0.5f, BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) }; + return x * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, a) / 2; } else { @@ -87,14 +87,14 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c -1.47148600683672014e-01f }; T ex = exp(x / 2); - T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + T result = ex * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); result *= ex; return result; } } template -BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x < 7.75) @@ -119,8 +119,8 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c 1.332898928162290861e-23 }; T a = x * x / 4; - T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; - return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + T Q[3] = { 1, 0.5f, BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) }; + return x * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, a) / 2; } else if(x < 500) { @@ -151,7 +151,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c 3.146401654361325073e+15, -2.213318202179221945e+15 }; - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else { @@ -165,14 +165,14 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c -5.843630344778927582e-02 }; T ex = exp(x / 2); - T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + T result = ex * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); result *= ex; return result; } } template -BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x < 7.75) @@ -198,8 +198,8 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 64, 1.95294659305369207813486871e-28) }; T a = x * x / 4; - T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; - return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + T Q[3] = { 1, 0.5f, BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) }; + return x * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, a) / 2; } else if(x < 20) { @@ -231,7 +231,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 64, -5.02808138522587680348583e+14), BOOST_MATH_BIG_CONSTANT(T, 64, 2.85505477056514919387171e+14) }; - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else if(x < 100) { @@ -256,7 +256,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 64, 9.98109660274422449523837e+03), BOOST_MATH_BIG_CONSTANT(T, 64, -3.74438822767781410362757e+04) }; - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else { @@ -274,14 +274,14 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 64, -9.17266479586791298924367e-01) }; T ex = exp(x / 2); - T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + T result = ex * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); result *= ex; return result; } } template -BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x < 7.75) @@ -315,8 +315,8 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 113, 8.2335693685833531118863552173880047183822e-47) }; T a = x * x / 4; - T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; - return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + T Q[3] = { 1, 0.5f, BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) }; + return x * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, a) / 2; } else if(x < 11) { @@ -351,8 +351,8 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 113, 1.407918492276267527897751358794783640e-46) }; T a = x * x / 4; - T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; - return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + T Q[3] = { 1, 0.5f, BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) }; + return x * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, a) / 2; } else if(x < 15) { @@ -387,8 +387,8 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 113, 6.732372906742845717148185173723304360e-52) }; T a = x * x / 4; - T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) }; - return x * boost::math::tools::evaluate_polynomial(Q, a) / 2; + T Q[3] = { 1, 0.5f, BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, a) }; + return x * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, a) / 2; } else if(x < 20) { @@ -419,7 +419,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 113, 3.669871448568623680543943144842394531e+18), BOOST_MATH_BIG_CONSTANT(T, 113, -2.813923031370708069940575240509912588e+18) }; - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else if(x < 35) { @@ -454,7 +454,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 113, -2.249149337812510200795436107962504749e+22), BOOST_MATH_BIG_CONSTANT(T, 113, 2.101619088427348382058085685849420866e+22) }; - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else if(x < 100) { @@ -484,7 +484,7 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 113, 1.396791306321498426110315039064592443e+12), BOOST_MATH_BIG_CONSTANT(T, 113, -4.217617301585849875301440316301068439e+12) }; - return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + return exp(x) * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); } else { @@ -510,23 +510,23 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c BOOST_MATH_BIG_CONSTANT(T, 113, -6.7008089049178178697338128837158732831105e+05) }; T ex = exp(x / 2); - T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); + T result = ex * BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x); result *= ex; return result; } } template -BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { - if(boost::math::tools::digits() <= 24) - return bessel_i1_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 53) - return bessel_i1_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 64) - return bessel_i1_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 113) - return bessel_i1_imp(x, boost::math::integral_constant()); + if(BOOST_MATH_NAMESPACE::tools::digits() <= 24) + return bessel_i1_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 53) + return bessel_i1_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 64) + return bessel_i1_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 113) + return bessel_i1_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); BOOST_MATH_ASSERT(0); return 0; } @@ -534,23 +534,23 @@ BOOST_MATH_GPU_ENABLED T bessel_i1_imp(const T& x, const boost::math::integral_c template BOOST_MATH_GPU_ENABLED inline T bessel_i1(const T& x) { - typedef boost::math::integral_constant::digits == 0) || (boost::math::numeric_limits::radix != 2)) ? + typedef BOOST_MATH_NAMESPACE::integral_constant::digits == 0) || (BOOST_MATH_NAMESPACE::numeric_limits::radix != 2)) ? 0 : - boost::math::numeric_limits::digits <= 24 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 24 ? 24 : - boost::math::numeric_limits::digits <= 53 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 53 ? 53 : - boost::math::numeric_limits::digits <= 64 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 64 ? 64 : - boost::math::numeric_limits::digits <= 113 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 113 ? 113 : -1 > tag_type; return bessel_i1_imp(x, tag_type()); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_I1_HPP diff --git a/include/boost/math/special_functions/detail/bessel_ik.hpp b/include/boost/math/special_functions/detail/bessel_ik.hpp index b0ae7cadb7..2f0b526db1 100644 --- a/include/boost/math/special_functions/detail/bessel_ik.hpp +++ b/include/boost/math/special_functions/detail/bessel_ik.hpp @@ -25,7 +25,7 @@ // Modified Bessel functions of the first and second kind of fractional order -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -62,20 +62,20 @@ BOOST_MATH_GPU_ENABLED inline T bessel_i_small_z_series(T v, T x, const Policy& T prefix; if(v < max_factorial::value) { - prefix = pow(x / 2, v) / boost::math::tgamma(v + 1, pol); + prefix = pow(x / 2, v) / BOOST_MATH_NAMESPACE::tgamma(v + 1, pol); } else { - prefix = v * log(x / 2) - boost::math::lgamma(v + 1, pol); + prefix = v * log(x / 2) - BOOST_MATH_NAMESPACE::lgamma(v + 1, pol); prefix = exp(prefix); } if(prefix == 0) return prefix; cyl_bessel_i_small_z s(v, x); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); policies::check_series_iterations("boost::math::bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol); return prefix * result; @@ -91,8 +91,8 @@ BOOST_MATH_GPU_ENABLED int temme_ik(T v, T x, T* result_K, T* K1, const Policy& unsigned long k; BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; // |x| <= 2, Temme series converge rapidly @@ -100,14 +100,14 @@ BOOST_MATH_GPU_ENABLED int temme_ik(T v, T x, T* result_K, T* K1, const Policy& BOOST_MATH_ASSERT(abs(x) <= 2); BOOST_MATH_ASSERT(abs(v) <= 0.5f); - T gp = boost::math::tgamma1pm1(v, pol); - T gm = boost::math::tgamma1pm1(-v, pol); + T gp = BOOST_MATH_NAMESPACE::tgamma1pm1(v, pol); + T gm = BOOST_MATH_NAMESPACE::tgamma1pm1(-v, pol); a = log(x / 2); b = exp(v * a); sigma = -a * v; c = abs(v) < tools::epsilon() ? - T(1) : T(boost::math::sin_pi(v, pol) / (v * pi())); + T(1) : T(BOOST_MATH_NAMESPACE::sin_pi(v, pol) / (v * pi())); d = abs(sigma) < tools::epsilon() ? T(1) : T(sinh(sigma) / sigma); gamma1 = abs(v) < tools::epsilon() ? @@ -208,10 +208,10 @@ BOOST_MATH_GPU_ENABLED int CF1_ik(T v, T x, T* fv, const Policy& pol) // z1 / z0 = U(v+1.5, 2v+1, 2x) / U(v+0.5, 2v+1, 2x), see // Thompson and Barnett, Computer Physics Communications, vol 47, 245 (1987) template -BOOST_MATH_GPU_ENABLED int CF2_ik(T v, T x, T* Kv, T* Kv1, const Policy& pol) +BOOST_MATH_GPU_ENABLED int CF2_ik(T v, T x, T* Kv, T* Kv1, T* Kv_scaled, T* Kv1_scaled, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; T S, C, Q, D, f, a, b, q, delta, tolerance, current, prev; unsigned long k; @@ -282,11 +282,17 @@ BOOST_MATH_GPU_ENABLED int CF2_ik(T v, T x, T* Kv, T* Kv1, const Policy& pol) } policies::check_series_iterations("boost::math::bessel_ik<%1%>(%1%,%1%) in CF2_ik", k, pol); + const T ratio = (0.5f + v + x + (v * v - 0.25f) * f) / x; if(-x < tools::log_min_value()) *Kv = exp(0.5f * log(pi() / (2 * x)) - x - log(S)); else *Kv = sqrt(pi() / (2 * x)) * exp(-x) / S; - *Kv1 = *Kv * (0.5f + v + x + (v * v - 0.25f) * f) / x; + *Kv1 = *Kv * ratio; + if ((*Kv < tools::min_value()) || (*Kv1 < tools::min_value())) + { + *Kv_scaled = sqrt(pi() / 2) / sqrt(x) / S; + *Kv1_scaled = *Kv_scaled * ratio; + } BOOST_MATH_INSTRUMENT_VARIABLE(*Kv); BOOST_MATH_INSTRUMENT_VARIABLE(*Kv1); @@ -305,9 +311,10 @@ BOOST_MATH_GPU_ENABLED int bessel_ik(T v, T x, T* result_I, T* result_K, int kin { // Kv1 = K_(v+1), fv = I_(v+1) / I_v // Ku1 = K_(u+1), fu = I_(u+1) / I_u - T u, Iv, Kv, Kv1, Ku, Ku1, fv; + T u, Iv, Kv, Kv1, Ku, Ku1, Ku_scaled = 0, Ku1_scaled = 0, fv; T W, current, prev, next; bool reflect = false; + bool use_scaled_k = false; unsigned n, k; int org_kind = kind; BOOST_MATH_INSTRUMENT_VARIABLE(v); @@ -315,8 +322,8 @@ BOOST_MATH_GPU_ENABLED int bessel_ik(T v, T x, T* result_I, T* result_K, int kin BOOST_MATH_INSTRUMENT_VARIABLE(kind); BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; constexpr auto function = "boost::math::bessel_ik<%1%>(%1%,%1%)"; @@ -329,6 +336,7 @@ BOOST_MATH_GPU_ENABLED int bessel_ik(T v, T x, T* result_I, T* result_K, int kin T scale = 1; T scale_sign = 1; + int exp2_scale = 0; n = iround(v, pol); u = v - n; // -1/2 <= u < 1/2 @@ -338,7 +346,7 @@ BOOST_MATH_GPU_ENABLED int bessel_ik(T v, T x, T* result_I, T* result_K, int kin if (((kind & need_i) == 0) && (fabs(4 * v * v - 25) / (8 * x) < tools::forth_root_epsilon())) { // A&S 9.7.2 - Iv = boost::math::numeric_limits::quiet_NaN(); // any value will do + Iv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // any value will do T mu = 4 * v * v; T eight_z = 8 * x; Kv = 1 + (mu - 1) / eight_z + (mu - 1) * (mu - 9) / (2 * eight_z * eight_z) + (mu - 1) * (mu - 9) * (mu - 25) / (6 * eight_z * eight_z * eight_z); @@ -356,12 +364,13 @@ BOOST_MATH_GPU_ENABLED int bessel_ik(T v, T x, T* result_I, T* result_K, int kin } else // x in (2, \infty) { - CF2_ik(u, x, &Ku, &Ku1, pol); // continued fraction CF2_ik + CF2_ik(u, x, &Ku, &Ku1, &Ku_scaled, &Ku1_scaled, pol); // continued fraction CF2_ik } BOOST_MATH_INSTRUMENT_VARIABLE(Ku); BOOST_MATH_INSTRUMENT_VARIABLE(Ku1); - prev = Ku; - current = Ku1; + use_scaled_k = ((kind & need_i) == 0) && (x > 2) && ((Ku < tools::min_value()) || (Ku1 < tools::min_value())); + prev = use_scaled_k ? Ku_scaled : Ku; + current = use_scaled_k ? Ku1_scaled : Ku1; for (k = 1; k <= n; k++) // forward recurrence for K { T fact = 2 * (u + k) / x; @@ -375,10 +384,22 @@ BOOST_MATH_GPU_ENABLED int bessel_ik(T v, T x, T* result_I, T* result_K, int kin : false; if (!will_overflow && ((tools::max_value() - fabs(prev)) / fact < fabs(current))) { - prev /= current; - scale /= current; - scale_sign *= ((boost::math::signbit)(current) ? -1 : 1); - current = 1; + if (use_scaled_k) + { + // Rescale by a power of two so no rounding error is introduced + int e2 = 0; + (void)frexp(current, &e2); + prev = ldexp(prev, -e2); + current = ldexp(current, -e2); + exp2_scale += e2; + } + else + { + prev /= current; + scale /= current; + scale_sign *= ((BOOST_MATH_NAMESPACE::signbit)(current) ? -1 : 1); + current = 1; + } } next = fact * current + prev; prev = current; @@ -414,13 +435,13 @@ BOOST_MATH_GPU_ENABLED int bessel_ik(T v, T x, T* result_I, T* result_K, int kin } } else - Iv = boost::math::numeric_limits::quiet_NaN(); // any value will do + Iv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // any value will do } if (reflect && (kind & need_i)) { BOOST_MATH_ASSERT(fabs(v - n - u) < tools::forth_root_epsilon()); T z = (u + n % 2); - T fact = (2 / pi()) * (boost::math::sin_pi(z, pol) * Kv); + T fact = (2 / pi()) * (BOOST_MATH_NAMESPACE::sin_pi(z, pol) * Kv); if(fact == 0) *result_I = Iv; else if(tools::max_value() * scale < fact) @@ -432,7 +453,40 @@ BOOST_MATH_GPU_ENABLED int bessel_ik(T v, T x, T* result_I, T* result_K, int kin { *result_I = Iv; } - if(tools::max_value() * scale < Kv) + if (use_scaled_k) + { + // Kv currently holds exp(x) * K_v(x) / 2^exp2_scale + int e2 = 0; + const T m = frexp(Kv, &e2); + exp2_scale += e2; + // Split exp(-x) into 2^j equal factors exp(-x / 2^j) that are each representable, + // and spread the binary exponent over them so no partial product leaves range. + T xr = x; + int parts = 1; + while (-xr < tools::log_min_value()) + { + xr /= 2; + parts *= 2; + } + const T factor = exp(-xr); + T result = m; + int e_rem = exp2_scale; + bool overflow = false; + for (int i = 0; i < parts; ++i) + { + const int e_i = e_rem / (parts - i); + e_rem -= e_i; + const T term = ldexp(factor, e_i); + if (result > tools::max_value() / term) + { + overflow = true; + break; + } + result *= term; + } + *result_K = overflow ? ((org_kind & need_k) ? policies::raise_overflow_error(function, nullptr, pol) : T(0)) : result; + } + else if(tools::max_value() * scale < Kv) *result_K = (org_kind & need_k) ? T(sign(Kv) * scale_sign * policies::raise_overflow_error(function, nullptr, pol)) : T(0); else *result_K = Kv / scale; @@ -441,7 +495,7 @@ BOOST_MATH_GPU_ENABLED int bessel_ik(T v, T x, T* result_I, T* result_K, int kin return 0; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_IK_HPP diff --git a/include/boost/math/special_functions/detail/bessel_j0.hpp b/include/boost/math/special_functions/detail/bessel_j0.hpp index 2df027b21d..320ffd301b 100644 --- a/include/boost/math/special_functions/detail/bessel_j0.hpp +++ b/include/boost/math/special_functions/detail/bessel_j0.hpp @@ -30,7 +30,7 @@ // x <= 8, minimax rational approximations on root-bracketing intervals // x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968 -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T bessel_j0(T x); @@ -130,8 +130,8 @@ BOOST_MATH_GPU_ENABLED T bessel_j0(T x) T value, factor, r, rc, rs; BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; BOOST_MATH_ASSERT(x >= 0); // reflection handled elsewhere. @@ -186,7 +186,7 @@ BOOST_MATH_GPU_ENABLED T bessel_j0(T x) return value; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_J0_HPP diff --git a/include/boost/math/special_functions/detail/bessel_j1.hpp b/include/boost/math/special_functions/detail/bessel_j1.hpp index fdb977952c..a953a20ffa 100644 --- a/include/boost/math/special_functions/detail/bessel_j1.hpp +++ b/include/boost/math/special_functions/detail/bessel_j1.hpp @@ -30,7 +30,7 @@ // x <= 8, minimax rational approximations on root-bracketing intervals // x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968 -namespace boost { namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T bessel_j1(T x) @@ -120,8 +120,8 @@ BOOST_MATH_GPU_ENABLED T bessel_j1(T x) T value, factor, r, rc, rs, w; BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; w = abs(x); if (x == 0) @@ -173,7 +173,7 @@ BOOST_MATH_GPU_ENABLED T bessel_j1(T x) return value; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_J1_HPP diff --git a/include/boost/math/special_functions/detail/bessel_jn.hpp b/include/boost/math/special_functions/detail/bessel_jn.hpp index 6400b27875..659ec79cc3 100644 --- a/include/boost/math/special_functions/detail/bessel_jn.hpp +++ b/include/boost/math/special_functions/detail/bessel_jn.hpp @@ -25,7 +25,7 @@ // n < abs(z), forward recurrence stable and usable // n >= abs(z), forward recurrence unstable, use Miller's algorithm -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T bessel_jn(int n, T x, const Policy& pol) @@ -92,7 +92,7 @@ BOOST_MATH_GPU_ENABLED T bessel_jn(int n, T x, const Policy& pol) { T fn; int s; // fn = J_(n+1) / J_n // |x| <= n, fast convergence for continued fraction CF1 - boost::math::detail::CF1_jy(static_cast(n), x, &fn, &s, pol); + BOOST_MATH_NAMESPACE::detail::CF1_jy(static_cast(n), x, &fn, &s, pol); prev = fn; current = 1; // Check recursion won't go on too far: @@ -110,7 +110,11 @@ BOOST_MATH_GPU_ENABLED T bessel_jn(int n, T x, const Policy& pol) prev = current; current = next; } - value = bessel_j0(x) / current; // normalization + // + // Normalize with whichever of J0 and J1 is larger: J0 may be near a zero, + // in which case the recurrence has cancelled all the digits of current. + // + value = (fabs(current) > fabs(prev)) ? bessel_j0(x) / current : bessel_j1(x) / prev; scale = 1 / scale; } value *= factor; @@ -121,7 +125,7 @@ BOOST_MATH_GPU_ENABLED T bessel_jn(int n, T x, const Policy& pol) return value / scale; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_JN_HPP diff --git a/include/boost/math/special_functions/detail/bessel_jy.hpp b/include/boost/math/special_functions/detail/bessel_jy.hpp index 2907f91eeb..f61e1afeee 100644 --- a/include/boost/math/special_functions/detail/bessel_jy.hpp +++ b/include/boost/math/special_functions/detail/bessel_jy.hpp @@ -26,7 +26,7 @@ // Bessel functions of the first and second kind of fractional order -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -79,15 +79,15 @@ namespace boost { namespace math { unsigned long k; BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; BOOST_MATH_ASSERT(fabs(v) <= 0.5f); // precondition for using this routine - T gp = boost::math::tgamma1pm1(v, pol); - T gm = boost::math::tgamma1pm1(-v, pol); - T spv = boost::math::sin_pi(v, pol); - T spv2 = boost::math::sin_pi(v/2, pol); + T gp = BOOST_MATH_NAMESPACE::tgamma1pm1(v, pol); + T gm = BOOST_MATH_NAMESPACE::tgamma1pm1(-v, pol); + T spv = BOOST_MATH_NAMESPACE::sin_pi(v, pol); + T spv2 = BOOST_MATH_NAMESPACE::sin_pi(v/2, pol); T xp = pow(x/2, v); a = log(x / 2); @@ -256,8 +256,8 @@ namespace boost { namespace math { return 0; } - BOOST_MATH_STATIC const int need_j = 1; - BOOST_MATH_STATIC const int need_y = 2; + BOOST_MATH_INLINE_CONSTEXPR int need_j = 1; + BOOST_MATH_INLINE_CONSTEXPR int need_y = 2; // Compute J(v, x) and Y(v, x) simultaneously by Steed's method, see // Barnett et al, Computer Physics Communications, vol 8, 377 (1974) @@ -278,15 +278,15 @@ namespace boost { namespace math { constexpr auto function = "boost::math::bessel_jy<%1%>(%1%,%1%)"; BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; if (v < 0) { reflect = true; v = -v; // v is non-negative from here } - if (v > static_cast((boost::math::numeric_limits::max)())) + if (v > static_cast((BOOST_MATH_NAMESPACE::numeric_limits::max)())) { *J = *Y = policies::raise_evaluation_error(function, "Order of Bessel function is too large to evaluate: got %1%", v, pol); return 1; // LCOV_EXCL_LINE previous line will throw. @@ -297,8 +297,8 @@ namespace boost { namespace math { if(reflect) { T z = (u + n % 2); - cp = boost::math::cos_pi(z, pol); - sp = boost::math::sin_pi(z, pol); + cp = BOOST_MATH_NAMESPACE::cos_pi(z, pol); + sp = BOOST_MATH_NAMESPACE::sin_pi(z, pol); if(u != 0) kind = need_j|need_y; // need both for reflection formula } @@ -312,10 +312,10 @@ namespace boost { namespace math { else if(kind & need_j) *J = policies::raise_domain_error(function, "Value of Bessel J_v(x) is complex-infinity at %1%", x, pol); // complex infinity else - *J = boost::math::numeric_limits::quiet_NaN(); // LCOV_EXCL_LINE, we should never get here, any value will do, not using J. + *J = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // LCOV_EXCL_LINE, we should never get here, any value will do, not using J. if((kind & need_y) == 0) - *Y = boost::math::numeric_limits::quiet_NaN(); // any value will do, not using Y. + *Y = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // any value will do, not using Y. else { // We shoud never get here: @@ -338,7 +338,7 @@ namespace boost { namespace math { // and divergent which leads to large errors :-( // Jv = bessel_j_small_z_series(v, x, pol); - Yv = boost::math::numeric_limits::quiet_NaN(); + Yv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } else if((x < 1) && (u != 0) && (log(policies::get_epsilon() / 2) > v * log((x/2) * (x/2) / v))) { @@ -349,7 +349,7 @@ namespace boost { namespace math { if(kind&need_j) Jv = bessel_j_small_z_series(v, x, pol); else - Jv = boost::math::numeric_limits::quiet_NaN(); + Jv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); if((org_kind&need_y && (!reflect || (cp != 0))) || (org_kind & need_j && (reflect && (sp != 0)))) { @@ -357,7 +357,7 @@ namespace boost { namespace math { Yv = bessel_y_small_z_series(v, x, &Yv_scale, pol); } else - Yv = boost::math::numeric_limits::quiet_NaN(); + Yv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); } else if((u == 0) && (x < policies::get_epsilon())) { @@ -369,7 +369,7 @@ namespace boost { namespace math { if(kind&need_j) Jv = bessel_j_small_z_series(v, x, pol); else - Jv = boost::math::numeric_limits::quiet_NaN(); + Jv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); if((org_kind&need_y && (!reflect || (cp != 0))) || (org_kind & need_j && (reflect && (sp != 0)))) { @@ -377,7 +377,7 @@ namespace boost { namespace math { Yv = bessel_yn_small_z(static_cast(n), x, &Yv_scale, pol); } else - Yv = boost::math::numeric_limits::quiet_NaN(); + Yv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // LCOV_EXCL_STOP } else if(asymptotic_bessel_large_x_limit(v, x)) @@ -387,13 +387,13 @@ namespace boost { namespace math { Yv = asymptotic_bessel_y_large_x_2(v, x, pol); } else - Yv = boost::math::numeric_limits::quiet_NaN(); // any value will do, we're not using it. + Yv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // any value will do, we're not using it. if(kind&need_j) { Jv = asymptotic_bessel_j_large_x_2(v, x, pol); } else - Jv = boost::math::numeric_limits::quiet_NaN(); // any value will do, we're not using it. + Jv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // any value will do, we're not using it. } else if((x > 8) && hankel_PQ(v, x, &p, &q, pol)) { @@ -413,12 +413,12 @@ namespace boost { namespace math { T mod_v = fmod(T(v / 2 + 0.25f), T(2)); T sx = sin(x); T cx = cos(x); - T sv = boost::math::sin_pi(mod_v, pol); - T cv = boost::math::cos_pi(mod_v, pol); + T sv = BOOST_MATH_NAMESPACE::sin_pi(mod_v, pol); + T cv = BOOST_MATH_NAMESPACE::cos_pi(mod_v, pol); T sc = sx * cv - sv * cx; // == sin(chi); T cc = cx * cv + sx * sv; // == cos(chi); - T chi = boost::math::constants::root_two() / (boost::math::constants::root_pi() * sqrt(x)); //sqrt(2 / (boost::math::constants::pi() * x)); + T chi = BOOST_MATH_NAMESPACE::constants::root_two() / (BOOST_MATH_NAMESPACE::constants::root_pi() * sqrt(x)); //sqrt(2 / (boost::math::constants::pi() * x)); Yv = chi * (p * sc + q * cc); Jv = chi * (p * cc - q * sc); } @@ -455,7 +455,7 @@ namespace boost { namespace math { Jv = scale * W / (Yv * fv - Yv1); // Wronskian relation } else - Jv = boost::math::numeric_limits::quiet_NaN(); // any value will do, we're not using it. + Jv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // any value will do, we're not using it. Yv_scale = scale; } else // x in (2, \infty) @@ -570,7 +570,7 @@ namespace boost { namespace math { Yv = prev; } else - Yv = boost::math::numeric_limits::quiet_NaN(); // any value will do, we're not using it. + Yv = BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); // any value will do, we're not using it. } if (reflect) @@ -598,6 +598,6 @@ namespace boost { namespace math { } // namespace detail -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_JY_HPP diff --git a/include/boost/math/special_functions/detail/bessel_jy_asym.hpp b/include/boost/math/special_functions/detail/bessel_jy_asym.hpp index 51e4efafca..22ded7b214 100644 --- a/include/boost/math/special_functions/detail/bessel_jy_asym.hpp +++ b/include/boost/math/special_functions/detail/bessel_jy_asym.hpp @@ -21,7 +21,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED inline T asymptotic_bessel_amplitude(T v, T x) @@ -85,8 +85,8 @@ BOOST_MATH_GPU_ENABLED inline T asymptotic_bessel_y_large_x_2(T v, T x, const Po // T cx = cos(x); T sx = sin(x); - T ci = boost::math::cos_pi(v / 2 + 0.25f, pol); - T si = boost::math::sin_pi(v / 2 + 0.25f, pol); + T ci = BOOST_MATH_NAMESPACE::cos_pi(v / 2 + 0.25f, pol); + T si = BOOST_MATH_NAMESPACE::sin_pi(v / 2 + 0.25f, pol); T sin_phase = sin(phase) * (cx * ci + sx * si) + cos(phase) * (sx * ci - cx * si); BOOST_MATH_INSTRUMENT_CODE(sin(phase)); BOOST_MATH_INSTRUMENT_CODE(cos(x)); @@ -119,8 +119,8 @@ BOOST_MATH_GPU_ENABLED inline T asymptotic_bessel_j_large_x_2(T v, T x, const Po BOOST_MATH_INSTRUMENT_CODE(sin(x)); T cx = cos(x); T sx = sin(x); - T ci = boost::math::cos_pi(v / 2 + 0.25f, pol); - T si = boost::math::sin_pi(v / 2 + 0.25f, pol); + T ci = BOOST_MATH_NAMESPACE::cos_pi(v / 2 + 0.25f, pol); + T si = BOOST_MATH_NAMESPACE::sin_pi(v / 2 + 0.25f, pol); T sin_phase = cos(phase) * (cx * ci + sx * si) - sin(phase) * (sx * ci - cx * si); BOOST_MATH_INSTRUMENT_VARIABLE(sin_phase); return sin_phase * ampl; @@ -165,10 +165,10 @@ template BOOST_MATH_GPU_ENABLED void temme_asymptotic_y_small_x(T v, T x, T* Y, T* Y1, const Policy& pol) { T c = 1; - T p = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, -v) / boost::math::tgamma(1 - v, pol); - T q = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, v) / boost::math::tgamma(1 + v, pol); + T p = (v / BOOST_MATH_NAMESPACE::sin_pi(v, pol)) * pow(x / 2, -v) / BOOST_MATH_NAMESPACE::tgamma(1 - v, pol); + T q = (v / BOOST_MATH_NAMESPACE::sin_pi(v, pol)) * pow(x / 2, v) / BOOST_MATH_NAMESPACE::tgamma(1 + v, pol); T f = (p - q) / v; - T g_prefix = boost::math::sin_pi(v / 2, pol); + T g_prefix = BOOST_MATH_NAMESPACE::sin_pi(v / 2, pol); g_prefix *= g_prefix * 2 / v; T g = f + g_prefix * q; T h = p; @@ -220,11 +220,11 @@ BOOST_MATH_GPU_ENABLED T asymptotic_bessel_i_large_x(T v, T x, const Policy& pol s = e * (e * s / sqrt(2 * x * constants::pi())); - return (boost::math::isfinite)(s) ? + return (BOOST_MATH_NAMESPACE::isfinite)(s) ? s : policies::raise_overflow_error("boost::math::asymptotic_bessel_i_large_x<%1%>(%1%,%1%)", nullptr, pol); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp b/include/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp index 9bdbb85842..0e97558cef 100644 --- a/include/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp +++ b/include/boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp @@ -15,7 +15,7 @@ #pragma once #endif -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template inline T asymptotic_bessel_derivative_amplitude(T v, T x) @@ -31,7 +31,7 @@ inline T asymptotic_bessel_derivative_amplitude(T v, T x) s -= (mu - 3) / (2 * txq); s -= ((mu - 1) * (mu - 45)) / (txq * txq * 8); - return sqrt(s * 2 / (boost::math::constants::pi() * x)); + return sqrt(s * 2 / (BOOST_MATH_NAMESPACE::constants::pi() * x)); } template @@ -132,10 +132,14 @@ inline bool asymptotic_bessel_derivative_large_x_limit(const T& v, const T& x) // using the former seems to work OK in practice with broadly similar // error rates either side of the divide for v < 10000. // At double precision eps^1/8 ~= 0.01. + // However, the expansions for the derivatives (A&S 9.2.30 and 9.2.31) are + // truncated after only three terms: for small v this leaves errors of up to + // 1e4 eps at x ~ 100 whereas the recurrence relations are good to a few eps, + // so we need x about twice as large, and to treat all v < 2 as v = 2. // - return (std::max)(T(fabs(v)), T(1)) < x * sqrt(boost::math::tools::forth_root_epsilon()); + return 2 * (std::max)(T(fabs(v)), T(2)) < x * sqrt(BOOST_MATH_NAMESPACE::tools::forth_root_epsilon()); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP diff --git a/include/boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp b/include/boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp index d7bb64f8cd..6907c9bd36 100644 --- a/include/boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp +++ b/include/boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp @@ -10,10 +10,12 @@ #pragma once #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template struct bessel_j_derivative_small_z_series_term @@ -56,24 +58,24 @@ inline T bessel_j_derivative_small_z_series(T v, T x, const Policy& pol) { BOOST_MATH_STD_USING T prefix; - if (v < boost::math::max_factorial::value) + if (v < BOOST_MATH_NAMESPACE::max_factorial::value) { - prefix = pow(x / 2, v - 1) / 2 / boost::math::tgamma(v + 1, pol); + prefix = pow(x / 2, v - 1) / 2 / BOOST_MATH_NAMESPACE::tgamma(v + 1, pol); } else { - prefix = (v - 1) * log(x / 2) - constants::ln_two() - boost::math::lgamma(v + 1, pol); + prefix = (v - 1) * log(x / 2) - constants::ln_two() - BOOST_MATH_NAMESPACE::lgamma(v + 1, pol); prefix = exp(prefix); } if (0 == prefix) return prefix; bessel_j_derivative_small_z_series_term s(v, x); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::bessel_j_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::bessel_j_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol); return prefix * result; } @@ -146,67 +148,67 @@ inline T bessel_y_derivative_small_z_series(T v, T x, const Policy& pol) T gam; T p = log(x / 2); T scale = 1; - bool need_logs = (v >= boost::math::max_factorial::value) || (boost::math::tools::log_max_value() / v < fabs(p)); + bool need_logs = (v >= BOOST_MATH_NAMESPACE::max_factorial::value) || (BOOST_MATH_NAMESPACE::tools::log_max_value() / v < fabs(p)); if (!need_logs) { - gam = boost::math::tgamma(v, pol); + gam = BOOST_MATH_NAMESPACE::tgamma(v, pol); p = pow(x / 2, v + 1) * 2; - if (boost::math::tools::max_value() * p < gam) + if (BOOST_MATH_NAMESPACE::tools::max_value() * p < gam) { scale /= gam; gam = 1; - if (boost::math::tools::max_value() * p < gam) + if (BOOST_MATH_NAMESPACE::tools::max_value() * p < gam) { // This term will overflow to -INF, when combined with the series below it becomes +INF: - return boost::math::policies::raise_overflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); } } - prefix = -gam / (boost::math::constants::pi() * p); + prefix = -gam / (BOOST_MATH_NAMESPACE::constants::pi() * p); } else { - gam = boost::math::lgamma(v, pol); + gam = BOOST_MATH_NAMESPACE::lgamma(v, pol); p = (v + 1) * p + constants::ln_two(); - prefix = gam - log(boost::math::constants::pi()) - p; - if (boost::math::tools::log_max_value() < prefix) + prefix = gam - log(BOOST_MATH_NAMESPACE::constants::pi()) - p; + if (BOOST_MATH_NAMESPACE::tools::log_max_value() < prefix) { - prefix -= log(boost::math::tools::max_value() / 4); - scale /= (boost::math::tools::max_value() / 4); - if (boost::math::tools::log_max_value() < prefix) + prefix -= log(BOOST_MATH_NAMESPACE::tools::max_value() / 4); + scale /= (BOOST_MATH_NAMESPACE::tools::max_value() / 4); + if (BOOST_MATH_NAMESPACE::tools::log_max_value() < prefix) { - return boost::math::policies::raise_overflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); } } prefix = -exp(prefix); } bessel_y_derivative_small_z_series_term_a s(v, x); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::bessel_y_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::bessel_y_derivative_small_z_series<%1%>(%1%,%1%)", max_iter, pol); result *= prefix; p = pow(x / 2, v - 1) / 2; if (!need_logs) { - prefix = boost::math::tgamma(-v, pol) * boost::math::cos_pi(v, pol) * p / boost::math::constants::pi(); + prefix = BOOST_MATH_NAMESPACE::tgamma(-v, pol) * BOOST_MATH_NAMESPACE::cos_pi(v, pol) * p / BOOST_MATH_NAMESPACE::constants::pi(); } else { int sgn {}; - prefix = boost::math::lgamma(-v, &sgn, pol) + (v - 1) * log(x / 2) - constants::ln_two(); - prefix = exp(prefix) * sgn / boost::math::constants::pi(); + prefix = BOOST_MATH_NAMESPACE::lgamma(-v, &sgn, pol) + (v - 1) * log(x / 2) - constants::ln_two(); + prefix = exp(prefix) * sgn / BOOST_MATH_NAMESPACE::constants::pi(); } bessel_y_derivative_small_z_series_term_b s2(v, x); - max_iter = boost::math::policies::get_max_series_iterations(); + max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); - T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon(), max_iter); + T b = BOOST_MATH_NAMESPACE::tools::sum_series(s2, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); result += scale * prefix * b; if(scale * tools::max_value() < result) - return boost::math::policies::raise_overflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); return result / scale; } @@ -214,6 +216,6 @@ inline T bessel_y_derivative_small_z_series(T v, T x, const Policy& pol) // of formulas in http://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/02/ // seems to lose precision. Instead using linear combination of regular Bessel is preferred. -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_JY_DERIVATIVES_SERIES_HPP diff --git a/include/boost/math/special_functions/detail/bessel_jy_series.hpp b/include/boost/math/special_functions/detail/bessel_jy_series.hpp index d9acfc4441..61f109363a 100644 --- a/include/boost/math/special_functions/detail/bessel_jy_series.hpp +++ b/include/boost/math/special_functions/detail/bessel_jy_series.hpp @@ -14,7 +14,7 @@ #include #include -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template struct bessel_j_small_z_series_term @@ -54,20 +54,20 @@ BOOST_MATH_GPU_ENABLED inline T bessel_j_small_z_series(T v, T x, const Policy& T prefix; if(v < max_factorial::value) { - prefix = pow(x / 2, v) / boost::math::tgamma(v+1, pol); + prefix = pow(x / 2, v) / BOOST_MATH_NAMESPACE::tgamma(v+1, pol); } else { - prefix = v * log(x / 2) - boost::math::lgamma(v+1, pol); + prefix = v * log(x / 2) - BOOST_MATH_NAMESPACE::lgamma(v+1, pol); prefix = exp(prefix); } if(0 == prefix) return prefix; bessel_j_small_z_series_term s(v, x); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); policies::check_series_iterations("boost::math::bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol); return prefix * result; @@ -149,7 +149,7 @@ BOOST_MATH_GPU_ENABLED inline T bessel_y_small_z_series(T v, T x, T* pscale, con if(!need_logs) { - gam = boost::math::tgamma(v, pol); + gam = BOOST_MATH_NAMESPACE::tgamma(v, pol); p = pow(x / 2, v); if(tools::max_value() * p < gam) { @@ -167,7 +167,7 @@ BOOST_MATH_GPU_ENABLED inline T bessel_y_small_z_series(T v, T x, T* pscale, con } else { - gam = boost::math::lgamma(v, pol); + gam = BOOST_MATH_NAMESPACE::lgamma(v, pol); p = v * p; prefix = gam - log(constants::pi()) - p; if(tools::log_max_value() < prefix) @@ -182,28 +182,28 @@ BOOST_MATH_GPU_ENABLED inline T bessel_y_small_z_series(T v, T x, T* pscale, con prefix = -exp(prefix); } bessel_y_small_z_series_term_a s(v, x); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); *pscale = scale; - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); policies::check_series_iterations("boost::math::bessel_y_small_z_series<%1%>(%1%,%1%)", max_iter, pol); result *= prefix; if(!need_logs) { - prefix = boost::math::tgamma(-v, pol) * boost::math::cos_pi(v, pol) * p / constants::pi(); + prefix = BOOST_MATH_NAMESPACE::tgamma(-v, pol) * BOOST_MATH_NAMESPACE::cos_pi(v, pol) * p / constants::pi(); } else { int sgn {}; - prefix = boost::math::lgamma(-v, &sgn, pol) + p; + prefix = BOOST_MATH_NAMESPACE::lgamma(-v, &sgn, pol) + p; prefix = exp(prefix) * sgn / constants::pi(); } bessel_y_small_z_series_term_b s2(v, x); max_iter = policies::get_max_series_iterations(); - T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon(), max_iter); + T b = BOOST_MATH_NAMESPACE::tools::sum_series(s2, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); result -= scale * prefix * b; return result; @@ -245,7 +245,7 @@ BOOST_MATH_GPU_ENABLED T bessel_yn_small_z(int n, T z, T* scale, const Policy& p auto p = static_cast(pow(z / 2, n)); #endif - T result = -((boost::math::factorial(static_cast(n - 1), pol) / constants::pi())); + T result = -((BOOST_MATH_NAMESPACE::factorial(static_cast(n - 1), pol) / constants::pi())); if(p * tools::max_value() < fabs(result)) { T div = tools::max_value() / 8; @@ -261,7 +261,7 @@ BOOST_MATH_GPU_ENABLED T bessel_yn_small_z(int n, T z, T* scale, const Policy& p } } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_JN_SERIES_HPP diff --git a/include/boost/math/special_functions/detail/bessel_jy_zero.hpp b/include/boost/math/special_functions/detail/bessel_jy_zero.hpp index 15671c0df7..23ce849d01 100644 --- a/include/boost/math/special_functions/detail/bessel_jy_zero.hpp +++ b/include/boost/math/special_functions/detail/bessel_jy_zero.hpp @@ -35,7 +35,7 @@ # pragma nv_diag_suppress 20012 #endif - namespace boost { namespace math { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { namespace bessel_zero @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED equation_as_9_3_39_and_its_derivative(const equation_as_9_3_39_and_its_derivative&) = default; - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(const T& z) const + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(const T& z) const { BOOST_MATH_STD_USING // ADL of std names, needed for acos, sqrt. @@ -88,7 +88,7 @@ const T its_derivative(zsq_minus_one_sqrt / z); - return boost::math::tuple(the_function, its_derivative); + return BOOST_MATH_NAMESPACE::tuple(the_function, its_derivative); } private: @@ -118,7 +118,7 @@ // to refine the value of the estimate of the root of z // as a function of zeta. - const T v_pow_third(boost::math::cbrt(v, pol)); + const T v_pow_third(BOOST_MATH_NAMESPACE::cbrt(v, pol)); const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third)); // Obtain zeta using the order v combined with the m'th root of @@ -129,7 +129,7 @@ // Set up a quadratic equation based on the Taylor series // expansion mentioned above. - const T b = -((((zeta * zeta_sqrt) * 2U) / 3U) + boost::math::constants::half_pi()); + const T b = -((((zeta * zeta_sqrt) * 2U) / 3U) + BOOST_MATH_NAMESPACE::constants::half_pi()); // Solve the quadratic equation, taking the positive root. const T z_estimate = (-b + sqrt((b * b) - T(2))) / 2U; @@ -139,21 +139,21 @@ const T range_zmin = (std::max)(z_estimate - T(1), T(1)); const T range_zmax = z_estimate + T(1); - const auto my_digits10 = static_cast(static_cast(boost::math::tools::digits() * 0.301F)); + const auto my_digits10 = static_cast(static_cast(BOOST_MATH_NAMESPACE::tools::digits() * 0.301F)); // Select the maximum allowed iterations based on the number // of decimal digits in the numeric type T, being at least 12. - const auto iterations_allowed = static_cast(BOOST_MATH_GPU_SAFE_MAX(12, my_digits10 * 2)); + const auto iterations_allowed = static_cast(BOOST_MATH_GPU_SAFE_MAX(12, my_digits10 * 2)); - boost::math::uintmax_t iterations_used = iterations_allowed; + BOOST_MATH_NAMESPACE::uintmax_t iterations_used = iterations_allowed; // Calculate the root of z as a function of zeta. - const T z = boost::math::tools::newton_raphson_iterate( - boost::math::detail::bessel_zero::equation_as_9_3_39_and_its_derivative(zeta), + const T z = BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate( + BOOST_MATH_NAMESPACE::detail::bessel_zero::equation_as_9_3_39_and_its_derivative(zeta), z_estimate, range_zmin, range_zmax, - BOOST_MATH_GPU_SAFE_MIN(boost::math::tools::digits(), boost::math::tools::digits()), + BOOST_MATH_GPU_SAFE_MIN(BOOST_MATH_NAMESPACE::tools::digits(), BOOST_MATH_NAMESPACE::tools::digits()), iterations_used); static_cast(iterations_used); @@ -181,7 +181,7 @@ template BOOST_MATH_GPU_ENABLED T equation_nist_10_21_40_a(const T& v, const Policy& pol) { - const T v_pow_third(boost::math::cbrt(v, pol)); + const T v_pow_third(BOOST_MATH_NAMESPACE::cbrt(v, pol)); const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third)); return v * ((((( + T(0.043) @@ -204,7 +204,7 @@ BOOST_MATH_GPU_ENABLED T operator()(const T& x) const { - return boost::math::cyl_bessel_j(my_v, x, my_pol); + return BOOST_MATH_NAMESPACE::cyl_bessel_j(my_v, x, my_pol); } private: @@ -226,7 +226,7 @@ function_object_jv_and_jv_prime(const function_object_jv_and_jv_prime&) = default; - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(const T& x) const + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(const T& x) const { // Obtain Jv(x) and Jv'(x). // Chris's original code called the Bessel function implementation layer direct, @@ -237,18 +237,18 @@ if(my_order_is_zero) { - j_v = boost::math::cyl_bessel_j(0, x, my_pol); - j_v_prime = -boost::math::cyl_bessel_j(1, x, my_pol); + j_v = BOOST_MATH_NAMESPACE::cyl_bessel_j(0, x, my_pol); + j_v_prime = -BOOST_MATH_NAMESPACE::cyl_bessel_j(1, x, my_pol); } else { - j_v = boost::math::cyl_bessel_j( my_v, x, my_pol); - const T j_v_m1 (boost::math::cyl_bessel_j(T(my_v - 1), x, my_pol)); + j_v = BOOST_MATH_NAMESPACE::cyl_bessel_j( my_v, x, my_pol); + const T j_v_m1 (BOOST_MATH_NAMESPACE::cyl_bessel_j(T(my_v - 1), x, my_pol)); j_v_prime = j_v_m1 - ((my_v * j_v) / x); } // Return a tuple containing both Jv(x) and Jv'(x). - return boost::math::make_tuple(j_v, j_v_prime); + return BOOST_MATH_NAMESPACE::make_tuple(j_v, j_v_prime); } private: @@ -298,7 +298,7 @@ // Bessel function whose reflected, positive integer order // is less than, but nearest to vv. - T root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m, pol); + T root_hi = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m, pol); T root_lo; if(m == 1) @@ -307,11 +307,11 @@ // an adaptive range-searching algorithm. root_lo = T(root_hi - 0.1F); - const bool hi_end_of_bracket_is_negative = (boost::math::cyl_bessel_j(v, root_hi, pol) < 0); + const bool hi_end_of_bracket_is_negative = (BOOST_MATH_NAMESPACE::cyl_bessel_j(v, root_hi, pol) < 0); - while((root_lo > boost::math::tools::epsilon())) + while((root_lo > BOOST_MATH_NAMESPACE::tools::epsilon())) { - const bool lo_end_of_bracket_is_negative = (boost::math::cyl_bessel_j(v, root_lo, pol) < 0); + const bool lo_end_of_bracket_is_negative = (BOOST_MATH_NAMESPACE::cyl_bessel_j(v, root_lo, pol) < 0); if(hi_end_of_bracket_is_negative != lo_end_of_bracket_is_negative) { @@ -333,22 +333,22 @@ } else { - root_lo = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m - 1, pol); + root_lo = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(vv_floor, m - 1, pol); } // Perform several steps of bisection iteration to refine the guess. - boost::math::uintmax_t number_of_iterations(12U); + BOOST_MATH_NAMESPACE::uintmax_t number_of_iterations(12U); // Do the bisection iteration. - const boost::math::tuple guess_pair = - boost::math::tools::bisect( - boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv(v, pol), + const BOOST_MATH_NAMESPACE::tuple guess_pair = + BOOST_MATH_NAMESPACE::tools::bisect( + BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv(v, pol), root_lo, root_hi, - boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::my_bisection_unreachable_tolerance, + BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::my_bisection_unreachable_tolerance, number_of_iterations); - return (boost::math::get<0>(guess_pair) + boost::math::get<1>(guess_pair)) / 2U; + return (BOOST_MATH_NAMESPACE::get<0>(guess_pair) + BOOST_MATH_NAMESPACE::get<1>(guess_pair)) / 2U; } if(m == 1U) @@ -373,7 +373,7 @@ else { // For larger v, use the first line of Eqs. 10.21.40 in the NIST Handbook. - guess = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::equation_nist_10_21_40_a(v, pol); + guess = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::equation_nist_10_21_40_a(v, pol); } } else @@ -381,17 +381,17 @@ if(v < 2.2F) { // Use Eq. 10.21.19 in the NIST Handbook. - const T a(((v + T(m * 2U)) - T(0.5)) * boost::math::constants::half_pi()); + const T a(((v + T(m * 2U)) - T(0.5)) * BOOST_MATH_NAMESPACE::constants::half_pi()); - guess = boost::math::detail::bessel_zero::equation_nist_10_21_19(v, a); + guess = BOOST_MATH_NAMESPACE::detail::bessel_zero::equation_nist_10_21_19(v, a); } else { // Get an estimate of the m'th root of airy_ai. - const T airy_ai_root(boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess(m, pol)); + const T airy_ai_root(BOOST_MATH_NAMESPACE::detail::airy_zero::airy_ai_zero_detail::initial_guess(m, pol)); // Use Eq. 9.5.26 in the A&S Handbook. - guess = boost::math::detail::bessel_zero::equation_as_9_5_26(v, airy_ai_root, pol); + guess = BOOST_MATH_NAMESPACE::detail::bessel_zero::equation_as_9_5_26(v, airy_ai_root, pol); } } @@ -404,7 +404,7 @@ template BOOST_MATH_GPU_ENABLED T equation_nist_10_21_40_b(const T& v, const Policy& pol) { - const T v_pow_third(boost::math::cbrt(v, pol)); + const T v_pow_third(BOOST_MATH_NAMESPACE::cbrt(v, pol)); const T v_pow_minus_two_thirds(T(1) / (v_pow_third * v_pow_third)); return v * ((((( - T(0.001) @@ -427,7 +427,7 @@ BOOST_MATH_GPU_ENABLED T operator()(const T& x) const { - return boost::math::cyl_neumann(my_v, x, my_pol); + return BOOST_MATH_NAMESPACE::cyl_neumann(my_v, x, my_pol); } private: @@ -446,9 +446,9 @@ BOOST_MATH_GPU_ENABLED function_object_yv_and_yv_prime(const function_object_yv_and_yv_prime&) = default; - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(const T& x) const + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(const T& x) const { - const T half_epsilon(boost::math::tools::epsilon() / 2U); + const T half_epsilon(BOOST_MATH_NAMESPACE::tools::epsilon() / 2U); const bool order_is_zero = ((my_v > -half_epsilon) && (my_v < +half_epsilon)); @@ -461,18 +461,18 @@ if(order_is_zero) { - y_v = boost::math::cyl_neumann(0, x, my_pol); - y_v_prime = -boost::math::cyl_neumann(1, x, my_pol); + y_v = BOOST_MATH_NAMESPACE::cyl_neumann(0, x, my_pol); + y_v_prime = -BOOST_MATH_NAMESPACE::cyl_neumann(1, x, my_pol); } else { - y_v = boost::math::cyl_neumann( my_v, x, my_pol); - const T y_v_m1 (boost::math::cyl_neumann(T(my_v - 1), x, my_pol)); + y_v = BOOST_MATH_NAMESPACE::cyl_neumann( my_v, x, my_pol); + const T y_v_m1 (BOOST_MATH_NAMESPACE::cyl_neumann(T(my_v - 1), x, my_pol)); y_v_prime = y_v_m1 - ((my_v * y_v) / x); } // Return a tuple containing both Yv(x) and Yv'(x). - return boost::math::make_tuple(y_v, y_v_prime); + return BOOST_MATH_NAMESPACE::make_tuple(y_v, y_v_prime); } private: @@ -520,20 +520,20 @@ // half-integer orders and use different brackets above and below these. if(T(vv - vv_floor) < 0.5F) { - root_hi = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol); + root_hi = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol); } else { - root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol); + root_hi = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol); } root_lo = T(root_hi - 0.1F); - const bool hi_end_of_bracket_is_negative = (boost::math::cyl_neumann(v, root_hi, pol) < 0); + const bool hi_end_of_bracket_is_negative = (BOOST_MATH_NAMESPACE::cyl_neumann(v, root_hi, pol) < 0); - while((root_lo > boost::math::tools::epsilon())) + while((root_lo > BOOST_MATH_NAMESPACE::tools::epsilon())) { - const bool lo_end_of_bracket_is_negative = (boost::math::cyl_neumann(v, root_lo, pol) < 0); + const bool lo_end_of_bracket_is_negative = (BOOST_MATH_NAMESPACE::cyl_neumann(v, root_lo, pol) < 0); if(hi_end_of_bracket_is_negative != lo_end_of_bracket_is_negative) { @@ -557,33 +557,33 @@ { if(T(vv - vv_floor) < 0.5F) { - root_lo = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m - 1, pol); - root_hi = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol); + root_lo = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m - 1, pol); + root_hi = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess(vv_floor, m, pol); root_lo += 0.01F; root_hi += 0.01F; } else { - root_lo = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m - 1, pol); - root_hi = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol); + root_lo = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m - 1, pol); + root_hi = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess(T(vv_floor + 0.5F), m, pol); root_lo += 0.01F; root_hi += 0.01F; } } // Perform several steps of bisection iteration to refine the guess. - boost::math::uintmax_t number_of_iterations(12U); + BOOST_MATH_NAMESPACE::uintmax_t number_of_iterations(12U); // Do the bisection iteration. - const boost::math::tuple guess_pair = - boost::math::tools::bisect( - boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv(v, pol), + const BOOST_MATH_NAMESPACE::tuple guess_pair = + BOOST_MATH_NAMESPACE::tools::bisect( + BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv(v, pol), root_lo, root_hi, - boost::math::detail::bessel_zero::cyl_neumann_zero_detail::my_bisection_unreachable_tolerance, + BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_neumann_zero_detail::my_bisection_unreachable_tolerance, number_of_iterations); - return (boost::math::get<0>(guess_pair) + boost::math::get<1>(guess_pair)) / 2U; + return (BOOST_MATH_NAMESPACE::get<0>(guess_pair) + BOOST_MATH_NAMESPACE::get<1>(guess_pair)) / 2U; } if(m == 1U) @@ -608,7 +608,7 @@ else { // For larger v, use the second line of Eqs. 10.21.40 in the NIST Handbook. - guess = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::equation_nist_10_21_40_b(v, pol); + guess = BOOST_MATH_NAMESPACE::detail::bessel_zero::cyl_neumann_zero_detail::equation_nist_10_21_40_b(v, pol); } } else @@ -616,17 +616,17 @@ if(v < 2.2F) { // Use Eq. 10.21.19 in the NIST Handbook. - const T a(((v + T(m * 2U)) - T(1.5)) * boost::math::constants::half_pi()); + const T a(((v + T(m * 2U)) - T(1.5)) * BOOST_MATH_NAMESPACE::constants::half_pi()); - guess = boost::math::detail::bessel_zero::equation_nist_10_21_19(v, a); + guess = BOOST_MATH_NAMESPACE::detail::bessel_zero::equation_nist_10_21_19(v, a); } else { // Get an estimate of the m'th root of airy_bi. - const T airy_bi_root(boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess(m, pol)); + const T airy_bi_root(BOOST_MATH_NAMESPACE::detail::airy_zero::airy_bi_zero_detail::initial_guess(m, pol)); // Use Eq. 9.5.26 in the A&S Handbook. - guess = boost::math::detail::bessel_zero::equation_as_9_5_26(v, airy_bi_root, pol); + guess = BOOST_MATH_NAMESPACE::detail::bessel_zero::equation_as_9_5_26(v, airy_bi_root, pol); } } @@ -634,7 +634,7 @@ } } // namespace cyl_neumann_zero_detail } // namespace bessel_zero - } } } // namespace boost::math::detail + } BOOST_MATH_NAMESPACE_END // namespace boost::math::detail #ifdef BOOST_MATH_ENABLE_CUDA # pragma nv_diag_default 20012 diff --git a/include/boost/math/special_functions/detail/bessel_k0.hpp b/include/boost/math/special_functions/detail/bessel_k0.hpp index 1841983dfd..4c3cd3b5a0 100644 --- a/include/boost/math/special_functions/detail/bessel_k0.hpp +++ b/include/boost/math/special_functions/detail/bessel_k0.hpp @@ -45,17 +45,17 @@ // references above. We can also improve performance WRT to // Holoborodko without loss of precision. -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template -BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T&, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T&, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_ASSERT(0); return 0; } template -BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x <= 1) @@ -125,7 +125,7 @@ BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_c } template -BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x <= 1) @@ -215,7 +215,7 @@ BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_c } template -BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x <= 1) @@ -315,7 +315,7 @@ BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_c } template -BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x <= 1) @@ -442,16 +442,16 @@ BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_c } template -BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { - if(boost::math::tools::digits() <= 24) - return bessel_k0_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 53) - return bessel_k0_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 64) - return bessel_k0_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 113) - return bessel_k0_imp(x, boost::math::integral_constant()); + if(BOOST_MATH_NAMESPACE::tools::digits() <= 24) + return bessel_k0_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 53) + return bessel_k0_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 64) + return bessel_k0_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 113) + return bessel_k0_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); BOOST_MATH_ASSERT(0); return 0; } @@ -459,23 +459,23 @@ BOOST_MATH_GPU_ENABLED T bessel_k0_imp(const T& x, const boost::math::integral_c template BOOST_MATH_GPU_ENABLED inline T bessel_k0(const T& x) { - typedef boost::math::integral_constant::digits == 0) || (boost::math::numeric_limits::radix != 2)) ? + typedef BOOST_MATH_NAMESPACE::integral_constant::digits == 0) || (BOOST_MATH_NAMESPACE::numeric_limits::radix != 2)) ? 0 : - boost::math::numeric_limits::digits <= 24 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 24 ? 24 : - boost::math::numeric_limits::digits <= 53 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 53 ? 53 : - boost::math::numeric_limits::digits <= 64 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 64 ? 64 : - boost::math::numeric_limits::digits <= 113 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 113 ? 113 : -1 > tag_type; return bessel_k0_imp(x, tag_type()); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/detail/bessel_k1.hpp b/include/boost/math/special_functions/detail/bessel_k1.hpp index eeeaa5d285..bbbbefe70b 100644 --- a/include/boost/math/special_functions/detail/bessel_k1.hpp +++ b/include/boost/math/special_functions/detail/bessel_k1.hpp @@ -45,17 +45,17 @@ // references above. We can also improve performance WRT to // Holoborodko without loss of precision. -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template - BOOST_MATH_GPU_ENABLED inline T bessel_k1_imp(const T&, const boost::math::integral_constant&) + BOOST_MATH_GPU_ENABLED inline T bessel_k1_imp(const T&, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_ASSERT(0); return 0; } template - BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const boost::math::integral_constant&) + BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x <= 1) @@ -126,7 +126,7 @@ namespace boost { namespace math { namespace detail{ } template - BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const boost::math::integral_constant&) + BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x <= 1) @@ -219,7 +219,7 @@ namespace boost { namespace math { namespace detail{ } template - BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const boost::math::integral_constant&) + BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x <= 1) @@ -319,7 +319,7 @@ namespace boost { namespace math { namespace detail{ } template - BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const boost::math::integral_constant&) + BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING if(x <= 1) @@ -483,16 +483,16 @@ namespace boost { namespace math { namespace detail{ } template - BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const boost::math::integral_constant&) + BOOST_MATH_GPU_ENABLED T bessel_k1_imp(const T& x, const BOOST_MATH_NAMESPACE::integral_constant&) { - if(boost::math::tools::digits() <= 24) - return bessel_k1_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 53) - return bessel_k1_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 64) - return bessel_k1_imp(x, boost::math::integral_constant()); - else if(boost::math::tools::digits() <= 113) - return bessel_k1_imp(x, boost::math::integral_constant()); + if(BOOST_MATH_NAMESPACE::tools::digits() <= 24) + return bessel_k1_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 53) + return bessel_k1_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 64) + return bessel_k1_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); + else if(BOOST_MATH_NAMESPACE::tools::digits() <= 113) + return bessel_k1_imp(x, BOOST_MATH_NAMESPACE::integral_constant()); BOOST_MATH_ASSERT(0); return 0; } @@ -500,23 +500,23 @@ namespace boost { namespace math { namespace detail{ template BOOST_MATH_GPU_ENABLED inline T bessel_k1(const T& x) { - typedef boost::math::integral_constant::digits == 0) || (boost::math::numeric_limits::radix != 2)) ? + typedef BOOST_MATH_NAMESPACE::integral_constant::digits == 0) || (BOOST_MATH_NAMESPACE::numeric_limits::radix != 2)) ? 0 : - boost::math::numeric_limits::digits <= 24 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 24 ? 24 : - boost::math::numeric_limits::digits <= 53 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 53 ? 53 : - boost::math::numeric_limits::digits <= 64 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 64 ? 64 : - boost::math::numeric_limits::digits <= 113 ? + BOOST_MATH_NAMESPACE::numeric_limits::digits <= 113 ? 113 : -1 > tag_type; return bessel_k1_imp(x, tag_type()); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/detail/bessel_kn.hpp b/include/boost/math/special_functions/detail/bessel_kn.hpp index 41becc8aa9..306de2e4f6 100644 --- a/include/boost/math/special_functions/detail/bessel_kn.hpp +++ b/include/boost/math/special_functions/detail/bessel_kn.hpp @@ -15,13 +15,14 @@ #include #include #include +#include #include #include // Modified Bessel function of the second kind of integer order // K_n(z) is the dominant solution, forward recurrence always OK (though unstable) -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T bessel_kn(int n, T x, const Policy& pol) @@ -29,7 +30,7 @@ BOOST_MATH_GPU_ENABLED T bessel_kn(int n, T x, const Policy& pol) BOOST_MATH_STD_USING T value, current, prev; - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; constexpr auto function = "boost::math::bessel_kn<%1%>(%1%,%1%)"; @@ -60,6 +61,12 @@ BOOST_MATH_GPU_ENABLED T bessel_kn(int n, T x, const Policy& pol) { prev = bessel_k0(x); current = bessel_k1(x); + if ((prev < tools::min_value()) || (current < tools::min_value())) + { + T Iv, Kv; + bessel_ik(static_cast(n), x, &Iv, &Kv, need_k, pol); + return Kv; + } int k = 1; BOOST_MATH_ASSERT(k < n); T scale = 1; @@ -79,13 +86,13 @@ BOOST_MATH_GPU_ENABLED T bessel_kn(int n, T x, const Policy& pol) } while(k < n); if (tools::max_value() * scale < fabs(value)) - return ((boost::math::signbit)(scale) ? -1 : 1) * sign(value) * policies::raise_overflow_error(function, nullptr, pol); + return ((BOOST_MATH_NAMESPACE::signbit)(scale) ? -1 : 1) * sign(value) * policies::raise_overflow_error(function, nullptr, pol); value /= scale; } return value; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_KN_HPP diff --git a/include/boost/math/special_functions/detail/bessel_y0.hpp b/include/boost/math/special_functions/detail/bessel_y0.hpp index f1aea6acbd..6d64339953 100644 --- a/include/boost/math/special_functions/detail/bessel_y0.hpp +++ b/include/boost/math/special_functions/detail/bessel_y0.hpp @@ -34,7 +34,7 @@ // x <= 8, minimax rational approximations on root-bracketing intervals // x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968 -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T bessel_y0(T x, const Policy&); @@ -141,8 +141,8 @@ BOOST_MATH_GPU_ENABLED T bessel_y0(T x, const Policy&) T value, factor, r, rc, rs; BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; BOOST_MATH_ASSERT(x > 0); @@ -195,7 +195,7 @@ BOOST_MATH_GPU_ENABLED T bessel_y0(T x, const Policy&) return value; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/detail/bessel_y1.hpp b/include/boost/math/special_functions/detail/bessel_y1.hpp index 0f0dbdf3bb..1b5c9b3ccf 100644 --- a/include/boost/math/special_functions/detail/bessel_y1.hpp +++ b/include/boost/math/special_functions/detail/bessel_y1.hpp @@ -34,7 +34,7 @@ // x <= 8, minimax rational approximations on root-bracketing intervals // x > 8, Hankel asymptotic expansion in Hart, Computer Approximations, 1968 -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T bessel_y1(T x, const Policy&); @@ -128,8 +128,8 @@ BOOST_MATH_GPU_ENABLED T bessel_y1(T x, const Policy&) T value, factor, r, rc, rs; BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; BOOST_MATH_ASSERT(x > 0); @@ -173,7 +173,7 @@ BOOST_MATH_GPU_ENABLED T bessel_y1(T x, const Policy&) return value; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/detail/bessel_yn.hpp b/include/boost/math/special_functions/detail/bessel_yn.hpp index f95167a73b..85ca74eb55 100644 --- a/include/boost/math/special_functions/detail/bessel_yn.hpp +++ b/include/boost/math/special_functions/detail/bessel_yn.hpp @@ -20,7 +20,7 @@ // Bessel function of the second kind of integer order // Y_n(z) is the dominant solution, forward recurrence always OK (though unstable) -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T bessel_yn(int n, T x, const Policy& pol) @@ -28,7 +28,7 @@ BOOST_MATH_GPU_ENABLED T bessel_yn(int n, T x, const Policy& pol) BOOST_MATH_STD_USING T value, factor, current, prev; - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; constexpr auto function = "boost::math::bessel_yn<%1%>(%1%,%1%)"; @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED T bessel_yn(int n, T x, const Policy& pol) T scale = 1; value = bessel_yn_small_z(n, x, &scale, pol); if (tools::max_value() * fabs(scale) < fabs(value)) - return boost::math::sign(scale) * boost::math::sign(value) * policies::raise_overflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::sign(scale) * BOOST_MATH_NAMESPACE::sign(value) * policies::raise_overflow_error(function, nullptr, pol); value = (factor * value) / scale; } else if(asymptotic_bessel_large_x_limit(n, x)) @@ -107,7 +107,7 @@ BOOST_MATH_GPU_ENABLED T bessel_yn(int n, T x, const Policy& pol) return value; } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_YN_HPP diff --git a/include/boost/math/special_functions/detail/daubechies_scaling_integer_grid.hpp b/include/boost/math/special_functions/detail/daubechies_scaling_integer_grid.hpp index f680c2b0f6..3154b64529 100644 --- a/include/boost/math/special_functions/detail/daubechies_scaling_integer_grid.hpp +++ b/include/boost/math/special_functions/detail/daubechies_scaling_integer_grid.hpp @@ -8,8 +8,10 @@ // THIS FILE GENERATED BY EXAMPLE/DAUBECHIES_SCALING_INTEGER_GRID.CPP, DO NOT EDIT. #ifndef BOOST_MATH_DAUBECHIES_SCALING_INTEGER_GRID_HPP #define BOOST_MATH_DAUBECHIES_SCALING_INTEGER_GRID_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include /* In order to keep the character count as small as possible and speed up @@ -30,7 +32,7 @@ The suffix is as follows: # define C_(x) static_cast(x) #endif -namespace boost::math::detail { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template struct daubechies_scaling_integer_grid_imp; @@ -240,5 +242,5 @@ constexpr inline std::array daubechies_scaling_integer_grid() return daubechies_scaling_integer_grid_imp::value; } -} // namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/detail/erf_inv.hpp b/include/boost/math/special_functions/detail/erf_inv.hpp index cb65cffbc1..3a66d2f5df 100644 --- a/include/boost/math/special_functions/detail/erf_inv.hpp +++ b/include/boost/math/special_functions/detail/erf_inv.hpp @@ -18,9 +18,11 @@ #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // @@ -301,12 +303,12 @@ BOOST_MATH_GPU_ENABLED T erf_inv_imp(const T& p, const T& q, const Policy&, cons template struct erf_roots { - boost::math::tuple operator()(const T& guess) + BOOST_MATH_NAMESPACE::tuple operator()(const T& guess) { BOOST_MATH_STD_USING T derivative = sign * (2 / sqrt(constants::pi())) * exp(-(guess * guess)); T derivative2 = -2 * guess * derivative; - return boost::math::make_tuple(((sign > 0) ? static_cast(boost::math::erf(guess, Policy()) - target) : static_cast(boost::math::erfc(guess, Policy())) - target), derivative, derivative2); + return BOOST_MATH_NAMESPACE::make_tuple(((sign > 0) ? static_cast(BOOST_MATH_NAMESPACE::erf(guess, Policy()) - target) : static_cast(BOOST_MATH_NAMESPACE::erfc(guess, Policy())) - target), derivative, derivative2); } erf_roots(T z, int s) : target(z), sign(s) {} private: @@ -490,13 +492,11 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type erf_inv(T z) return erf_inv(z, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else // Special handling for NVRTC -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN template BOOST_MATH_GPU_ENABLED auto erf_inv(T x) @@ -546,8 +546,7 @@ BOOST_MATH_GPU_ENABLED auto erfc_inv(float x, const Policy&) return ::erfcinvf(x); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTV diff --git a/include/boost/math/special_functions/detail/fp_traits.hpp b/include/boost/math/special_functions/detail/fp_traits.hpp index 7362d0fada..dd8eacd893 100644 --- a/include/boost/math/special_functions/detail/fp_traits.hpp +++ b/include/boost/math/special_functions/detail/fp_traits.hpp @@ -21,11 +21,13 @@ With these techniques, the code could be simplified. # define BOOST_FPCLASSIFY_VAX_FORMAT #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include +#endif #include #include #include @@ -105,8 +107,7 @@ static_assert((BOOST_MATH_ENDIAN_BIG_BYTE || BOOST_MATH_ENDIAN_LITTLE_BYTE) //------------------------------------------------------------------------------ -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { //------------------------------------------------------------------------------ @@ -556,7 +557,6 @@ template struct fp_traits //------------------------------------------------------------------------------ } // namespace detail -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/detail/gamma_inva.hpp b/include/boost/math/special_functions/detail/gamma_inva.hpp index 8c3be8ef1a..f8a028ef85 100644 --- a/include/boost/math/special_functions/detail/gamma_inva.hpp +++ b/include/boost/math/special_functions/detail/gamma_inva.hpp @@ -21,7 +21,7 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN #ifdef BOOST_MATH_HAS_NVRTC template @@ -36,7 +36,7 @@ struct gamma_inva_t BOOST_MATH_GPU_ENABLED gamma_inva_t(T z_, T p_, bool invert_) : z(z_), p(p_), invert(invert_) {} BOOST_MATH_GPU_ENABLED T operator()(T a) { - return invert ? p - boost::math::gamma_q(a, z, Policy()) : boost::math::gamma_p(a, z, Policy()) - p; + return invert ? p - BOOST_MATH_NAMESPACE::gamma_q(a, z, Policy()) : BOOST_MATH_NAMESPACE::gamma_p(a, z, Policy()) - p; } private: T z, p; @@ -56,7 +56,7 @@ BOOST_MATH_GPU_ENABLED T inverse_poisson_cornish_fisher(T lambda, T p, T q, cons // kurtosis: // T k = 1/lambda; // Get the inverse of a std normal distribution: - T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two(); + T x = BOOST_MATH_NAMESPACE::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two(); // Set the sign: if(p < 0.5) x = -x; @@ -222,18 +222,17 @@ template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type gamma_p_inva(T1 x, T2 p) { - return boost::math::gamma_p_inva(x, p, policies::policy<>()); + return BOOST_MATH_NAMESPACE::gamma_p_inva(x, p, policies::policy<>()); } template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type gamma_q_inva(T1 x, T2 q) { - return boost::math::gamma_q_inva(x, q, policies::policy<>()); + return BOOST_MATH_NAMESPACE::gamma_q_inva(x, q, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SP_DETAIL_GAMMA_INVA diff --git a/include/boost/math/special_functions/detail/hypergeometric_0F1_bessel.hpp b/include/boost/math/special_functions/detail/hypergeometric_0F1_bessel.hpp index be91d406c2..2f9fa85067 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_0F1_bessel.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_0F1_bessel.hpp @@ -13,7 +13,7 @@ #include #include - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { template inline T hypergeometric_0F1_bessel(const T& b, const T& z, const Policy& pol) @@ -24,23 +24,23 @@ BOOST_MATH_ASSERT(z < 0); // condition used at call site const T sqrt_z = sqrt(-z); - const T bessel_mult = boost::math::cyl_bessel_j(b - 1, 2 * sqrt_z, pol); + const T bessel_mult = BOOST_MATH_NAMESPACE::cyl_bessel_j(b - 1, 2 * sqrt_z, pol); - if (b > boost::math::max_factorial::value) + if (b > BOOST_MATH_NAMESPACE::max_factorial::value) { const T lsqrt_z = log(sqrt_z); const T lsqrt_z_pow_b = (b - 1) * lsqrt_z; - T lg = (boost::math::lgamma(b, pol) - lsqrt_z_pow_b); + T lg = (BOOST_MATH_NAMESPACE::lgamma(b, pol) - lsqrt_z_pow_b); lg = exp(lg); return lg * bessel_mult; } else { const T sqrt_z_pow_b = pow(sqrt_z, b - 1); - return (boost::math::tgamma(b, pol) / sqrt_z_pow_b) * bessel_mult; + return (BOOST_MATH_NAMESPACE::tgamma(b, pol) / sqrt_z_pow_b) * bessel_mult; } } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_0F1_BESSEL_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_addition_theorems_on_z.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_addition_theorems_on_z.hpp index 49f0fc0aac..2747722d48 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_addition_theorems_on_z.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_addition_theorems_on_z.hpp @@ -24,7 +24,7 @@ // See https://dlmf.nist.gov/13.13 // - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { // // This works moderately well for a < 0, but has some very strange behaviour with @@ -42,8 +42,8 @@ { BOOST_MATH_STD_USING long long scale1(0), scale2(0); - M = boost::math::detail::hypergeometric_1F1_imp(a, b, z, pol, scale1); - M_next = boost::math::detail::hypergeometric_1F1_imp(T(a - 1), b, z, pol, scale2); + M = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a, b, z, pol, scale1); + M_next = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(T(a - 1), b, z, pol, scale2); if (scale1 != scale2) M_next *= exp(T(scale2 - scale1)); if (M > 1e10f) @@ -80,10 +80,10 @@ BOOST_MATH_STD_USING BOOST_MATH_ASSERT((z + k) / z > 0.5f); hypergeometric_1f1_recurrence_on_z_minus_zero_series s(a, b, z, k, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); log_scaling += s.scale(); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); return result * exp(T(k)) * pow(z / (z + k), b - a); } @@ -101,8 +101,8 @@ hypergeometric_1f1_recurrence_on_z_plus_plus_series(const T& a, const T& b, const T& z, int k_, const Policy& pol) : term(1), a_plus_n(a), b_plus_n(b), z_(z), n(0), k(k_) { - M = boost::math::detail::hypergeometric_1F1_imp(a, b, z, pol); - M_next = boost::math::detail::hypergeometric_1F1_imp(a + 1, b + 1, z, pol); + M = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a, b, z, pol); + M_next = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a + 1, b + 1, z, pol); } T operator()() { @@ -125,9 +125,9 @@ T hypergeometric_1f1_recurrence_on_z_plus_plus(const T& a, const T& b, const T& z, int k, const Policy& pol) { hypergeometric_1f1_recurrence_on_z_plus_plus_series s(a, b, z, k, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); return result; } @@ -139,8 +139,8 @@ hypergeometric_1f1_recurrence_on_z_zero_minus_series(const T& a, const T& b, const T& z, int k_, const Policy& pol) : term(1), b_pochhammer(1 - b), x_k_power(-k_ / z), b_minus_n(b), a_(a), z_(z), b_(b), n(0), k(k_) { - M = boost::math::detail::hypergeometric_1F1_imp(a, b, z, pol); - M_next = boost::math::detail::hypergeometric_1F1_imp(a, b - 1, z, pol); + M = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a, b, z, pol); + M_next = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a, b - 1, z, pol); } T operator()() { @@ -164,9 +164,9 @@ BOOST_MATH_STD_USING BOOST_MATH_ASSERT(abs(k) < fabs(z)); hypergeometric_1f1_recurrence_on_z_zero_minus_series s(a, b, z, k, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); return result * pow((z + k) / z, 1 - b); } @@ -178,8 +178,8 @@ hypergeometric_1f1_recurrence_on_z_plus_zero_series(const T& a, const T& b, const T& z, int k_, const Policy& pol) : term(1), a_pochhammer(a), z_plus_k(z + k_), b_(b), a_(a), z_(z), n(0), k(k_) { - M = boost::math::detail::hypergeometric_1F1_imp(a, b, z, pol); - M_next = boost::math::detail::hypergeometric_1F1_imp(a + 1, b, z, pol); + M = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a, b, z, pol); + M_next = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a + 1, b, z, pol); } T operator()() { @@ -203,9 +203,9 @@ BOOST_MATH_ASSERT(k / z > -0.5f); //BOOST_MATH_ASSERT(floor(a) != a || a > 0); hypergeometric_1f1_recurrence_on_z_plus_zero_series s(a, b, z, k, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); return result * pow(z / (z + k), a); } @@ -217,8 +217,8 @@ hypergeometric_1f1_recurrence_on_z_zero_plus_series(const T& a, const T& b, const T& z, int k_, const Policy& pol) : term(1), b_minus_a_plus_n(b - a), b_plus_n(b), a_(a), z_(z), n(0), k(k_) { - M = boost::math::detail::hypergeometric_1F1_imp(a, b, z, pol); - M_next = boost::math::detail::hypergeometric_1F1_imp(a, b + 1, z, pol); + M = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a, b, z, pol); + M_next = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a, b + 1, z, pol); } T operator()() { @@ -241,9 +241,9 @@ { BOOST_MATH_STD_USING hypergeometric_1f1_recurrence_on_z_zero_plus_series s(a, b, z, k, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); return result * exp(T(k)); } // @@ -258,8 +258,8 @@ hypergeometric_1f1_recurrence_on_z_minus_minus_series(const T& a, const T& b, const T& z, int k_, const Policy& pol) : term(1), one_minus_b_plus_n(1 - b), a_(a), b_(b), z_(z), n(0), k(k_) { - M = boost::math::detail::hypergeometric_1F1_imp(a, b, z, pol); - M_next = boost::math::detail::hypergeometric_1F1_imp(a - 1, b - 1, z, pol); + M = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a, b, z, pol); + M_next = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(a - 1, b - 1, z, pol); } T operator()() { @@ -281,13 +281,13 @@ { BOOST_MATH_STD_USING hypergeometric_1f1_recurrence_on_z_minus_minus_series s(a, b, z, k, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1f1_recurrence_on_z_plus_plus<%1%>(%1%,%1%,%1%)", max_iter, pol); return result * exp(T(k)) * pow((z + k) / z, 1 - b); } #endif - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_1F1_ADDITION_THEOREMS_ON_Z_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_bessel.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_bessel.hpp index 07d9dabf89..4c7c993261 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_bessel.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_bessel.hpp @@ -17,7 +17,7 @@ #include - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { template T hypergeometric_1F1_divergent_fallback(const T& a, const T& b, const T& z, const Policy& pol, long long& log_scaling); @@ -35,7 +35,7 @@ // actually evaluate them: T x = sqrt(fabs(2 * z * b - 4 * a * z)); T v = b - 1; - return log(boost::math::constants::e() * x / (2 * v)) * v > tools::log_min_value(); + return log(BOOST_MATH_NAMESPACE::constants::e() * x / (2 * v)) * v > tools::log_min_value(); } // @@ -69,7 +69,7 @@ BOOST_MATH_STD_USING term /= pow(fabs(bessel_arg), b_minus_1_plus_n / 2); mult /= sqrt(fabs(bessel_arg)); - bessel_cache[cache_size - 1] = bessel_arg > 0 ? boost::math::cyl_bessel_j(b_minus_1_plus_n - 1, 2 * sqrt(bessel_arg), pol) : boost::math::cyl_bessel_i(b_minus_1_plus_n - 1, 2 * sqrt(-bessel_arg), pol); + bessel_cache[cache_size - 1] = bessel_arg > 0 ? BOOST_MATH_NAMESPACE::cyl_bessel_j(b_minus_1_plus_n - 1, 2 * sqrt(bessel_arg), pol) : BOOST_MATH_NAMESPACE::cyl_bessel_i(b_minus_1_plus_n - 1, 2 * sqrt(-bessel_arg), pol); if (fabs(bessel_cache[cache_size - 1]) < tools::min_value() / tools::epsilon()) { // We get very limited precision due to rapid denormalisation/underflow of the Bessel values, raise an exception and try something else: @@ -79,7 +79,7 @@ cache_offset = -cache_size; return; } - if ((fabs(term * bessel_cache[cache_size - 1]) < tools::min_value() / (tools::epsilon() * tools::epsilon())) || !(boost::math::isfinite)(term) || (!std::numeric_limits::has_infinity && (fabs(term) > tools::max_value()))) + if ((fabs(term * bessel_cache[cache_size - 1]) < tools::min_value() / (tools::epsilon() * tools::epsilon())) || !(BOOST_MATH_NAMESPACE::isfinite)(term) || (!std::numeric_limits::has_infinity && (fabs(term) > tools::max_value()))) { term = -log(fabs(bessel_arg)) * b_minus_1_plus_n / 2; log_scale = lltrunc(term); @@ -91,7 +91,7 @@ #ifndef BOOST_MATH_NO_CXX17_IF_CONSTEXPR if constexpr (std::numeric_limits::has_infinity) { - if (!(boost::math::isfinite)(bessel_cache[cache_size - 1])) + if (!(BOOST_MATH_NAMESPACE::isfinite)(bessel_cache[cache_size - 1])) { policies::raise_evaluation_error("hypergeometric_1F1_AS_13_3_7_tricomi_series<%1%>", "Expected finite Bessel function result but got %1%", bessel_cache[cache_size - 1], pol); // Exceptions are off if we get here, just fill the cache with NaN's and we'll let this method fail and fallback later: @@ -99,15 +99,15 @@ } } else - if ((boost::math::isnan)(bessel_cache[cache_size - 1]) || (fabs(bessel_cache[cache_size - 1]) >= tools::max_value())) + if ((BOOST_MATH_NAMESPACE::isnan)(bessel_cache[cache_size - 1]) || (fabs(bessel_cache[cache_size - 1]) >= tools::max_value())) { policies::raise_evaluation_error("hypergeometric_1F1_AS_13_3_7_tricomi_series<%1%>", "Expected finite Bessel function result but got %1%", bessel_cache[cache_size - 1], pol); // Exceptions are off if we get here, just fill the cache with NaN's and we'll let this method fail and fallback later: std::fill(bessel_cache.begin(), bessel_cache.end(), std::numeric_limits::quiet_NaN()); } #else - if ((std::numeric_limits::has_infinity && !(boost::math::isfinite)(bessel_cache[cache_size - 1])) - || (!std::numeric_limits::has_infinity && ((boost::math::isnan)(bessel_cache[cache_size - 1]) || (fabs(bessel_cache[cache_size - 1]) >= tools::max_value())))) + if ((std::numeric_limits::has_infinity && !(BOOST_MATH_NAMESPACE::isfinite)(bessel_cache[cache_size - 1])) + || (!std::numeric_limits::has_infinity && ((BOOST_MATH_NAMESPACE::isnan)(bessel_cache[cache_size - 1]) || (fabs(bessel_cache[cache_size - 1]) >= tools::max_value())))) { policies::raise_evaluation_error("hypergeometric_1F1_AS_13_3_7_tricomi_series<%1%>", "Expected finite Bessel function result but got %1%", bessel_cache[cache_size - 1], pol); // Exceptions are off if we get here, just fill the cache with NaN's and we'll let this method fail and fallback later: @@ -206,7 +206,7 @@ if ((j < cache_size - 2) && (tools::max_value() / fabs(64 * bessel_cache[j] / bessel_cache[j + 1]) < fabs(bessel_cache[j]))) { T rescale = static_cast(pow(fabs(bessel_cache[j] / bessel_cache[j + 1]), T(j + 1)) * 2); - if (!((boost::math::isfinite)(rescale))) + if (!((BOOST_MATH_NAMESPACE::isfinite)(rescale))) rescale = tools::max_value(); for (int k = j; k < cache_size; ++k) bessel_cache[k] /= rescale; @@ -281,7 +281,7 @@ if ((j < cache_size - 2) && (tools::max_value() / fabs(64 * bessel_cache[j] / bessel_cache[j + 1]) < fabs(bessel_cache[j]))) { T rescale = static_cast(pow(fabs(bessel_cache[j] / bessel_cache[j + 1]), T(j + 1)) * 2); - if (!((boost::math::isfinite)(rescale))) + if (!((BOOST_MATH_NAMESPACE::isfinite)(rescale))) rescale = tools::max_value(); for (int k = j; k < cache_size; ++k) bessel_cache[k] /= rescale; @@ -364,7 +364,7 @@ try #endif { - prefix = boost::math::tgamma(b, pol); + prefix = BOOST_MATH_NAMESPACE::tgamma(b, pol); prefix *= exp(z / 2); } #ifndef BOOST_MATH_NO_EXCEPTIONS @@ -373,16 +373,16 @@ use_logs = true; } #endif - if (use_logs || (prefix == 0) || !(boost::math::isfinite)(prefix) || (!std::numeric_limits::has_infinity && (fabs(prefix) >= tools::max_value()))) + if (use_logs || (prefix == 0) || !(BOOST_MATH_NAMESPACE::isfinite)(prefix) || (!std::numeric_limits::has_infinity && (fabs(prefix) >= tools::max_value()))) { use_logs = true; - prefix = boost::math::lgamma(b, &prefix_sgn, pol) + z / 2; + prefix = BOOST_MATH_NAMESPACE::lgamma(b, &prefix_sgn, pol) + z / 2; scale = lltrunc(prefix); log_scale += scale; prefix -= scale; } T result(0); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); bool retry = false; long long series_scale = 0; #ifndef BOOST_MATH_NO_EXCEPTIONS @@ -399,12 +399,12 @@ T norm = 0; result = 0; if((a < 0) && (b < 0)) - result = boost::math::tools::checked_sum_series(s, boost::math::policies::get_epsilon(), max_iter, result, norm); + result = BOOST_MATH_NAMESPACE::tools::checked_sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter, result, norm); else - result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter, result); - if (!(boost::math::isfinite)(result) || (result == 0) || (!std::numeric_limits::has_infinity && (fabs(result) >= tools::max_value()))) + result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter, result); + if (!(BOOST_MATH_NAMESPACE::isfinite)(result) || (result == 0) || (!std::numeric_limits::has_infinity && (fabs(result) >= tools::max_value()))) retry = true; - if (norm / fabs(result) > 1 / boost::math::tools::root_epsilon()) + if (norm / fabs(result) > 1 / BOOST_MATH_NAMESPACE::tools::root_epsilon()) retry = true; // fatal cancellation } #ifndef BOOST_MATH_NO_EXCEPTIONS @@ -412,7 +412,7 @@ { retry = true; } - catch (const boost::math::evaluation_error&) + catch (const BOOST_MATH_NAMESPACE::evaluation_error&) { retry = true; } @@ -424,7 +424,7 @@ log_scale -= scale; return hypergeometric_1F1_divergent_fallback(a, b, z, pol, log_scale); } - catch (const boost::math::evaluation_error&) + catch (const BOOST_MATH_NAMESPACE::evaluation_error&) { log_scale -= scale; return hypergeometric_1F1_divergent_fallback(a, b, z, pol, log_scale); @@ -436,10 +436,10 @@ log_scale -= series_scale; return hypergeometric_1F1_divergent_fallback(a, b, z, pol, log_scale); } - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_AS_13_3_7<%1%>(%1%,%1%,%1%)", max_iter, pol); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_AS_13_3_7<%1%>(%1%,%1%,%1%)", max_iter, pol); if (use_logs) { - int sgn = boost::math::sign(result); + int sgn = BOOST_MATH_NAMESPACE::sign(result); prefix += log(fabs(result)); result = sgn * prefix_sgn * exp(prefix); } @@ -463,7 +463,7 @@ { typedef T result_type; - cyl_bessel_i_large_x_sum(const T& v, const T& x) : v(v), z(x), term(1), k(0) {} + cyl_bessel_i_large_x_sum(const T& v_, const T& x) : v(v_), z(x), term(1), k(0) {} T operator()() { @@ -481,12 +481,12 @@ { BOOST_MATH_STD_USING cyl_bessel_i_large_x_sum s(v, x); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::cyl_bessel_i_large_x<%1%>(%1%,%1%)", max_iter, pol); - long long scale = boost::math::lltrunc(x); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::cyl_bessel_i_large_x<%1%>(%1%,%1%)", max_iter, pol); + long long scale = BOOST_MATH_NAMESPACE::lltrunc(x); log_scaling += scale; - return result * exp(x - scale) / sqrt(boost::math::constants::two_pi() * x); + return result * exp(x - scale) / sqrt(BOOST_MATH_NAMESPACE::constants::two_pi() * x); } @@ -509,11 +509,21 @@ // that the result should be unity when b-a == b, in fact this is not (quite) // the case for large z. // - hypergeometric_1F1_AS_13_3_6_series(const T& a, const T& b, const T& z, const T& b_minus_a, const Policy& pol_) - : b_minus_a(b_minus_a), half_z(z / 2), poch_1(2 * b_minus_a - 1), poch_2(b_minus_a - a), b_poch(b), term(1), last_result(1), sign(1), n(0), cache_offset(-cache_size), scale(0), pol(pol_) + hypergeometric_1F1_AS_13_3_6_series(const T& a, const T& b, const T& z, const T& b_minus_a_, const Policy& pol_) + : b_minus_a(b_minus_a_), half_z(z / 2), poch_1(2 * b_minus_a_ - 1), poch_2(b_minus_a_ - a), b_poch(b), term(1), last_result(1), sign(1), n(0), cache_offset(-cache_size), scale(0), pol(pol_) { + BOOST_MATH_STD_USING + // + // The cache is normalised using a directly calculated Bessel I, either that of the first term or the one below it. + // For negative order v, I_v is the sum of a positive and a negative term when -2k < v < 1 - 2k, so it may be near + // a zero and have few correct digits. Use the first term's order unless that's the case: + // + T v = b_minus_a_ - 0.5f; + normalise_on_first = !((v < 0) && (floor(-v) != 2 * floor(-v / 2))); // not odd(floor(-v)) + if (!normalise_on_first) + v -= 1; bessel_i_cache[cache_size - 1] = half_z > tools::log_max_value() ? - cyl_bessel_i_large_x_scaled(T(b_minus_a - 1.5f), half_z, scale, pol) : boost::math::cyl_bessel_i(b_minus_a - 1.5f, half_z, pol); + cyl_bessel_i_large_x_scaled(v, half_z, scale, pol) : BOOST_MATH_NAMESPACE::cyl_bessel_i(v, half_z, pol); refill_cache(); } T operator()() @@ -550,6 +560,7 @@ T b_minus_a, half_z, poch_1, poch_2, b_poch, term, last_result; int sign; int n, cache_offset; + bool normalise_on_first; long long scale; const Policy& pol; std::array bessel_i_cache; @@ -565,7 +576,13 @@ // cache_offset += cache_size; T last_value = bessel_i_cache.back(); - bessel_i_backwards_iterator i(b_minus_a + cache_offset + (int)cache_size - 1.5f, half_z, tools::min_value() * (fabs(last_value) > 1 ? last_value : 1) / tools::epsilon()); + // + // The iterator steps down in order from v + k with k an integer, so each order v + j is rounded only once. + // Stepping down from a rounded order instead put every order out by ~eps * cache_offset, which is amplified + // where I_v is small: + // + T v = b_minus_a - 0.5f; + bessel_i_backwards_iterator i(v, half_z, tools::min_value() * (fabs(last_value) > 1 ? last_value : 1) / tools::epsilon(), tools::recurrence_offset(cache_offset + cache_size - 1)); for (int j = cache_size - 1; j >= 0; --j, ++i) { @@ -584,10 +601,10 @@ rescale = tools::max_value(); for (int k = j; k < cache_size; ++k) bessel_i_cache[k] /= rescale; - i = bessel_i_backwards_iterator(b_minus_a -0.5f + cache_offset + j, half_z, bessel_i_cache[j + 1], bessel_i_cache[j]); + i = bessel_i_backwards_iterator(v, half_z, bessel_i_cache[j + 1], bessel_i_cache[j], tools::recurrence_offset(cache_offset + j)); } } - T ratio = last_value / *i; + T ratio = (normalise_on_first && (cache_offset == 0)) ? last_value / bessel_i_cache[0] : last_value / *i; for (auto j = bessel_i_cache.begin(); j != bessel_i_cache.end(); ++j) *j *= ratio; } @@ -609,10 +626,10 @@ return exp(z - scale); } hypergeometric_1F1_AS_13_3_6_series s(a, b, z, b_minus_a, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_AS_13_3_6<%1%>(%1%,%1%,%1%)", max_iter, pol); - result *= boost::math::tgamma(b_minus_a - 0.5f, pol) * pow(z / 4, -b_minus_a + T(0.5f)); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_AS_13_3_6<%1%>(%1%,%1%,%1%)", max_iter, pol); + result *= BOOST_MATH_NAMESPACE::tgamma(b_minus_a - 0.5f, pol) * pow(z / 4, -b_minus_a + T(0.5f)); long long scale = lltrunc(z / 2); log_scaling += scale; log_scaling += s.scaling(); @@ -649,7 +666,7 @@ T operator()() { // we actually return the n-2 term: - T result = C_minus_2 * power_term * boost::math::cyl_bessel_j(bessel_order, bessel_arg, pol); + T result = C_minus_2 * power_term * BOOST_MATH_NAMESPACE::cyl_bessel_j(bessel_order, bessel_arg, pol); bessel_order += 1; power_term *= mult; ++n; @@ -673,11 +690,11 @@ T hypergeometric_1F1_AS_13_3_8(const T& a, const T& b, const T& z, const T& h, const Policy& pol) { BOOST_MATH_STD_USING - T prefix = exp(h * z) * boost::math::tgamma(b); + T prefix = exp(h * z) * BOOST_MATH_NAMESPACE::tgamma(b); hypergeometric_1F1_AS_13_3_8_series s(a, b, z, h, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_AS_13_3_8<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_AS_13_3_8<%1%>(%1%,%1%,%1%)", max_iter, pol); result *= prefix; return result; } @@ -699,7 +716,7 @@ } T operator()() { - T result = term * a_minus_half_plus_s * boost::math::cyl_bessel_i(a_minus_half_plus_s, half_z, pol); + T result = term * a_minus_half_plus_s * BOOST_MATH_NAMESPACE::cyl_bessel_i(a_minus_half_plus_s, half_z, pol); term *= two_a_minus_1_plus_s * two_a_minus_b_plus_s / (b_plus_s * ++s); two_a_minus_1_plus_s += 1; @@ -722,10 +739,10 @@ T prefix; int prefix_sgn = 1; if (true/*(a < boost::math::max_factorial::value) && (a > 0)*/) - prefix = boost::math::tgamma(a - 0.5f, pol); + prefix = BOOST_MATH_NAMESPACE::tgamma(a - 0.5f, pol); else { - prefix = boost::math::lgamma(a - 0.5f, &prefix_sgn, pol); + prefix = BOOST_MATH_NAMESPACE::lgamma(a - 0.5f, &prefix_sgn, pol); use_logs = true; } if (use_logs) @@ -745,9 +762,9 @@ } hypergeometric_1f1_13_11_1_series s(a, b, z, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1f1_13_11_1<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1f1_13_11_1<%1%>(%1%,%1%,%1%)", max_iter, pol); if (use_logs) { long long scaling = lltrunc(prefix); @@ -763,6 +780,6 @@ #endif - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_1F1_BESSEL_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_by_ratios.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_by_ratios.hpp index ce2fe20eb7..33b6eedb45 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_by_ratios.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_by_ratios.hpp @@ -11,7 +11,7 @@ #include #include - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { template T hypergeometric_1F1_imp(const T& a, const T& b, const T& z, const Policy& pol, long long& log_scaling); @@ -90,7 +90,7 @@ // This is going to be a mighty big number: // long long local_scaling = 0; - T M2 = boost::math::detail::hypergeometric_1F1_imp(T(1 + a - b), T(2 - b), z, pol, local_scaling); + T M2 = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(T(1 + a - b), T(2 - b), z, pol, local_scaling); log_scaling -= local_scaling; // all the M2 terms are in the denominator // // Since a, b and z are all likely to be large we need the Wronksian @@ -107,10 +107,10 @@ // Let M3 = M(1+a-b + 1, 2-b + 1, z) // we can get to this from the ratio which is cheaper to calculate: // - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients coef2(1 + a - b + 1, 2 - b + 1, z); - T M3 = boost::math::tools::function_ratio_from_backwards_recurrence(coef2, boost::math::policies::get_epsilon(), max_iter) * M2; - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients coef2(1 + a - b + 1, 2 - b + 1, z); + T M3 = BOOST_MATH_NAMESPACE::tools::function_ratio_from_backwards_recurrence(coef2, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter) * M2; + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol); // // Get the RHS of the Wronksian: // @@ -134,10 +134,10 @@ // // Get the function ratio, M(a+1, b+1, z)/M(a,b,z): // - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients coef(a + 1, b + 1, z); - T ratio = boost::math::tools::function_ratio_from_backwards_recurrence(coef, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients coef(a + 1, b + 1, z); + T ratio = BOOST_MATH_NAMESPACE::tools::function_ratio_from_backwards_recurrence(coef, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol); return hypergeometric_1F1_from_function_ratio_negative_b(a, b, z, pol, log_scaling, ratio); } // @@ -576,10 +576,10 @@ // // Get the function ratio, M(a+1, b+1, z)/M(a,b,z): // - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients coef(a, b, z); - T ratio = 1 / boost::math::tools::function_ratio_from_forwards_recurrence(coef, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients coef(a, b, z); + T ratio = 1 / BOOST_MATH_NAMESPACE::tools::function_ratio_from_forwards_recurrence(coef, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol); // // We can't normalise via the Wronksian as the subtraction in the Wronksian will suffer an exquisite amount of cancellation - // potentially many hundreds of digits in this region. However, if forwards iteration is stable at this point @@ -589,7 +589,7 @@ long long scale = 0; int steps = itrunc(ceil(-b)); T reference_value = hypergeometric_1F1_imp(T(a + steps), T(b + steps), z, pol, log_scaling); - T found = boost::math::tools::apply_recurrence_relation_forward(boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients(a + 1, b + 1, z), steps - 1, T(1), ratio, &scale); + T found = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_forward(BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients(a + 1, b + 1, z), steps - 1, T(1), ratio, &scale); log_scaling -= scale; if ((fabs(reference_value) < 1) && (fabs(reference_value) < tools::min_value() * fabs(found))) { @@ -625,10 +625,10 @@ // // Get the function ratio, M(a+1, b+1, z)/M(a,b,z): // - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients coef(a, b + 1, z); - T ratio = boost::math::tools::function_ratio_from_backwards_recurrence(coef, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients coef(a, b + 1, z); + T ratio = BOOST_MATH_NAMESPACE::tools::function_ratio_from_backwards_recurrence(coef, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol); // // We need to use A&S 13.4.3 to convert a ratio for M(a, b + 1, z) / M(a, b, z) // to M(a+1, b+1, z) / M(a, b, z) @@ -642,14 +642,14 @@ // This is going to be a mighty big number: // long long local_scaling = 0; - T M2 = boost::math::detail::hypergeometric_1F1_imp(T(1 + a - b), T(2 - b), z, pol, local_scaling); + T M2 = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(T(1 + a - b), T(2 - b), z, pol, local_scaling); log_scaling -= local_scaling; // all the M2 terms are in the denominator // // Let M3 = M(1+a-b + 1, 2-b + 1, z) // We don't use the ratio to get this as it's not clear that it's reliable: // long long local_scaling2 = 0; - T M3 = boost::math::detail::hypergeometric_1F1_imp(T(2 + a - b), T(3 - b), z, pol, local_scaling2); + T M3 = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(T(2 + a - b), T(3 - b), z, pol, local_scaling2); // // M2 and M3 must be identically scaled: // @@ -673,6 +673,6 @@ return rhs / lhs; } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_HYPERGEOMETRIC_1F1_BY_RATIOS_HPP_ diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_cf.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_cf.hpp index bc23d5f145..cd038f17e7 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_cf.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_cf.hpp @@ -19,7 +19,7 @@ // - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { template struct hypergeometric_1F1_cf_func @@ -39,12 +39,12 @@ T hypergeometric_1F1_cf(const T& a, const T& b, const T& z, const Policy& pol, const char* function) { hypergeometric_1F1_cf_func func(a, b, z); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::continued_fraction_a(func, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations(function, max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::continued_fraction_a(func, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations(function, max_iter, pol); return 1 + a * z / (b * (1 + result)); } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_1F1_BESSEL_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_large_a.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_large_a.hpp index 8b8bbc40df..0a266a349c 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_large_a.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_large_a.hpp @@ -17,19 +17,19 @@ // - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { template T hypergeometric_1F1_large_neg_a_asymtotic_dlmf_13_8_9(T a, T b, T z, const Policy& pol) { - T result = boost::math::cyl_bessel_j(b - 1, sqrt(2 * z * (b - 2 * a)), pol); - result *= boost::math::tgamma(b, pol) * exp(z / 2); + T result = BOOST_MATH_NAMESPACE::cyl_bessel_j(b - 1, sqrt(2 * z * (b - 2 * a)), pol); + result *= BOOST_MATH_NAMESPACE::tgamma(b, pol) * exp(z / 2); T p = pow((b / 2 - a) * z, (1 - b) / 4); result *= p; result *= p; return result; } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_1F1_BESSEL_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_large_abz.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_large_abz.hpp index d072ec2b60..9f96f00f52 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_large_abz.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_large_abz.hpp @@ -13,7 +13,7 @@ #include #include - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { template inline bool is_negative_integer(const T& x) @@ -29,12 +29,12 @@ enum{ cache_size = 64 }; typedef T result_type; - hypergeometric_1F1_igamma_series(const T& alpha, const T& delta, const T& x, const Policy& pol) - : delta_poch(-delta), alpha_poch(alpha), x(x), k(0), cache_offset(0), pol(pol) + hypergeometric_1F1_igamma_series(const T& alpha, const T& delta, const T& x_, const Policy& pol_) + : delta_poch(-delta), alpha_poch(alpha), x(x_), k(0), cache_offset(0), pol(pol_) { BOOST_MATH_STD_USING - T log_term = log(x) * -alpha; - log_scaling = lltrunc(log_term - 3 - boost::math::tools::log_min_value() / 50); + T log_term = log(x_) * -alpha; + log_scaling = lltrunc(log_term - 3 - BOOST_MATH_NAMESPACE::tools::log_min_value() / 50); term = exp(log_term - log_scaling); refill_cache(); } @@ -55,7 +55,7 @@ { typedef typename lanczos::lanczos::type lanczos_type; - gamma_cache[cache_size - 1] = boost::math::gamma_p(alpha_poch + ((int)cache_size - 1), x, pol); + gamma_cache[cache_size - 1] = BOOST_MATH_NAMESPACE::gamma_p(alpha_poch + ((int)cache_size - 1), x, pol); for (int i = cache_size - 1; i > 0; --i) { gamma_cache[i - 1] = gamma_cache[i] >= 1 ? T(1) : T(gamma_cache[i] + regularised_gamma_prefix(T(alpha_poch + (i - 1)), x, pol, lanczos_type()) / (alpha_poch + (i - 1))); @@ -82,10 +82,10 @@ } hypergeometric_1F1_igamma_series s(b_minus_a, a - 1, x, pol); log_scaling += s.log_scaling; - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::tgamma<%1%>(%1%,%1%)", max_iter, pol); - T log_prefix = x + boost::math::lgamma(b, pol) - boost::math::lgamma(a, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::tgamma<%1%>(%1%,%1%)", max_iter, pol); + T log_prefix = x + BOOST_MATH_NAMESPACE::lgamma(b, pol) - BOOST_MATH_NAMESPACE::lgamma(a, pol); long long scale = lltrunc(log_prefix); log_scaling += scale; return result * exp(log_prefix - scale); @@ -123,10 +123,10 @@ if (crossover_shift > a_shift) crossover_shift = a_shift; crossover_a = a_local + crossover_shift; - boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(crossover_a, b_local, x); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T b_ratio = boost::math::tools::function_ratio_from_backwards_recurrence(b_coef, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(crossover_a, b_local, x); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T b_ratio = BOOST_MATH_NAMESPACE::tools::function_ratio_from_backwards_recurrence(b_coef, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); // // Convert to a ratio: // (1+a-b)M(a, b, z) - aM(a+1, b, z) + (b-1)M(a, b-1, z) = 0 @@ -138,9 +138,9 @@ // // Recurse down to a_local, compare values and re-normalise first and second: // - boost::math::detail::hypergeometric_1F1_recurrence_a_coefficients a_coef(crossover_a, b_local, x); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_a_coefficients a_coef(crossover_a, b_local, x); long long backwards_scale = 0; - T comparitor = boost::math::tools::apply_recurrence_relation_backward(a_coef, crossover_shift, second, first, &backwards_scale); + T comparitor = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_backward(a_coef, crossover_shift, second, first, &backwards_scale); log_scaling -= backwards_scale; if ((h < 1) && (tools::max_value() * h > comparitor)) { @@ -157,8 +157,8 @@ // if (crossover_shift < a_shift) { - boost::math::detail::hypergeometric_1F1_recurrence_a_coefficients a_coef_2(crossover_a + 1, b_local, x); - h = boost::math::tools::apply_recurrence_relation_forward(a_coef_2, a_shift - crossover_shift - 1, first, second, &log_scaling); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_a_coefficients a_coef_2(crossover_a + 1, b_local, x); + h = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_forward(a_coef_2, a_shift - crossover_shift - 1, first, second, &log_scaling); } else h = first; @@ -168,10 +168,10 @@ // // Regular case where forwards iteration is stable right from the start: // - boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(a_local, b_local, x); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T b_ratio = boost::math::tools::function_ratio_from_backwards_recurrence(b_coef, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(a_local, b_local, x); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T b_ratio = BOOST_MATH_NAMESPACE::tools::function_ratio_from_backwards_recurrence(b_coef, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); // // Convert to a ratio: // (1+a-b)M(a, b, z) - aM(a+1, b, z) + (b-1)M(a, b-1, z) = 0 @@ -179,8 +179,8 @@ // hence: M(a+1,b,z) = ((1+a-b) / a) M(a,b,z) + ((b-1) / a) M(a,b,z)/b_ratio // T second = ((1 + a_local - b_local) / a_local) * h + ((b_local - 1) / a_local) * h / b_ratio; - boost::math::detail::hypergeometric_1F1_recurrence_a_coefficients a_coef(a_local + 1, b_local, x); - h = boost::math::tools::apply_recurrence_relation_forward(a_coef, --a_shift, h, second, &log_scaling); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_a_coefficients a_coef(a_local + 1, b_local, x); + h = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_forward(a_coef, --a_shift, h, second, &log_scaling); } } else @@ -196,10 +196,10 @@ // will check this with an assert: // BOOST_MATH_ASSERT(2 * a - b_local + x > 0); - boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(a, b_local, x); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T b_ratio = boost::math::tools::function_ratio_from_backwards_recurrence(b_coef, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(a, b_local, x); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T b_ratio = BOOST_MATH_NAMESPACE::tools::function_ratio_from_backwards_recurrence(b_coef, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); // // Convert to a ratio: // (1+a-b)M(a, b, z) - aM(a+1, b, z) + (b-1)M(a, b-1, z) = 0 @@ -213,9 +213,9 @@ h = h / second; else { - boost::math::detail::hypergeometric_1F1_recurrence_a_coefficients a_coef(a + 1, b_local, x); - T comparitor = boost::math::tools::apply_recurrence_relation_forward(a_coef, -(a_shift + 1), first, second); - if (boost::math::tools::min_value() * comparitor > h) + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_a_coefficients a_coef(a + 1, b_local, x); + T comparitor = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_forward(a_coef, -(a_shift + 1), first, second); + if (BOOST_MATH_NAMESPACE::tools::min_value() * comparitor > h) { // Ooops, need to rescale h: long long rescale = lltrunc(log(fabs(h))); @@ -243,12 +243,12 @@ // We get here for b_shift > 0 when b > z. We can't use forward recursion on b - it's unstable, // so grab the ratio and work backwards to b - b_shift and normalise. // - boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(a, b, x); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(a, b, x); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); T first = 1; // arbitrary value; - T second = 1 / boost::math::tools::function_ratio_from_backwards_recurrence(b_coef, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); + T second = 1 / BOOST_MATH_NAMESPACE::tools::function_ratio_from_backwards_recurrence(b_coef, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); if (b_shift == 1) h = h / second; else @@ -256,11 +256,11 @@ // // Reset coefficients and recurse: // - boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef_2(a, b - 1, x); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef_2(a, b - 1, x); long long local_scale = 0; - T comparitor = boost::math::tools::apply_recurrence_relation_backward(b_coef_2, --b_shift, first, second, &local_scale); + T comparitor = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_backward(b_coef_2, --b_shift, first, second, &local_scale); log_scaling -= local_scale; - if (boost::math::tools::min_value() * comparitor > h) + if (BOOST_MATH_NAMESPACE::tools::min_value() * comparitor > h) { // Ooops, need to rescale h: long long rescale = lltrunc(log(fabs(h))); @@ -282,17 +282,17 @@ else { BOOST_MATH_ASSERT(!is_negative_integer(b - a)); - boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(a, b_local, x); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - second = h / boost::math::tools::function_ratio_from_backwards_recurrence(b_coef, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef(a, b_local, x); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + second = h / BOOST_MATH_NAMESPACE::tools::function_ratio_from_backwards_recurrence(b_coef, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_large_abz<%1%>(%1%,%1%,%1%)", max_iter, pol); } if (b_shift == -1) h = second; else { - boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef_2(a, b_local - 1, x); - h = boost::math::tools::apply_recurrence_relation_backward(b_coef_2, -(++b_shift), h, second, &log_scaling); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients b_coef_2(a, b_local - 1, x); + h = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_backward(b_coef_2, -(++b_shift), h, second, &log_scaling); } } return h; @@ -355,7 +355,7 @@ a_shift = 0; T a_local = a - a_shift; T b_local = b - b_shift; - T h = boost::math::detail::hypergeometric_1F1_generic_series(a_local, b_local, z, pol, log_scaling, "hypergeometric_1F1_large_series<%1%>(a,b,z)"); + T h = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_generic_series(a_local, b_local, z, pol, log_scaling, "hypergeometric_1F1_large_series<%1%>(a,b,z)"); // // Apply shifts on a and b as required: // @@ -367,13 +367,13 @@ // calculate a second 1F1 for a == 1 and recurse as normal: // long long scale = 0; - T h2 = boost::math::detail::hypergeometric_1F1_generic_series(T(a_local + 1), b_local, z, pol, scale, "hypergeometric_1F1_large_series<%1%>(a,b,z)"); + T h2 = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_generic_series(T(a_local + 1), b_local, z, pol, scale, "hypergeometric_1F1_large_series<%1%>(a,b,z)"); if (scale != log_scaling) { h2 *= exp(T(scale - log_scaling)); } - boost::math::detail::hypergeometric_1F1_recurrence_a_coefficients coef(a_local + 1, b_local, z); - h = boost::math::tools::apply_recurrence_relation_forward(coef, a_shift - 1, h, h2, &log_scaling); + BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_a_coefficients coef(a_local + 1, b_local, z); + h = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_forward(coef, a_shift - 1, h, h2, &log_scaling); h = hypergeometric_1F1_shift_on_b(h, a, b_local, z, b_shift, pol, log_scaling); } else @@ -402,7 +402,7 @@ b_shift -= 1; b_local += 1; } - T h = boost::math::detail::hypergeometric_1F1_AS_13_3_6(a, b_local, z, T(b_local - a), pol, log_scaling); + T h = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_AS_13_3_6(a, b_local, z, T(b_local - a), pol, log_scaling); return hypergeometric_1F1_shift_on_b(h, a, b_local, z, b_shift, pol, log_scaling); } @@ -487,6 +487,6 @@ return 0; // We don't get here! } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_HYPERGEOMETRIC_1F1_LARGE_ABZ_HPP_ diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_negative_b_regions.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_negative_b_regions.hpp index 3752fec158..b8bdfefc4c 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_negative_b_regions.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_negative_b_regions.hpp @@ -8,8 +8,7 @@ #ifndef BOOST_MATH_DETIAL_1F1_MAP_NEG_B_HPP #define BOOST_MATH_DETIAL_1F1_MAP_NEG_B_HPP -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // // hypergeometric_1F1_negative_b_recurrence_region maps out the domains over which @@ -515,7 +514,7 @@ namespace boost { return 0; } -} } } +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_DETIAL_1F1_MAP_NEG_B_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_recurrence.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_recurrence.hpp index db5ea1da06..3b7a31ce60 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_recurrence.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_recurrence.hpp @@ -17,7 +17,7 @@ #include #include - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { // forward declaration for initial values template @@ -29,10 +29,10 @@ template struct hypergeometric_1F1_recurrence_a_coefficients { - using result_type = boost::math::tuple; + using result_type = BOOST_MATH_NAMESPACE::tuple; - hypergeometric_1F1_recurrence_a_coefficients(const T& a, const T& b, const T& z): - a(a), b(b), z(z) + hypergeometric_1F1_recurrence_a_coefficients(const T& a_, const T& b_, const T& z_): + a(a_), b(b_), z(z_) { } @@ -48,7 +48,7 @@ const T bn = (2 * ai - b + z); const T cn = -ai; - return boost::math::make_tuple(an, bn, cn); + return BOOST_MATH_NAMESPACE::make_tuple(an, bn, cn); } private: @@ -60,10 +60,10 @@ template struct hypergeometric_1F1_recurrence_b_coefficients { - using result_type = boost::math::tuple; + using result_type = BOOST_MATH_NAMESPACE::tuple; - hypergeometric_1F1_recurrence_b_coefficients(const T& a, const T& b, const T& z): - a(a), b(b), z(z) + hypergeometric_1F1_recurrence_b_coefficients(const T& a_, const T& b_, const T& z_): + a(a_), b(b_), z(z_) { } @@ -79,7 +79,7 @@ const T bn = bi * (1 - bi - z); const T cn = z * (bi - a); - return boost::math::make_tuple(an, bn, cn); + return BOOST_MATH_NAMESPACE::make_tuple(an, bn, cn); } private: @@ -93,10 +93,10 @@ template struct hypergeometric_1F1_recurrence_small_b_coefficients { - using result_type = boost::math::tuple; + using result_type = BOOST_MATH_NAMESPACE::tuple; - hypergeometric_1F1_recurrence_small_b_coefficients(const T& a, const T& b, const T& z, int N) : - a(a), b(b), z(z), N(N) + hypergeometric_1F1_recurrence_small_b_coefficients(const T& a_, const T& b_, const T& z_, int N_) : + a(a_), b(b_), z(z_), N(N_) { } @@ -113,7 +113,7 @@ const T bn = bi * (-bi_minus_1 - z); const T cn = z * (bi - a); - return boost::math::make_tuple(an, bn, cn); + return BOOST_MATH_NAMESPACE::make_tuple(an, bn, cn); } private: @@ -126,10 +126,10 @@ template struct hypergeometric_1F1_recurrence_a_and_b_coefficients { - using result_type = boost::math::tuple; + using result_type = BOOST_MATH_NAMESPACE::tuple; - hypergeometric_1F1_recurrence_a_and_b_coefficients(const T& a, const T& b, const T& z, int offset = 0): - a(a), b(b), z(z), offset(offset) + hypergeometric_1F1_recurrence_a_and_b_coefficients(const T& a_, const T& b_, const T& z_, int offset_ = 0): + a(a_), b(b_), z(z_), offset(offset_) { } @@ -146,7 +146,7 @@ const T bn = bi * (z - (b + (offset + i - 1))); const T cn = -ai * z; - return boost::math::make_tuple(an, bn, cn); + return BOOST_MATH_NAMESPACE::make_tuple(an, bn, cn); } private: @@ -166,7 +166,7 @@ template struct hypergeometric_1F1_recurrence_2a_and_2b_coefficients { - typedef boost::math::tuple result_type; + typedef BOOST_MATH_NAMESPACE::tuple result_type; hypergeometric_1F1_recurrence_2a_and_2b_coefficients(const T& a, const T& b, const T& z, int offset = 0) : a(a), b(b), z(z), offset(offset) @@ -185,7 +185,7 @@ + ai * bi * z * (b + (offset + i + 1)) / ((b + (offset + i + 1)) * (z - bi)); const T cn = -ai * (a + (offset + i + 1)) * z * z / ((b + (offset + i + 1)) * (z - bi)); - return boost::math::make_tuple(an, bn, cn); + return BOOST_MATH_NAMESPACE::make_tuple(an, bn, cn); } private: @@ -201,7 +201,7 @@ template struct hypergeometric_1F1_recurrence_2a_coefficients { - typedef boost::math::tuple result_type; + typedef BOOST_MATH_NAMESPACE::tuple result_type; hypergeometric_1F1_recurrence_2a_coefficients(const T& a, const T& b, const T& z, int offset = 0) : a(a), b(b), z(z), offset(offset) @@ -217,7 +217,7 @@ const T bn = (b - ai) * (a + (offset + i - 1)) / (2 * (a + (offset + i - 1)) - b + z) + (2 * ai - b + z) + ai * (b - (a + (offset + i + 1))) / (2 * (a + (offset + i + 1)) - b + z); const T cn = -ai * (a + (offset + i + 1)) / (2 * (a + (offset + i + 1)) - b + z); - return boost::math::make_tuple(an, bn, cn); + return BOOST_MATH_NAMESPACE::make_tuple(an, bn, cn); } private: @@ -233,7 +233,7 @@ template struct hypergeometric_1F1_recurrence_2b_coefficients { - typedef boost::math::tuple result_type; + typedef BOOST_MATH_NAMESPACE::tuple result_type; hypergeometric_1F1_recurrence_2b_coefficients(const T& a, const T& b, const T& z, int offset = 0) : a(a), b(b), z(z), offset(offset) @@ -252,7 +252,7 @@ const T bn = z * bi * bi_m1 * (bi_m1 - a) / (-bi_m1 * (-bi_m2 - z)) + bi * (-bi_m1 - z) + z * (bi - a) * bi_p1 * bi / (bi_p1 * (bi + z)); const T cn = z * z * (bi - a) * (bi_p1 - a) / (bi_p1 * (bi + z)); - return boost::math::make_tuple(an, bn, cn); + return BOOST_MATH_NAMESPACE::make_tuple(an, bn, cn); } private: @@ -270,7 +270,7 @@ template struct hypergeometric_1F1_recurrence_a_plus_b_minus_coefficients { - typedef boost::math::tuple result_type; + typedef BOOST_MATH_NAMESPACE::tuple result_type; hypergeometric_1F1_recurrence_a_plus_b_minus_coefficients(const T& a, const T& b, const T& z, int offset = 0) : a(a), b(b), z(z), offset(offset) @@ -286,7 +286,7 @@ const T bn = z * ((-1 / (ai + z) - 1 / (ai + z - 1)) * (bi + z - 1) + 3) + bi - 1; const T cn = ai * (1 - bi) / (ai + z); - return boost::math::make_tuple(an, bn, cn); + return BOOST_MATH_NAMESPACE::make_tuple(an, bn, cn); } private: @@ -396,10 +396,10 @@ // If the shifts are so large that we would throw an evaluation_error, try the series instead, // even though this will almost certainly throw as well: // - if (b_shift > static_cast(boost::math::policies::get_max_series_iterations())) + if (b_shift > static_cast(BOOST_MATH_NAMESPACE::policies::get_max_series_iterations())) return hypergeometric_1F1_checked_series_impl(a, b, z, pol, log_scaling); - if (a_shift > static_cast(boost::math::policies::get_max_series_iterations())) + if (a_shift > static_cast(BOOST_MATH_NAMESPACE::policies::get_max_series_iterations())) return hypergeometric_1F1_checked_series_impl(a, b, z, pol, log_scaling); int a_b_shift = b < 0 ? itrunc(b + b_shift) : b_shift; // The max we can shift on a and b together @@ -444,12 +444,12 @@ T second {}; long long scale1 {}; long long scale2 {}; - first = boost::math::detail::hypergeometric_1F1_imp(T(a + a_shift), T(b + b_shift), z, pol, scale1); + first = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(T(a + a_shift), T(b + b_shift), z, pol, scale1); // // It would be good to compute "second" from first and the ratio - unfortunately we are right on the cusp // recursion on a switching from stable backwards to stable forwards behaviour and so this is not possible here. // - second = boost::math::detail::hypergeometric_1F1_imp(T(a + a_shift - 1), T(b + b_shift), z, pol, scale2); + second = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_imp(T(a + a_shift - 1), T(b + b_shift), z, pol, scale2); if (scale1 != scale2) second *= exp(T(scale2 - scale1)); log_scaling += scale1; @@ -459,7 +459,7 @@ // and want to recurse until [a + a_shift - leading_a_shift, b + b_shift, z] and [a + a_shift - leadng_a_shift - 1, b + b_shift, z] // which is leading_a_shift -1 steps. // - second = boost::math::tools::apply_recurrence_relation_backward( + second = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_backward( hypergeometric_1F1_recurrence_a_coefficients(a + a_shift - 1, b + b_shift, z), leading_a_shift, first, second, &log_scaling, &first); @@ -480,7 +480,7 @@ // Now apply a_b_shift - 1 recursions to get down to // [a + 1, b + trailing_b_shift + 1, z] and [a, b + trailing_b_shift, z] // - second = boost::math::tools::apply_recurrence_relation_backward( + second = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_backward( hypergeometric_1F1_recurrence_a_and_b_coefficients(a, b + b_shift - a_b_shift, z, a_b_shift - 1), a_b_shift - 1, first, second, &log_scaling, &first); // @@ -508,7 +508,7 @@ // if (trailing_b_shift) { - second = boost::math::tools::apply_recurrence_relation_backward( + second = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_backward( hypergeometric_1F1_recurrence_small_b_coefficients(a, b, z, trailing_b_shift), trailing_b_shift, first, second, &log_scaling); } @@ -517,6 +517,6 @@ - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_HYPERGEOMETRIC_1F1_RECURRENCE_HPP_ diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_scaled_series.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_scaled_series.hpp index e128e3d7ad..ad10efb2da 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_scaled_series.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_scaled_series.hpp @@ -7,10 +7,12 @@ #ifndef BOOST_MATH_HYPERGEOMETRIC_1F1_SCALED_SERIES_HPP #define BOOST_MATH_HYPERGEOMETRIC_1F1_SCALED_SERIES_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif - namespace boost{ namespace math{ namespace detail{ + BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template T hypergeometric_1F1_scaled_series(const T& a, const T& b, T z, const Policy& pol, const char* function) @@ -22,9 +24,9 @@ // and keep track of the integer scaling factor n. At the end we can perform // an exact subtraction of n from z and scale the result: // - T sum(0), term(1), upper_limit(sqrt(boost::math::tools::max_value())), diff; + T sum(0), term(1), upper_limit(sqrt(BOOST_MATH_NAMESPACE::tools::max_value())), diff; unsigned n = 0; - long long log_scaling_factor = 1 - lltrunc(boost::math::tools::log_max_value()); + long long log_scaling_factor = 1 - lltrunc(BOOST_MATH_NAMESPACE::tools::log_max_value()); T scaling_factor = exp(T(log_scaling_factor)); std::intmax_t current_scaling = 0; @@ -38,11 +40,11 @@ current_scaling += log_scaling_factor; } term *= (((a + n) / ((b + n) * (n + 1))) * z); - if (n > boost::math::policies::get_max_series_iterations()) - return boost::math::policies::raise_evaluation_error(function, "Series did not converge, best value is %1%", sum, pol); + if (n > BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()) + return BOOST_MATH_NAMESPACE::policies::raise_evaluation_error(function, "Series did not converge, best value is %1%", sum, pol); ++n; diff = fabs(term / sum); - } while (diff > boost::math::policies::get_epsilon()); + } while (diff > BOOST_MATH_NAMESPACE::policies::get_epsilon()); z = -z - current_scaling; while (z < log_scaling_factor) @@ -55,6 +57,6 @@ - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_1F1_SCALED_SERIES_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_small_a_negative_b_by_ratio.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_small_a_negative_b_by_ratio.hpp index 4414a75d86..91d181276a 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_small_a_negative_b_by_ratio.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_small_a_negative_b_by_ratio.hpp @@ -8,10 +8,12 @@ #ifndef BOOST_MATH_HYPERGEOMETRIC_1F1_SMALL_A_NEG_B_HPP #define BOOST_MATH_HYPERGEOMETRIC_1F1_SMALL_A_NEG_B_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { // forward declaration for initial values template @@ -29,12 +31,12 @@ { { 0.0f, -47.3046f }, {-6.7275f, -52.0351f }, { -8.9543f, -57.2386f }, {-11.9182f, -62.9625f }, {-14.421f, -69.2587f }, {-19.1943f, -76.1846f }, {-23.2252f, -83.803f }, {-28.1024f, -92.1833f }, {-34.0039f, -101.402f }, {-37.4043f, -111.542f }, {-45.2593f, -122.696f }, {-54.7637f, -134.966f }, {-60.2401f, -148.462f }, {-72.8905f, -163.308f }, {-88.1975f, -179.639f }, {-88.1975f, -197.603f }, {-106.719f, -217.363f }, {-129.13f, -239.1f }, {-142.043f, -263.01f }, {-156.247f, -289.311f }, {-189.059f, -318.242f }, {-207.965f, -350.066f }, {-228.762f, -385.073f }, {-276.801f, -423.58f }, {-304.482f, -465.938f }, {-334.93f, -512.532f }, {-368.423f, -563.785f }, {-405.265f, -620.163f }, {-445.792f, -682.18f }, {-539.408f, -750.398f }, {-593.349f, -825.437f }, {-652.683f, -907.981f }, {-717.952f, -998.779f } }; - auto p = std::lower_bound(max_b, max_b + sizeof(max_b) / sizeof(max_b[0]), z, [](const float (&a)[2], const T& z) { return a[1] > z; }); + auto p = std::lower_bound(max_b, max_b + sizeof(max_b) / sizeof(max_b[0]), z, [](const float (&a)[2], const T& value) { return a[1] > value; }); T b = p - max_b ? (*--p)[0] : 0; // // We need approximately an extra 10 recurrences per 50 binary digits precision above that of double: // - b += (std::max)(0, boost::math::tools::digits() - 53) / 5; + b += (std::max)(0, BOOST_MATH_NAMESPACE::tools::digits() - 53) / 5; return b; } @@ -47,14 +49,14 @@ // then recurse until b > 0, compute a reference value and normalize (Millers method). // int iterations = itrunc(-b, pol); - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T ratio = boost::math::tools::function_ratio_from_forwards_recurrence(boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients(a, b, z), boost::math::tools::epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_small_a_negative_b_by_ratio<%1%>(%1%,%1%,%1%)", max_iter, pol); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T ratio = BOOST_MATH_NAMESPACE::tools::function_ratio_from_forwards_recurrence(BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients(a, b, z), BOOST_MATH_NAMESPACE::tools::epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::hypergeometric_1F1_small_a_negative_b_by_ratio<%1%>(%1%,%1%,%1%)", max_iter, pol); T first = 1; T second = 1 / ratio; long long scaling1 = 0; BOOST_MATH_ASSERT(b + iterations != a); - second = boost::math::tools::apply_recurrence_relation_forward(boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients(a, b + 1, z), iterations, first, second, &scaling1); + second = BOOST_MATH_NAMESPACE::tools::apply_recurrence_relation_forward(BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_recurrence_b_coefficients(a, b + 1, z), iterations, first, second, &scaling1); long long scaling2 = 0; first = hypergeometric_1F1_imp(a, T(b + iterations + 1), z, pol, scaling2); // @@ -65,6 +67,6 @@ } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_1F1_SMALL_A_NEG_B_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_asym.hpp b/include/boost/math/special_functions/detail/hypergeometric_asym.hpp index e603957180..8e537994ff 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_asym.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_asym.hpp @@ -18,7 +18,7 @@ #pragma warning(disable:4127) #endif - namespace boost { namespace math { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -44,13 +44,15 @@ } else { - e = z > static_cast((std::numeric_limits::max)()) ? (std::numeric_limits::max)() : lltrunc(z, pol); + e = z >= static_cast((std::numeric_limits::max)()) ? (std::numeric_limits::max)() : lltrunc(z, pol); log_scaling += e; + if (z - e > tools::log_max_value()) + return policies::raise_overflow_error(function, nullptr, pol); prefix = exp(z - e); } if ((fabs(a) < 10) && (fabs(b) < 10)) { - prefix *= pow(z, a) * pow(z, -b) * boost::math::tgamma(b, pol) / boost::math::tgamma(a, pol); + prefix *= pow(z, a) * pow(z, -b) * BOOST_MATH_NAMESPACE::tgamma(b, pol) / BOOST_MATH_NAMESPACE::tgamma(a, pol); } else { @@ -59,12 +61,12 @@ log_scaling += e; prefix *= exp(t - e); - t = boost::math::lgamma(b, &s, pol); + t = BOOST_MATH_NAMESPACE::lgamma(b, &s, pol); e = lltrunc(t, pol); log_scaling += e; prefix *= s * exp(t - e); - t = boost::math::lgamma(a, &s, pol); + t = BOOST_MATH_NAMESPACE::lgamma(a, &s, pol); e = lltrunc(t, pol); log_scaling -= e; prefix /= s * exp(t - e); @@ -89,16 +91,16 @@ term /= ++k; a1_poch += 1; a2_poch += 1; - if (fabs(sum) * boost::math::policies::get_epsilon() > fabs(term)) + if (fabs(sum) * BOOST_MATH_NAMESPACE::policies::get_epsilon() > fabs(term)) break; - if(fabs(sum) / abs_sum < boost::math::policies::get_epsilon()) - return boost::math::policies::raise_evaluation_error(function, "Large-z asymptotic approximation to 1F1 has destroyed all the digits in the result due to cancellation. Current best guess is %1%", + if(fabs(sum) / abs_sum < BOOST_MATH_NAMESPACE::policies::get_epsilon()) + return BOOST_MATH_NAMESPACE::policies::raise_evaluation_error(function, "Large-z asymptotic approximation to 1F1 has destroyed all the digits in the result due to cancellation. Current best guess is %1%", prefix * sum, Policy()); - if(k > boost::math::policies::get_max_series_iterations()) - return boost::math::policies::raise_evaluation_error(function, "1F1: Unable to locate solution in a reasonable time:" + if(k > BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()) + return BOOST_MATH_NAMESPACE::policies::raise_evaluation_error(function, "1F1: Unable to locate solution in a reasonable time:" " large-z asymptotic approximation. Current best guess is %1%", prefix * sum, Policy()); if((k > 10) && (fabs(term) > fabs(last_term))) - return boost::math::policies::raise_evaluation_error(function, "Large-z asymptotic approximation to 1F1 is divergent. Current best guess is %1%", prefix * sum, Policy()); + return BOOST_MATH_NAMESPACE::policies::raise_evaluation_error(function, "Large-z asymptotic approximation to 1F1 is divergent. Current best guess is %1%", prefix * sum, Policy()); } while (true); return prefix * sum; @@ -170,7 +172,7 @@ return in_region; } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/detail/hypergeometric_cf.hpp b/include/boost/math/special_functions/detail/hypergeometric_cf.hpp index 236cc551a6..6c72f53cb0 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_cf.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_cf.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_MATH_DETAIL_HYPERGEOMETRIC_CF_HPP #define BOOST_MATH_DETAIL_HYPERGEOMETRIC_CF_HPP - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { // primary template for term of continued fraction template @@ -169,9 +169,9 @@ std::uintmax_t max_iter = policies::get_max_series_iterations(); const T result = tools::continued_fraction_b( term, - boost::math::policies::get_epsilon(), + BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations( + BOOST_MATH_NAMESPACE::policies::check_series_iterations( "boost::math::hypergeometric_pFq_cf<%1%>(%1%,%1%,%1%)", max_iter, pol); @@ -223,6 +223,6 @@ return result; } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_DETAIL_HYPERGEOMETRIC_CF_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_pFq_checked_series.hpp b/include/boost/math/special_functions/detail/hypergeometric_pFq_checked_series.hpp index 895c586482..04e131c579 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_pFq_checked_series.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_pFq_checked_series.hpp @@ -11,19 +11,21 @@ # define BOOST_MATH_PFQ_MAX_B_TERMS 5 #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include #include - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { template unsigned set_crossover_locations(const Seq& aj, const Seq& bj, const Real& z, unsigned int* crossover_locations) { BOOST_MATH_STD_USING - using nothrow_policy = typename boost::math::policies::normalise, boost::math::policies::rounding_error>::type; + using nothrow_policy = typename BOOST_MATH_NAMESPACE::policies::normalise, BOOST_MATH_NAMESPACE::policies::rounding_error>::type; unsigned N_terms = 0; if(aj.size() == 1 && bj.size() == 1) @@ -123,14 +125,14 @@ std::pair hypergeometric_pFq_checked_series_impl(const Seq& aj, const Seq& bj, const Real& z, const Policy& pol, const Terminal& termination, long long& log_scale) { BOOST_MATH_STD_USING - using nothrow_policy = typename boost::math::policies::normalise>::type; + using nothrow_policy = typename BOOST_MATH_NAMESPACE::policies::normalise>::type; Real result = 1; Real abs_result = 1; Real term = 1; Real term0 = 0; - Real tol = boost::math::policies::get_epsilon(); + Real tol = BOOST_MATH_NAMESPACE::policies::get_epsilon(); std::uintmax_t k = 0; - Real upper_limit(sqrt(boost::math::tools::max_value())), diff; + Real upper_limit(sqrt(BOOST_MATH_NAMESPACE::tools::max_value())), diff; if ((tools::max_value() / fabs(z) < upper_limit)) { upper_limit = tools::max_value() / fabs(z); @@ -143,7 +145,7 @@ } } Real lower_limit(1 / upper_limit); - long long log_scaling_factor = lltrunc(boost::math::tools::log_max_value(), nothrow_policy()) - 2; + long long log_scaling_factor = lltrunc(BOOST_MATH_NAMESPACE::tools::log_max_value(), nothrow_policy()) - 2; Real scaling_factor = exp(Real(log_scaling_factor)); Real term_m1; long long local_scaling = 0; @@ -223,7 +225,7 @@ if (*bi + k == 0) { // The series is undefined: - result = boost::math::policies::raise_domain_error("boost::math::hypergeometric_pFq<%1%>", "One of the b values was the negative integer %1%", *bi, pol); + result = BOOST_MATH_NAMESPACE::policies::raise_domain_error("boost::math::hypergeometric_pFq<%1%>", "One of the b values was the negative integer %1%", *bi, pol); return std::make_pair(result, result); } term /= *bi + k; @@ -269,7 +271,7 @@ if (have_no_correct_bits) { // We have no correct bits in the result... just give up! - result = boost::math::policies::raise_evaluation_error("boost::math::hypergeometric_pFq<%1%>", "Cancellation is so severe that no bits in the result are correct, last result was %1%", Real(result * exp(Real(log_scale))), pol); + result = BOOST_MATH_NAMESPACE::policies::raise_evaluation_error("boost::math::hypergeometric_pFq<%1%>", "Cancellation is so severe that no bits in the result are correct, last result was %1%", Real(result * exp(Real(log_scale))), pol); return std::make_pair(result, result); } else @@ -440,7 +442,7 @@ if (*bi + k == 0) { // The series is undefined: - result = boost::math::policies::raise_domain_error("boost::math::hypergeometric_pFq<%1%>", "One of the b values was the negative integer %1%", *bi, pol); + result = BOOST_MATH_NAMESPACE::policies::raise_domain_error("boost::math::hypergeometric_pFq<%1%>", "One of the b values was the negative integer %1%", *bi, pol); return std::make_pair(result, result); } term /= *bi + k; @@ -475,10 +477,10 @@ else d = fabs(term * exp(Real(rescale)) / result); } - if (d < boost::math::policies::get_epsilon()) + if (d < BOOST_MATH_NAMESPACE::policies::get_epsilon()) break; } - } while (!termination(k - s) && ((diff > boost::math::policies::get_epsilon()) || terms_are_growing)); + } while (!termination(k - s) && ((diff > BOOST_MATH_NAMESPACE::policies::get_epsilon()) || terms_are_growing)); //std::cout << "Norm loop result = " << std::setprecision(35) << boost::multiprecision::mpfr_float_50(loop_result)* exp(boost::multiprecision::mpfr_float_50(loop_scale)) << std::endl; // @@ -543,7 +545,7 @@ if (*bi + k == 0) { // The series is undefined: - result = boost::math::policies::raise_domain_error("boost::math::hypergeometric_pFq<%1%>", "One of the b values was the negative integer %1%", *bi, pol); + result = BOOST_MATH_NAMESPACE::policies::raise_domain_error("boost::math::hypergeometric_pFq<%1%>", "One of the b values was the negative integer %1%", *bi, pol); return std::make_pair(result, result); } term *= *bi + k; @@ -577,7 +579,7 @@ else d = fabs(term * exp(Real(rescale)) / result); } - if (d < boost::math::policies::get_epsilon()) + if (d < BOOST_MATH_NAMESPACE::policies::get_epsilon()) break; } @@ -597,7 +599,7 @@ loop_scale -= log_scaling_factor; } diff = fabs(term / loop_result); - } while (!termination(s - k) && ((diff > boost::math::policies::get_epsilon()) || (fabs(term) > fabs(term_m1)))); + } while (!termination(s - k) && ((diff > BOOST_MATH_NAMESPACE::policies::get_epsilon()) || (fabs(term) > fabs(term_m1)))); //std::cout << "Norm loop result = " << std::setprecision(35) << boost::multiprecision::mpfr_float_50(loop_result)* exp(boost::multiprecision::mpfr_float_50(loop_scale)) << std::endl; // @@ -661,15 +663,15 @@ Real hypergeometric_pFq_checked_series_impl(const Seq& aj, const Seq& bj, const Real& z, const Policy& pol, long long& log_scale) { BOOST_MATH_STD_USING - iteration_terminator term(boost::math::policies::get_max_series_iterations()); + iteration_terminator term(BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()); std::pair result = hypergeometric_pFq_checked_series_impl(aj, bj, z, pol, term, log_scale); // // Check to see how many digits we've lost, if it's more than half, raise an evaluation error - // this is an entirely arbitrary cut off, but not unreasonable. // - if (result.second * sqrt(boost::math::policies::get_epsilon()) > abs(result.first)) + if (result.second * sqrt(BOOST_MATH_NAMESPACE::policies::get_epsilon()) > abs(result.first)) { - return boost::math::policies::raise_evaluation_error("boost::math::hypergeometric_pFq<%1%>", "Cancellation is so severe that fewer than half the bits in the result are correct, last result was %1%", Real(result.first * exp(Real(log_scale))), pol); + return BOOST_MATH_NAMESPACE::policies::raise_evaluation_error("boost::math::hypergeometric_pFq<%1%>", "Cancellation is so severe that fewer than half the bits in the result are correct, last result was %1%", Real(result.first * exp(Real(log_scale))), pol); } return result.first; } @@ -682,6 +684,6 @@ return hypergeometric_pFq_checked_series_impl(aj, bj, z, pol, log_scale); } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_HYPERGEOMETRIC_PFQ_SERIES_HPP_ diff --git a/include/boost/math/special_functions/detail/hypergeometric_pade.hpp b/include/boost/math/special_functions/detail/hypergeometric_pade.hpp index 29d8179114..1cae280fc6 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_pade.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_pade.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_MATH_HYPERGEOMETRIC_PADE_HPP #define BOOST_MATH_HYPERGEOMETRIC_PADE_HPP - namespace boost{ namespace math{ namespace detail{ + BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // Luke: C ---------- SUBROUTINE R1F1P(CP, Z, A, B, N) ---------- // Luke: C ----- PADE APPROXIMATION OF 1F1( 1 ; CP ; -Z ) ------- @@ -34,7 +34,7 @@ T b1 = one + (z / ct1); T a1 = b1 - (z / cp); - const unsigned max_iterations = boost::math::policies::get_max_series_iterations(); + const unsigned max_iterations = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); T b2 = T(0), a2 = T(0); T result = T(0), prev_result; @@ -56,7 +56,7 @@ result = a2 / b2; // condition for interruption - if ((fabs(result) * boost::math::tools::epsilon()) > fabs(result - prev_result)) + if ((fabs(result) * BOOST_MATH_NAMESPACE::tools::epsilon()) > fabs(result - prev_result)) break; b0 = b1; b1 = b2; @@ -90,7 +90,7 @@ T b1 = one + ((z / (cp + one)) * (bp + one)); T a1 = b1 - ((bp / cp) * z); - const unsigned max_iterations = boost::math::policies::get_max_series_iterations(); + const unsigned max_iterations = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); T b2 = T(0), a2 = T(0); T result = T(0), prev_result = a1 / b1; @@ -114,7 +114,7 @@ result = a2 / b2; // condition for interruption - if ((fabs(result) * boost::math::tools::epsilon()) > fabs(result - prev_result)) + if ((fabs(result) * BOOST_MATH_NAMESPACE::tools::epsilon()) > fabs(result - prev_result)) break; b0 = b1; b1 = b2; @@ -126,6 +126,6 @@ return a2 / b2; } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_PADE_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_rational.hpp b/include/boost/math/special_functions/detail/hypergeometric_rational.hpp index b958e3af66..a48cd654fc 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_rational.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_rational.hpp @@ -10,9 +10,11 @@ #ifndef BOOST_MATH_HYPERGEOMETRIC_RATIONAL_HPP #define BOOST_MATH_HYPERGEOMETRIC_RATIONAL_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif - namespace boost{ namespace math{ namespace detail{ + BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // Luke: C ------- SUBROUTINE R1F1P(AP, CP, Z, A, B, N) --------- // Luke: C --- RATIONAL APPROXIMATION OF 1F1( AP ; CP ; -Z ) ---- @@ -42,7 +44,7 @@ T a3 = b3 - ((one + ct2) * ct1); ct1 = three; - const unsigned max_iterations = boost::math::policies::get_max_series_iterations(); + const unsigned max_iterations = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); T a4 = T(0), b4 = T(0); T result = T(0), prev_result = a3 / b3; @@ -66,7 +68,7 @@ result = a4 / b4; // condition for interruption - if ((fabs(result) * boost::math::tools::epsilon()) > fabs(result - prev_result) / fabs(result)) + if ((fabs(result) * BOOST_MATH_NAMESPACE::tools::epsilon()) > fabs(result - prev_result) / fabs(result)) break; b1 = b2; b2 = b3; b3 = b4; @@ -162,6 +164,6 @@ return a4 / b4; } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_RATIONAL_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_separated_series.hpp b/include/boost/math/special_functions/detail/hypergeometric_separated_series.hpp index 3baff69f41..3ac4d3657f 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_separated_series.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_separated_series.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_MATH_HYPERGEOMETRIC_SEPARATED_SERIES_HPP #define BOOST_MATH_HYPERGEOMETRIC_SEPARATED_SERIES_HPP - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { template inline T hypergeometric_1F1_separated_series(const T& a, const T& b, const T& z, const Policy& pol) @@ -45,6 +45,6 @@ return result; } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_SEPARATED_SERIES_HPP diff --git a/include/boost/math/special_functions/detail/hypergeometric_series.hpp b/include/boost/math/special_functions/detail/hypergeometric_series.hpp index 2a2a54af9b..836fc0c646 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_series.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_series.hpp @@ -10,14 +10,16 @@ #ifndef BOOST_MATH_DETAIL_HYPERGEOMETRIC_SERIES_HPP #define BOOST_MATH_DETAIL_HYPERGEOMETRIC_SERIES_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include #include #include - namespace boost { namespace math { namespace detail { + BOOST_MATH_NAMESPACE_BEGIN namespace detail { // primary template for term of Taylor series template @@ -29,8 +31,8 @@ { typedef T result_type; - hypergeometric_pFq_generic_series_term(const T& b, const T& z) - : n(0), term(1), b(b), z(z) + hypergeometric_pFq_generic_series_term(const T& b_, const T& z_) + : n(0), term(1), b(b_), z(z_) { } @@ -55,8 +57,8 @@ { typedef T result_type; - hypergeometric_pFq_generic_series_term(const T& a, const T& z) - : n(0), term(1), a(a), z(z) + hypergeometric_pFq_generic_series_term(const T& a_, const T& z_) + : n(0), term(1), a(a_), z(z_) { } @@ -81,8 +83,8 @@ { typedef T result_type; - hypergeometric_pFq_generic_series_term(const T& a, const T& b, const T& z) - : n(0), term(1), a(a), b(b), z(z) + hypergeometric_pFq_generic_series_term(const T& a_, const T& b_, const T& z_) + : n(0), term(1), a(a_), b(b_), z(z_) { } @@ -107,8 +109,8 @@ { typedef T result_type; - hypergeometric_pFq_generic_series_term(const T& a, const T& b1, const T& b2, const T& z) - : n(0), term(1), a(a), b1(b1), b2(b2), z(z) + hypergeometric_pFq_generic_series_term(const T& a_, const T& b1_, const T& b2_, const T& z_) + : n(0), term(1), a(a_), b1(b1_), b2(b2_), z(z_) { } @@ -133,8 +135,8 @@ { typedef T result_type; - hypergeometric_pFq_generic_series_term(const T& a1, const T& a2, const T& z) - : n(0), term(1), a1(a1), a2(a2), z(z) + hypergeometric_pFq_generic_series_term(const T& a1_, const T& a2_, const T& z_) + : n(0), term(1), a1(a1_), a2(a2_), z(z_) { } @@ -159,8 +161,8 @@ { typedef T result_type; - hypergeometric_pFq_generic_series_term(const T& a1, const T& a2, const T& b, const T& z) - : n(0), term(1), a1(a1), a2(a2), b(b), z(z) + hypergeometric_pFq_generic_series_term(const T& a1_, const T& a2_, const T& b_, const T& z_) + : n(0), term(1), a1(a1_), a2(a2_), b(b_), z(z_) { } @@ -189,7 +191,7 @@ BOOST_MATH_STD_USING std::uintmax_t max_iter = policies::get_max_series_iterations(); - const T result = boost::math::tools::sum_series(term, boost::math::policies::get_epsilon(), max_iter); + const T result = BOOST_MATH_NAMESPACE::tools::sum_series(term, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); policies::check_series_iterations("boost::math::hypergeometric_pFq_generic_series<%1%>(%1%,%1%,%1%)", max_iter, pol); return result; @@ -239,7 +241,7 @@ return r; } int s1, s2; - auto r = static_cast(boost::math::lgamma(T(z + n), &s1, pol) - boost::math::lgamma(z, &s2, pol)); + auto r = static_cast(BOOST_MATH_NAMESPACE::lgamma(T(z + n), &s1, pol) - BOOST_MATH_NAMESPACE::lgamma(z, &s2, pol)); if(s) *s = s1 * s2; return r; @@ -250,10 +252,10 @@ inline T hypergeometric_1F1_generic_series(const T& a, const T& b, const T& z, const Policy& pol, long long& log_scaling, const char* function) { BOOST_MATH_STD_USING - T sum(0), term(1), upper_limit(sqrt(boost::math::tools::max_value())), diff; + T sum(0), term(1), upper_limit(sqrt(BOOST_MATH_NAMESPACE::tools::max_value())), diff; T lower_limit(1 / upper_limit); unsigned n = 0; - long long log_scaling_factor = lltrunc(boost::math::tools::log_max_value()) - 2; + long long log_scaling_factor = lltrunc(BOOST_MATH_NAMESPACE::tools::log_max_value()) - 2; T scaling_factor = exp(T(log_scaling_factor)); T term_m1 = 0; long long local_scaling = 0; @@ -281,7 +283,7 @@ summit_location = itrunc(t); } - if (summit_location > boost::math::policies::get_max_series_iterations() / 4) + if (summit_location > BOOST_MATH_NAMESPACE::policies::get_max_series_iterations() / 4) { // // Skip forward to the location of the largest term in the series and @@ -322,11 +324,11 @@ } term_m1 = term; term *= (((a + n) / ((b + n) * (n + 1))) * z); - if (n - summit_location > boost::math::policies::get_max_series_iterations()) - return boost::math::policies::raise_evaluation_error(function, "Series did not converge, best value is %1%", sum, pol); + if (n - summit_location > BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()) + return BOOST_MATH_NAMESPACE::policies::raise_evaluation_error(function, "Series did not converge, best value is %1%", sum, pol); ++n; diff = fabs(term / sum); - } while ((diff > boost::math::policies::get_epsilon()) || (fabs(term_m1) < fabs(term)) || (small_a && n < 10)); + } while ((diff > BOOST_MATH_NAMESPACE::policies::get_epsilon()) || (fabs(term_m1) < fabs(term)) || (small_a && n < 10)); // // See if we need to go backwards as well: @@ -363,11 +365,11 @@ } term_m1 = term; term *= (b + (n - 1)) * n / ((a + (n - 1)) * z); - if (summit_location - n > boost::math::policies::get_max_series_iterations()) - return boost::math::policies::raise_evaluation_error(function, "Series did not converge, best value is %1%", sum, pol); + if (summit_location - n > BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()) + return BOOST_MATH_NAMESPACE::policies::raise_evaluation_error(function, "Series did not converge, best value is %1%", sum, pol); --n; diff = fabs(term / sum); - } while ((diff > boost::math::policies::get_epsilon()) || (fabs(term_m1) < fabs(term))); + } while ((diff > BOOST_MATH_NAMESPACE::policies::get_epsilon()) || (fabs(term_m1) < fabs(term))); } if (have_minima && n && summit_location) @@ -397,12 +399,12 @@ } //term_m1 = term; term *= (((a + n) / ((b + n) * (n + 1))) * z); - if (n > boost::math::policies::get_max_series_iterations()) - return boost::math::policies::raise_evaluation_error(function, "Series did not converge, best value is %1%", sum, pol); + if (n > BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()) + return BOOST_MATH_NAMESPACE::policies::raise_evaluation_error(function, "Series did not converge, best value is %1%", sum, pol); if (++n == backstop) break; // we've caught up with ourselves. diff = fabs(term / sum); - } while ((diff > boost::math::policies::get_epsilon())/* || (fabs(term_m1) < fabs(term))*/); + } while ((diff > BOOST_MATH_NAMESPACE::policies::get_epsilon())/* || (fabs(term_m1) < fabs(term))*/); } //std::cout << sum << std::endl; return sum; @@ -429,6 +431,6 @@ return detail::sum_pFq_series(s, pol); } - } } } // namespaces + } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_DETAIL_HYPERGEOMETRIC_SERIES_HPP diff --git a/include/boost/math/special_functions/detail/ibeta_inv_ab.hpp b/include/boost/math/special_functions/detail/ibeta_inv_ab.hpp index aab18f50f1..c97fc65ad8 100644 --- a/include/boost/math/special_functions/detail/ibeta_inv_ab.hpp +++ b/include/boost/math/special_functions/detail/ibeta_inv_ab.hpp @@ -23,7 +23,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template struct beta_inv_ab_t @@ -32,8 +32,8 @@ struct beta_inv_ab_t BOOST_MATH_GPU_ENABLED T operator()(T a) { return invert ? - p - boost::math::ibetac(swap_ab ? b : a, swap_ab ? a : b, z, Policy()) - : boost::math::ibeta(swap_ab ? b : a, swap_ab ? a : b, z, Policy()) - p; + p - BOOST_MATH_NAMESPACE::ibetac(swap_ab ? b : a, swap_ab ? a : b, z, Policy()) + : BOOST_MATH_NAMESPACE::ibeta(swap_ab ? b : a, swap_ab ? a : b, z, Policy()) - p; } private: T b, z, p; @@ -54,7 +54,7 @@ BOOST_MATH_GPU_ENABLED T inverse_negative_binomial_cornish_fisher(T n, T sf, T s // kurtosis: T k = (6 - sf * (5+sfc)) / (n * (sfc)); // Get the inverse of a std normal distribution: - T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two(); + T x = BOOST_MATH_NAMESPACE::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two(); // Set the sign: if(p < 0.5) x = -x; @@ -153,8 +153,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_ab_imp(const T& b, const T& z, const T& p, co // // Max iterations permitted: // - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); - boost::math::pair r = bracket_and_solve_root(f, guess, factor, swap_ab ? true : false, tol, max_iter, pol); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::pair r = bracket_and_solve_root(f, guess, factor, swap_ab ? true : false, tol, max_iter, pol); if(max_iter >= policies::get_max_root_iterations()) return policies::raise_evaluation_error("boost::math::ibeta_invab_imp<%1%>(%1%,%1%,%1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol); return (r.first + r.second) / 2; @@ -298,32 +298,31 @@ template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibeta_inva(RT1 b, RT2 x, RT3 p) { - return boost::math::ibeta_inva(b, x, p, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ibeta_inva(b, x, p, policies::policy<>()); } template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibetac_inva(RT1 b, RT2 x, RT3 q) { - return boost::math::ibetac_inva(b, x, q, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ibetac_inva(b, x, q, policies::policy<>()); } template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibeta_invb(RT1 a, RT2 x, RT3 p) { - return boost::math::ibeta_invb(a, x, p, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ibeta_invb(a, x, p, policies::policy<>()); } template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ibetac_invb(RT1 a, RT2 x, RT3 q) { - return boost::math::ibetac_invb(a, x, q, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ibetac_invb(a, x, q, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SP_DETAIL_BETA_INV_AB diff --git a/include/boost/math/special_functions/detail/ibeta_inverse.hpp b/include/boost/math/special_functions/detail/ibeta_inverse.hpp index 2465a11ed6..abf66e7925 100644 --- a/include/boost/math/special_functions/detail/ibeta_inverse.hpp +++ b/include/boost/math/special_functions/detail/ibeta_inverse.hpp @@ -20,7 +20,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // // Helper object used by root finding @@ -31,17 +31,17 @@ struct temme_root_finder { BOOST_MATH_GPU_ENABLED temme_root_finder(const T t_, const T a_) : t(t_), a(a_) { BOOST_MATH_ASSERT( - math::tools::epsilon() <= a && !(boost::math::isinf)(a)); + BOOST_MATH_NAMESPACE::tools::epsilon() <= a && !(BOOST_MATH_NAMESPACE::isinf)(a)); } - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(T x) + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(T x) { BOOST_MATH_STD_USING // ADL of std names T y = 1 - x; T f = log(x) + a * log(y) + t; T f1 = (1 / x) - (a / (y)); - return boost::math::make_tuple(f, f1); + return BOOST_MATH_NAMESPACE::make_tuple(f, f1); } private: T t, a; @@ -63,7 +63,7 @@ BOOST_MATH_GPU_ENABLED T temme_method_1_ibeta_inverse(T a, T b, T z, const Polic // get the first approximation for eta from the inverse // error function (Eq: 2.9 and 2.10). // - T eta0 = boost::math::erfc_inv(2 * z, pol); + T eta0 = BOOST_MATH_NAMESPACE::erfc_inv(2 * z, pol); eta0 /= -sqrt(a / 2); T terms[4] = { eta0 }; @@ -148,7 +148,7 @@ BOOST_MATH_GPU_ENABLED T temme_method_2_ibeta_inverse(T /*a*/, T /*b*/, T z, T r // Get first estimate for eta, see Eq 3.9 and 3.10, // but note there is a typo in Eq 3.10: // - T eta0 = boost::math::erfc_inv(2 * z, pol); + T eta0 = BOOST_MATH_NAMESPACE::erfc_inv(2 * z, pol); eta0 /= -sqrt(r / 2); T s = sin(theta); @@ -311,7 +311,7 @@ BOOST_MATH_GPU_ENABLED T temme_method_2_ibeta_inverse(T /*a*/, T /*b*/, T z, T r temme_root_finder(-lu, alpha), x, lower, upper, policies::digits() / 2); #ifndef BOOST_MATH_NO_EXCEPTIONS } - catch (const boost::math::evaluation_error&) + catch (const BOOST_MATH_NAMESPACE::evaluation_error&) { // Due to numerical instability we may have cases where no root is found when // in fact we should just touch the origin. We simply ignore the error here @@ -342,9 +342,9 @@ BOOST_MATH_GPU_ENABLED T temme_method_3_ibeta_inverse(T a, T b, T p, T q, const // T eta0; if(p < q) - eta0 = boost::math::gamma_q_inv(b, p, pol); + eta0 = BOOST_MATH_NAMESPACE::gamma_q_inv(b, p, pol); else - eta0 = boost::math::gamma_p_inv(b, q, pol); + eta0 = BOOST_MATH_NAMESPACE::gamma_p_inv(b, q, pol); eta0 /= a; // // Define the variables and powers we'll need later on: @@ -440,7 +440,7 @@ struct ibeta_roots BOOST_MATH_GPU_ENABLED ibeta_roots(T _a, T _b, T t, bool inv = false) : a(_a), b(_b), target(t), invert(inv) {} - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(T x) + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(T x) { BOOST_MATH_STD_USING // ADL of std names @@ -456,23 +456,68 @@ struct ibeta_roots if(x == 0) x = tools::min_value() * 64; - T f2 = f1 * (-y * a + (b - 2) * x + 1); + // + // Second derivative: f1 * ((a - 1) / x - (b - 1) / y). + // f1 already carries the sign for the inverted case, so + // no further sign change is needed here: + // + T f2 = f1 * (y * a - (b - 2) * x - 1); if(fabs(f2) < y * x * tools::max_value()) f2 /= (y * x); - if(invert) - f2 = -f2; // make sure we don't have a zero derivative: if(f1 == 0) f1 = (invert ? -1 : 1) * tools::min_value() * 64; - return boost::math::make_tuple(f, f1, f2); + return BOOST_MATH_NAMESPACE::make_tuple(f, f1, f2); } private: T a, b, target; bool invert; }; +// +// Estimate x from the leading terms of the power series +// +// I_x(a, b) = x^a / (a B(a, b)) * (1 - a (b - 1) x / (a + 1) + ...) +// +// Returns true and sets *px only when x is small enough for the estimate +// to be good, which is the case far out in the lower tail. +// +template +BOOST_MATH_GPU_ENABLED bool ibeta_inv_small_x_estimate(T a, T b, T p, T* px, const Policy& pol) +{ + BOOST_MATH_STD_USING + + T bet = 0; +#ifndef BOOST_MATH_NO_EXCEPTIONS + try +#endif + { + bet = BOOST_MATH_NAMESPACE::beta(a, b, pol); + } +#ifndef BOOST_MATH_NO_EXCEPTIONS + catch (const std::overflow_error&) + { + return false; + } +#endif + if(!(bet > tools::min_value()) || !(BOOST_MATH_NAMESPACE::isfinite)(bet)) + return false; + // + // Work in logs: p * a * B(a, b) can underflow even though x does not. + // + T x = exp((log(p) + log(a) + log(bet)) / a); + // + // Successive terms of the series fall off like x when b is small and + // like (b - 1) x when b is large, so this bounds what has been dropped: + // + if(!(x * (1 + fabs(b - 1)) < T(0.1)) || !(x > tools::min_value())) + return false; + *px = x * (1 + (b - 1) * x / (a + 1)); + return true; +} + template BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* py) { @@ -562,7 +607,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* if(a > 1) { x = pow(p, 1 / a); - y = -boost::math::expm1(log(p) / a, pol); + y = -BOOST_MATH_NAMESPACE::expm1(log(p) / a, pol); } else { @@ -572,8 +617,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* } else { - x = exp(boost::math::log1p(-q, pol) / a); - y = -boost::math::expm1(boost::math::log1p(-q, pol) / a, pol); + x = exp(BOOST_MATH_NAMESPACE::log1p(-q, pol) / a); + y = -BOOST_MATH_NAMESPACE::expm1(BOOST_MATH_NAMESPACE::log1p(-q, pol) / a, pol); } if(invert) BOOST_MATH_GPU_SAFE_SWAP(x, y); @@ -597,7 +642,20 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* } T minv = BOOST_MATH_GPU_SAFE_MIN(a, b); T maxv = BOOST_MATH_GPU_SAFE_MAX(a, b); - if((sqrt(minv) > (maxv - minv)) && (minv > 5)) + if((p < T(1e-20)) && ibeta_inv_small_x_estimate(a, b, p, &x, pol)) + { + // + // Far out in the tail the asymptotic expansions below lose accuracy + // and can leave the iteration too far from the root to converge. + // Here x is small enough that the first two terms of the power + // series for the incomplete beta give a better starting point. + // The test on p is only there to keep the cost of the estimate + // (a call to beta) away from ordinary arguments: the expansions + // are still good many orders of magnitude below that threshold. + // + y = 1 - x; + } + else if((sqrt(minv) > (maxv - minv)) && (minv > 5)) { // // When a and b differ by a small amount @@ -628,7 +686,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* T ppa = pow(p, 1/a); if((ppa < 0.0025) && (a + b < 200)) { - x = ppa * pow(a * boost::math::beta(a, b, pol), 1/a); + x = ppa * pow(a * BOOST_MATH_NAMESPACE::beta(a, b, pol), 1/a); } else x = temme_method_2_ibeta_inverse(a, b, p, r, theta, pol); @@ -661,11 +719,11 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* try #endif { - bet = boost::math::beta(a, b, pol); + bet = BOOST_MATH_NAMESPACE::beta(a, b, pol); typedef typename Policy::overflow_error_type overflow_type; - BOOST_MATH_IF_CONSTEXPR(overflow_type::value != boost::math::policies::throw_on_error) + BOOST_MATH_IF_CONSTEXPR(overflow_type::value != BOOST_MATH_NAMESPACE::policies::throw_on_error) if(bet > tools::max_value()) bet = tools::max_value(); } @@ -688,7 +746,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* x = temme_method_3_ibeta_inverse(a, b, p, q, pol); y = 1 - x; } - else if ((y > 1e-5) && BOOST_MATH_GPU_SAFE_MIN(a, b) > 1000) + else if ((y > 1e-5) && BOOST_MATH_GPU_SAFE_MIN(a, b) >= 1000) { // All options have failed, use the saddle point as a starting location: x = BOOST_MATH_GPU_SAFE_MAX(a, b) / (a + b); @@ -708,7 +766,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* // Now we need to ensure that we start our iteration from the // right side of the inflection point: // - T fs = boost::math::ibeta(a, b, xs, pol) - p; + T fs = BOOST_MATH_NAMESPACE::ibeta(a, b, xs, pol) - p; if(fabs(fs) / p < tools::epsilon() * 3) { // The result is at the point of inflection, best just return it: @@ -740,7 +798,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* #ifndef BOOST_MATH_NO_EXCEPTIONS try { #endif - bet = boost::math::beta(a, b, pol); + bet = BOOST_MATH_NAMESPACE::beta(a, b, pol); #ifndef BOOST_MATH_NO_EXCEPTIONS } catch (const std::runtime_error&) @@ -748,9 +806,9 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* overflow = true; } #endif - if (overflow || !(boost::math::isfinite)(bet)) + if (overflow || !(BOOST_MATH_NAMESPACE::isfinite)(bet)) { - xg = exp((boost::math::lgamma(a + 1, pol) + boost::math::lgamma(b, pol) - boost::math::lgamma(a + b, pol) + log(p)) / a); + xg = exp((BOOST_MATH_NAMESPACE::lgamma(a + 1, pol) + BOOST_MATH_NAMESPACE::lgamma(b, pol) - BOOST_MATH_NAMESPACE::lgamma(a + b, pol) + log(p)) / a); if (xg > 2 / tools::epsilon()) xg = 2 / tools::epsilon(); } @@ -760,11 +818,13 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* y = 1 / (1 + xg); // // And finally we know that our result is below the inflection - // point, so set an upper limit on our search: + // point, so set an upper limit on our search. The root can be + // exactly at the inflection point (a == b and p == 1/2), and the + // root finder only creeps up on a bound, so leave it a little room: // if(x > xs) x = xs; - upper = xs; + upper = BOOST_MATH_GPU_SAFE_MIN(T(xs * 1.0001f), T(1)); } else if((a > 1) && (b > 1)) { @@ -777,7 +837,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* // T xs = (a - 1) / (a + b - 2); T xs2 = (b - 1) / (a + b - 2); - T ps = boost::math::ibeta(a, b, xs, pol) - p; + T ps = BOOST_MATH_NAMESPACE::ibeta(a, b, xs, pol) - p; if(ps < 0) { @@ -790,9 +850,9 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* // Estimate x and y, using expm1 to get a good estimate // for y when it's very small: // - T lx = log(p * a * boost::math::beta(a, b, pol)) / a; + T lx = log(p * a * BOOST_MATH_NAMESPACE::beta(a, b, pol)) / a; x = exp(lx); - y = x < 0.9 ? T(1 - x) : (T)(-boost::math::expm1(lx, pol)); + y = x < 0.9 ? T(1 - x) : (T)(-BOOST_MATH_NAMESPACE::expm1(lx, pol)); if((b < a) && (x < 0.2)) { @@ -816,11 +876,13 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* } // // And finally we know that our result is below the inflection - // point, so set an upper limit on our search: + // point, so set an upper limit on our search. The root can be + // exactly at the inflection point (a == b and p == 1/2), and the + // root finder only creeps up on a bound, so leave it a little room: // if(x > xs) x = xs; - upper = xs; + upper = BOOST_MATH_GPU_SAFE_MIN(T(xs * 1.0001f), T(1)); } else /*if((a <= 1) != (b <= 1))*/ { @@ -870,8 +932,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* try { #endif - x = pow(p * a * boost::math::beta(a, b, pol), 1 / a); - if ((x > 1) || !(boost::math::isfinite)(x)) + x = pow(p * a * BOOST_MATH_NAMESPACE::beta(a, b, pol), 1 / a); + if ((x > 1) || !(BOOST_MATH_NAMESPACE::isfinite)(x)) x = 1; #ifndef BOOST_MATH_NO_EXCEPTIONS } @@ -881,7 +943,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* } #endif if(x == 0) - x = boost::math::tools::min_value(); + x = BOOST_MATH_NAMESPACE::tools::min_value(); y = 1 - x; } else /*if(pow(q, 1/b) < 0.1)*/ @@ -891,8 +953,8 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* try { #endif - y = pow(1 - pow(p, b * boost::math::beta(a, b, pol)), 1/b); - if ((y > 1) || !(boost::math::isfinite)(y)) + y = pow(1 - pow(p, b * BOOST_MATH_NAMESPACE::beta(a, b, pol)), 1/b); + if ((y > 1) || !(BOOST_MATH_NAMESPACE::isfinite)(y)) y = 1; #ifndef BOOST_MATH_NO_EXCEPTIONS } @@ -902,7 +964,7 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* } #endif if(y == 0) - y = boost::math::tools::min_value(); + y = BOOST_MATH_NAMESPACE::tools::min_value(); x = 1 - y; } } @@ -936,21 +998,21 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* // // We're not interested in answers smaller than machine epsilon: // - lower = boost::math::tools::epsilon(); + lower = BOOST_MATH_NAMESPACE::tools::epsilon(); if(x < lower) x = lower; } else - lower = boost::math::tools::min_value(); + lower = BOOST_MATH_NAMESPACE::tools::min_value(); if(x < lower) x = lower; } - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); - boost::math::uintmax_t max_iter_used = 0; + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter_used = 0; // // Figure out how many digits to iterate towards: // - int digits = boost::math::policies::digits() / 2; + int digits = BOOST_MATH_NAMESPACE::policies::digits() / 2; if((x < 1e-50) && ((a < 1) || (b < 1))) { // @@ -972,11 +1034,11 @@ BOOST_MATH_GPU_ENABLED T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* // Since we can't use halley_iterate on device we use newton raphson // #ifndef BOOST_MATH_HAS_GPU_SUPPORT - x = boost::math::tools::halley_iterate( + x = BOOST_MATH_NAMESPACE::tools::halley_iterate( #else - x = boost::math::tools::newton_raphson_iterate( + x = BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate( #endif - boost::math::detail::ibeta_roots(a, b, (p < q ? p : q), (p < q ? false : true)), x, lower, upper, digits, max_iter); + BOOST_MATH_NAMESPACE::detail::ibeta_roots(a, b, (p < q ? p : q), (p < q ? false : true)), x, lower, upper, digits, max_iter); policies::check_root_iterations("boost::math::ibeta<%1%>(%1%, %1%, %1%)", max_iter + max_iter_used, pol); // // We don't really want these asserts here, but they are useful for sanity @@ -1112,8 +1174,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return ibetac_inv(a, b, q, static_cast(nullptr), pol); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP diff --git a/include/boost/math/special_functions/detail/iconv.hpp b/include/boost/math/special_functions/detail/iconv.hpp index 20889d411e..b2814b2011 100644 --- a/include/boost/math/special_functions/detail/iconv.hpp +++ b/include/boost/math/special_functions/detail/iconv.hpp @@ -14,16 +14,16 @@ #include #include -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template -BOOST_MATH_GPU_ENABLED inline int iconv_imp(T v, Policy const&, boost::math::true_type const&) +BOOST_MATH_GPU_ENABLED inline int iconv_imp(T v, Policy const&, BOOST_MATH_NAMESPACE::true_type const&) { return static_cast(v); } template -BOOST_MATH_GPU_ENABLED inline int iconv_imp(T v, Policy const& pol, boost::math::false_type const&) +BOOST_MATH_GPU_ENABLED inline int iconv_imp(T v, Policy const& pol, BOOST_MATH_NAMESPACE::false_type const&) { BOOST_MATH_STD_USING return iround(v, pol); @@ -32,12 +32,12 @@ BOOST_MATH_GPU_ENABLED inline int iconv_imp(T v, Policy const& pol, boost::math: template BOOST_MATH_GPU_ENABLED inline int iconv(T v, Policy const& pol) { - typedef typename boost::math::is_convertible::type tag_type; + typedef typename BOOST_MATH_NAMESPACE::is_convertible::type tag_type; return iconv_imp(v, pol, tag_type()); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ICONV_HPP diff --git a/include/boost/math/special_functions/detail/igamma_inverse.hpp b/include/boost/math/special_functions/detail/igamma_inverse.hpp index 4efd4f78a3..63e93c8373 100644 --- a/include/boost/math/special_functions/detail/igamma_inverse.hpp +++ b/include/boost/math/special_functions/detail/igamma_inverse.hpp @@ -19,7 +19,7 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -91,7 +91,7 @@ BOOST_MATH_GPU_ENABLED inline T didonato_FN(T p, T a, T x, unsigned N, T toleran // See equation 34. // BOOST_MATH_STD_USING - T u = log(p) + boost::math::lgamma(a + 1, pol); + T u = log(p) + BOOST_MATH_NAMESPACE::lgamma(a + 1, pol); return exp((u + x - log(didonato_SN(a, x, N, tolerance))) / a); } @@ -119,7 +119,7 @@ BOOST_MATH_GPU_ENABLED T find_inverse_gamma(T a, T p, T q, const Policy& pol, bo } else if(a < 1) { - T g = boost::math::tgamma(a, pol); + T g = BOOST_MATH_NAMESPACE::tgamma(a, pol); T b = q * g; BOOST_MATH_INSTRUMENT_VARIABLE(g); BOOST_MATH_INSTRUMENT_VARIABLE(b); @@ -237,7 +237,7 @@ BOOST_MATH_GPU_ENABLED T find_inverse_gamma(T a, T p, T q, const Policy& pol, bo else { T D = BOOST_MATH_GPU_SAFE_MAX(T(2), T(a * (a - 1))); - T lg = boost::math::lgamma(a, pol); + T lg = BOOST_MATH_NAMESPACE::lgamma(a, pol); T lb = log(q) + lg; if(lb < -D * T(2.3)) { @@ -282,13 +282,13 @@ BOOST_MATH_GPU_ENABLED T find_inverse_gamma(T a, T p, T q, const Policy& pol, bo if(w < 0.15f * ap1) { // DiDonato and Morris Eq 35: - T v = log(p) + boost::math::lgamma(ap1, pol); + T v = log(p) + BOOST_MATH_NAMESPACE::lgamma(ap1, pol); z = exp((v + w) / a); - s = boost::math::log1p(z / ap1 * (1 + z / ap2), pol); + s = BOOST_MATH_NAMESPACE::log1p(z / ap1 * (1 + z / ap2), pol); z = exp((v + z - s) / a); - s = boost::math::log1p(z / ap1 * (1 + z / ap2), pol); + s = BOOST_MATH_NAMESPACE::log1p(z / ap1 * (1 + z / ap2), pol); z = exp((v + z - s) / a); - s = boost::math::log1p(z / ap1 * (1 + z / ap2 * (1 + z / (a + 3))), pol); + s = BOOST_MATH_NAMESPACE::log1p(z / ap1 * (1 + z / ap2 * (1 + z / (a + 3))), pol); z = exp((v + z - s) / a); BOOST_MATH_INSTRUMENT_VARIABLE(z); } @@ -304,7 +304,7 @@ BOOST_MATH_GPU_ENABLED T find_inverse_gamma(T a, T p, T q, const Policy& pol, bo { // DiDonato and Morris Eq 36: T ls = log(didonato_SN(a, z, 100, T(1e-4))); - T v = log(p) + boost::math::lgamma(ap1, pol); + T v = log(p) + BOOST_MATH_NAMESPACE::lgamma(ap1, pol); z = exp((v + z - ls) / a); result = z * (1 - (a * log(z) - z - v + ls) / (a - z)); @@ -336,7 +336,7 @@ struct gamma_p_inverse_func } } - BOOST_MATH_GPU_ENABLED boost::math::tuple operator()(const T& x)const + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::tuple operator()(const T& x)const { BOOST_FPU_EXCEPTION_GUARD // @@ -356,7 +356,7 @@ struct gamma_p_inverse_func T f, f1; value_type ft; - f = static_cast(boost::math::detail::gamma_incomplete_imp( + f = static_cast(BOOST_MATH_NAMESPACE::detail::gamma_incomplete_imp( static_cast(a), static_cast(x), true, invert, @@ -390,7 +390,7 @@ struct gamma_p_inverse_func f2 = -f2; } - return boost::math::make_tuple(static_cast(f - p), f1, f2); + return BOOST_MATH_NAMESPACE::make_tuple(static_cast(f - p), f1, f2); } private: T a, p; @@ -422,6 +422,14 @@ BOOST_MATH_GPU_ENABLED T gamma_p_inv_imp(T a, T p, const Policy& pol) T lower = tools::min_value(); if(guess <= lower) guess = tools::min_value(); + // + // If the result is smaller than the smallest normal number, then the + // root finder has no root to converge on inside [lower, max], so check + // for underflow up front. Only a tiny guess can be this far out, so + // the extra evaluation is rarely paid for: + // + if((guess < sqrt(lower)) && (BOOST_MATH_NAMESPACE::gamma_p(a, lower, pol) >= p)) + return policies::raise_underflow_error(function, "Expected result known to be non-zero, but is smaller than the smallest available number.", pol); BOOST_MATH_INSTRUMENT_VARIABLE(guess); // // Work out how many digits to converge to, normally this is @@ -445,7 +453,7 @@ BOOST_MATH_GPU_ENABLED T gamma_p_inv_imp(T a, T p, const Policy& pol) // // Go ahead and iterate: // - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); #ifndef BOOST_MATH_HAS_GPU_SUPPORT guess = tools::halley_iterate( @@ -495,6 +503,13 @@ BOOST_MATH_GPU_ENABLED T gamma_q_inv_imp(T a, T q, const Policy& pol) if(guess <= lower) guess = tools::min_value(); // + // If the result is smaller than the smallest normal number, then the + // root finder has no root to converge on inside [lower, max], so check + // for underflow up front (see gamma_p_inv_imp): + // + if((guess < sqrt(lower)) && (BOOST_MATH_NAMESPACE::gamma_q(a, lower, pol) <= q)) + return policies::raise_underflow_error(function, "Expected result known to be non-zero, but is smaller than the smallest available number.", pol); + // // Work out how many digits to converge to, normally this is // 2/3 of the digits in T, but if the first derivative is very // large convergence is slow, so we'll bump it up to full @@ -516,7 +531,7 @@ BOOST_MATH_GPU_ENABLED T gamma_q_inv_imp(T a, T q, const Policy& pol) // // Go ahead and iterate: // - boost::math::uintmax_t max_iter = policies::get_max_root_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_root_iterations(); #ifndef BOOST_MATH_HAS_GPU_SUPPORT guess = tools::halley_iterate( @@ -578,8 +593,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return gamma_q_inv(a, p, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP diff --git a/include/boost/math/special_functions/detail/igamma_large.hpp b/include/boost/math/special_functions/detail/igamma_large.hpp index e585748183..792c4169a7 100644 --- a/include/boost/math/special_functions/detail/igamma_large.hpp +++ b/include/boost/math/special_functions/detail/igamma_large.hpp @@ -63,13 +63,13 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // This version will never be called (at runtime), it's a stub used // when T is unsuitable to be passed to these routines: // template -BOOST_MATH_GPU_ENABLED inline T igamma_temme_large(T, T, const Policy& /* pol */, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline T igamma_temme_large(T, T, const Policy& /* pol */, const BOOST_MATH_NAMESPACE::integral_constant&) { // stub function, should never actually be called BOOST_MATH_ASSERT(0); @@ -83,11 +83,11 @@ BOOST_MATH_GPU_ENABLED inline T igamma_temme_large(T, T, const Policy& /* pol */ #ifndef BOOST_MATH_HAS_GPU_SUPPORT template -BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING // ADL of std functions T sigma = (x - a) / a; - T phi = -boost::math::log1pmx(sigma, pol); + T phi = -BOOST_MATH_NAMESPACE::log1pmx(sigma, pol); T y = a * phi; T z = sqrt(2 * phi); if(x < a) @@ -282,7 +282,7 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b if(x < a) result = -result; - result += boost::math::erfc(sqrt(y), pol) / 2; + result += BOOST_MATH_NAMESPACE::erfc(sqrt(y), pol) / 2; return result; } @@ -294,11 +294,11 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b // (IEEE double precision or 10^-17). // template -BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING // ADL of std functions T sigma = (x - a) / a; - T phi = -boost::math::log1pmx(sigma, pol); + T phi = -BOOST_MATH_NAMESPACE::log1pmx(sigma, pol); T y = a * phi; T z = sqrt(2 * phi); if(x < a) @@ -430,7 +430,7 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b result = -result; #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { result += ::erfcf(::sqrtf(y)) / 2; } @@ -439,7 +439,7 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b result += ::erfc(::sqrt(y)) / 2; } #else - result += boost::math::erfc(sqrt(y), pol) / 2; + result += BOOST_MATH_NAMESPACE::erfc(sqrt(y), pol) / 2; #endif return result; @@ -449,11 +449,11 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b // (IEEE float precision, or 10^-8) // template -BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING // ADL of std functions T sigma = (x - a) / a; - T phi = -boost::math::log1pmx(sigma, pol); + T phi = -BOOST_MATH_NAMESPACE::log1pmx(sigma, pol); T y = a * phi; T z = sqrt(2 * phi); if(x < a) @@ -496,7 +496,7 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b result = -result; #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { result += ::erfcf(::sqrtf(y)) / 2; } @@ -505,7 +505,7 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b result += ::erfc(::sqrt(y)) / 2; } #else - result += boost::math::erfc(sqrt(y), pol) / 2; + result += BOOST_MATH_NAMESPACE::erfc(sqrt(y), pol) / 2; #endif return result; @@ -521,11 +521,11 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b #ifndef BOOST_MATH_HAS_GPU_SUPPORT template -BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING // ADL of std functions T sigma = (x - a) / a; - T phi = -boost::math::log1pmx(sigma, pol); + T phi = -BOOST_MATH_NAMESPACE::log1pmx(sigma, pol); T y = a * phi; T z = sqrt(2 * phi); if(x < a) @@ -806,7 +806,7 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b if(x < a) result = -result; - result += boost::math::erfc(sqrt(y), pol) / 2; + result += BOOST_MATH_NAMESPACE::erfc(sqrt(y), pol) / 2; return result; } @@ -815,8 +815,7 @@ BOOST_MATH_GPU_ENABLED T igamma_temme_large(T a, T x, const Policy& pol, const b #endif } // namespace detail -} // namespace math -} // namespace math +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_DETAIL_IGAMMA_LARGE diff --git a/include/boost/math/special_functions/detail/lambert_w_lookup_table.ipp b/include/boost/math/special_functions/detail/lambert_w_lookup_table.ipp index 9f1b488ead..8437b37560 100644 --- a/include/boost/math/special_functions/detail/lambert_w_lookup_table.ipp +++ b/include/boost/math/special_functions/detail/lambert_w_lookup_table.ipp @@ -16,26 +16,25 @@ // Sizes of arrays of z values for Lambert W[0], W[1] ... W[64]" and W[-1], W[-2] ... W[-64]. -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace lambert_w_detail { namespace lambert_w_lookup { -static constexpr std::size_t noof_sqrts = 12; -static constexpr std::size_t noof_halves = 12; -static constexpr std::size_t noof_w0es = 65; -static constexpr std::size_t noof_w0zs = 65; -static constexpr std::size_t noof_wm1es = 64; -static constexpr std::size_t noof_wm1zs = 64; +BOOST_MATH_INLINE_CONSTEXPR std::size_t noof_sqrts = 12; +BOOST_MATH_INLINE_CONSTEXPR std::size_t noof_halves = 12; +BOOST_MATH_INLINE_CONSTEXPR std::size_t noof_w0es = 65; +BOOST_MATH_INLINE_CONSTEXPR std::size_t noof_w0zs = 65; +BOOST_MATH_INLINE_CONSTEXPR std::size_t noof_wm1es = 64; +BOOST_MATH_INLINE_CONSTEXPR std::size_t noof_wm1zs = 64; -static constexpr lookup_t halves[noof_halves] = +BOOST_MATH_INLINE_CONSTEXPR lookup_t halves[noof_halves] = { // Common to Lambert W0 and W-1 (and exactly representable). static_cast(0.5L), static_cast(0.25L), static_cast(0.125L), static_cast(0.0625L), static_cast(0.03125L), static_cast(0.015625L), static_cast(0.0078125L), static_cast(0.00390625L), static_cast(0.001953125L), static_cast(0.0009765625L), static_cast(0.00048828125L), static_cast(0.000244140625L) }; // halves, 0.5, 0.25, ... 0.000244140625, common to W0 and W-1. -static constexpr lookup_t sqrtw0s[noof_sqrts] = +BOOST_MATH_INLINE_CONSTEXPR lookup_t sqrtw0s[noof_sqrts] = { // For Lambert W0 only. static_cast(0.6065306597126334242631173765403218567L), static_cast(0.7788007830714048686684607000907199500L), static_cast(0.8824969025845954031047175929687018290L), static_cast(0.9394130628134757862473572557999761753L), @@ -45,7 +44,7 @@ static constexpr lookup_t sqrtw0s[noof_sqrts] = static_cast(0.9995118379398893653889967919448497792L), static_cast(0.9997558891748972165136242351259789505L) }; // sqrtw0s -static constexpr lookup_t sqrtwm1s[noof_sqrts] = +BOOST_MATH_INLINE_CONSTEXPR lookup_t sqrtwm1s[noof_sqrts] = { // For Lambert W-1 only. static_cast(1.648721270700128146848650787814163572L), static_cast(1.284025416687741484073420568062436458L), static_cast(1.133148453066826316829007227811793873L), static_cast(1.064494458917859429563390594642889673L), @@ -55,7 +54,7 @@ static constexpr lookup_t sqrtwm1s[noof_sqrts] = static_cast(1.000488400478694473126173623807163354L), static_cast(1.000244170429747854937005233924135774L) }; // sqrtwm1s -static constexpr lookup_t w0es[noof_w0zs] = +BOOST_MATH_INLINE_CONSTEXPR lookup_t w0es[noof_w0zs] = { // Fukushima e powers array e[0] = 2.718, 1., e[2] = e^-1 = 0.135, e[3] = e^-2 = 0.133 ... e[64] = 4.3596100000630809736231248158884615452e-28. static_cast(2.7182818284590452353602874713526624978e+00L), static_cast(1.0000000000000000000000000000000000000e+00L), static_cast(3.6787944117144232159552377016146086745e-01L), @@ -93,7 +92,7 @@ static constexpr lookup_t w0es[noof_w0zs] = }; // w0es -static constexpr lookup_t w0zs[noof_w0zs] = +BOOST_MATH_INLINE_CONSTEXPR lookup_t w0zs[noof_w0zs] = { // z values for W[0], W[1], W[2] ... W[64] (Fukushima array Fk). static_cast(0.0000000000000000000000000000000000000e+00L), static_cast(2.7182818284590452353602874713526624978e+00L), static_cast(1.4778112197861300454460854921150015626e+01L), static_cast(6.0256610769563003222785588963745153691e+01L), static_cast(2.1839260013257695631244104481144351361e+02L), @@ -115,7 +114,7 @@ static constexpr lookup_t w0zs[noof_w0zs] = }; // w0zs -static constexpr lookup_t wm1es[noof_wm1es] = +BOOST_MATH_INLINE_CONSTEXPR lookup_t wm1es[noof_wm1es] = { // Fukushima e array e[0] = e^1 = 2.718, e[1] = e^2 = 7.39 ... e[64] = 4.60718e+28. static_cast(2.7182818284590452353602874713526624978e+00L), static_cast(7.3890560989306502272304274605750078132e+00L), static_cast(2.0085536923187667740928529654581717897e+01L), static_cast(5.4598150033144239078110261202860878403e+01L), static_cast(1.4841315910257660342111558004055227962e+02L), @@ -136,7 +135,7 @@ static constexpr lookup_t wm1es[noof_wm1es] = static_cast(8.4383566687414544890733294803731179601e+26L), static_cast(2.2937831594696098790993528402686136005e+27L), static_cast(6.2351490808116168829092387089284697448e+27L) }; // wm1es -static constexpr lookup_t wm1zs[noof_wm1zs] = +BOOST_MATH_INLINE_CONSTEXPR lookup_t wm1zs[noof_wm1zs] = { // Fukushima G array of z values for integral K, (Fukushima Gk) g[0] (k = -1) = 1 ... g[64] = -1.0264389699511303e-26. static_cast(-3.6787944117144232159552377016146086745e-01L), static_cast(-2.7067056647322538378799898994496880682e-01L), static_cast(-1.4936120510359182893802724695018532990e-01L), static_cast(-7.3262555554936721174872085092964968848e-02L), static_cast(-3.3689734995427335483180242115742121244e-02L), @@ -158,5 +157,4 @@ static constexpr lookup_t wm1zs[noof_wm1zs] = }; // wm1zs } // namespace lambert_w_lookup } // namespace detail -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END diff --git a/include/boost/math/special_functions/detail/lanczos_sse2.hpp b/include/boost/math/special_functions/detail/lanczos_sse2.hpp index 43353ce2b5..89e8be439d 100644 --- a/include/boost/math/special_functions/detail/lanczos_sse2.hpp +++ b/include/boost/math/special_functions/detail/lanczos_sse2.hpp @@ -18,7 +18,7 @@ #define ALIGN16 __declspec(align(16)) #endif -namespace boost{ namespace math{ namespace lanczos{ +BOOST_MATH_NAMESPACE_BEGIN namespace lanczos{ template <> inline double lanczos13m53::lanczos_sum(const double& x) @@ -225,8 +225,7 @@ inline long double lanczos13m53::lanczos_sum_expG_scaled(const long #endif } // namespace lanczos -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #undef ALIGN16 diff --git a/include/boost/math/special_functions/detail/lgamma_small.hpp b/include/boost/math/special_functions/detail/lgamma_small.hpp index 706d200db8..aa758dbf5d 100644 --- a/include/boost/math/special_functions/detail/lgamma_small.hpp +++ b/include/boost/math/special_functions/detail/lgamma_small.hpp @@ -27,7 +27,7 @@ #pragma GCC system_header #endif -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // // These need forward declaring to keep GCC happy: @@ -41,7 +41,7 @@ BOOST_MATH_GPU_ENABLED T gamma_imp(T z, const Policy& pol, const lanczos::undefi // lgamma for small arguments: // template -BOOST_MATH_GPU_ENABLED T lgamma_small_imp(T z, T zm1, T zm2, const boost::math::integral_constant&, const Policy& /* l */, const Lanczos&) +BOOST_MATH_GPU_ENABLED T lgamma_small_imp(T z, T zm1, T zm2, const BOOST_MATH_NAMESPACE::integral_constant&, const Policy& /* l */, const Lanczos&) { // This version uses rational approximations for small // values of z accurate enough for 64-bit mantissas @@ -249,7 +249,7 @@ BOOST_MATH_GPU_ENABLED T lgamma_small_imp(T z, T zm1, T zm2, const boost::math:: // LCOV_EXCL_START // template -T lgamma_small_imp(T z, T zm1, T zm2, const boost::math::integral_constant&, const Policy& /* l */, const Lanczos&) +T lgamma_small_imp(T z, T zm1, T zm2, const BOOST_MATH_NAMESPACE::integral_constant&, const Policy& /* l */, const Lanczos&) { // // This version uses rational approximations for small @@ -512,7 +512,7 @@ T lgamma_small_imp(T z, T zm1, T zm2, const boost::math::integral_constant -BOOST_MATH_GPU_ENABLED T lgamma_small_imp(T z, T zm1, T zm2, const boost::math::integral_constant&, const Policy& pol, const Lanczos& l) +BOOST_MATH_GPU_ENABLED T lgamma_small_imp(T z, T zm1, T zm2, const BOOST_MATH_NAMESPACE::integral_constant&, const Policy& pol, const Lanczos& l) { // // No rational approximations are available because either @@ -546,24 +546,24 @@ BOOST_MATH_GPU_ENABLED T lgamma_small_imp(T z, T zm1, T zm2, const boost::math:: { // special case near 2: T dz = zm2; - result = dz * log((z + lanczos_g_near_1_and_2(l) - T(0.5)) / boost::math::constants::e()); - result += boost::math::log1p(dz / (lanczos_g_near_1_and_2(l) + T(1.5)), pol) * T(1.5); - result += boost::math::log1p(Lanczos::lanczos_sum_near_2(dz), pol); + result = dz * log((z + lanczos_g_near_1_and_2(l) - T(0.5)) / BOOST_MATH_NAMESPACE::constants::e()); + result += BOOST_MATH_NAMESPACE::log1p(dz / (lanczos_g_near_1_and_2(l) + T(1.5)), pol) * T(1.5); + result += BOOST_MATH_NAMESPACE::log1p(Lanczos::lanczos_sum_near_2(dz), pol); } else { // special case near 1: T dz = zm1; - result = dz * log((z + lanczos_g_near_1_and_2(l) - T(0.5)) / boost::math::constants::e()); - result += boost::math::log1p(dz / (lanczos_g_near_1_and_2(l) + T(0.5)), pol) / 2; - result += boost::math::log1p(Lanczos::lanczos_sum_near_1(dz), pol); + result = dz * log((z + lanczos_g_near_1_and_2(l) - T(0.5)) / BOOST_MATH_NAMESPACE::constants::e()); + result += BOOST_MATH_NAMESPACE::log1p(dz / (lanczos_g_near_1_and_2(l) + T(0.5)), pol) / 2; + result += BOOST_MATH_NAMESPACE::log1p(Lanczos::lanczos_sum_near_1(dz), pol); } return result; } #endif // BOOST_MATH_HAS_GPU_SUPPORT -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_FUNCTIONS_DETAIL_LGAMMA_SMALL diff --git a/include/boost/math/special_functions/detail/polygamma.hpp b/include/boost/math/special_functions/detail/polygamma.hpp index a608f22c7f..6cd40dd165 100644 --- a/include/boost/math/special_functions/detail/polygamma.hpp +++ b/include/boost/math/special_functions/detail/polygamma.hpp @@ -11,9 +11,11 @@ #ifndef _BOOST_POLYGAMMA_DETAIL_2013_07_30_HPP_ #define _BOOST_POLYGAMMA_DETAIL_2013_07_30_HPP_ +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include @@ -26,8 +28,10 @@ #include #ifdef BOOST_MATH_HAS_THREADS +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif #ifdef _MSC_VER #pragma once @@ -35,7 +39,7 @@ #pragma warning(disable:4702) // Unreachable code (release mode only warning) #endif -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template T polygamma_atinfinityplus(const int n, const T& x, const Policy& pol, const char* function) // for large values of x such as for x> 400 @@ -47,15 +51,35 @@ namespace boost { namespace math { namespace detail{ // term == value of current term to be added to sum. // part_term == value of current term excluding the Bernoulli number part // + // + // (n-1)! / x^(n+1) can be a normal number while x^(n+1) overflows or x^-(n+1) underflows, so + // compute it as mantissa * 2^exponent from the mantissas and exponents of (n-1)! and x. + // Taking logs instead loses log(result) eps of relative accuracy. + // + const bool use_factorial = (n <= (int)BOOST_MATH_NAMESPACE::max_factorial::value) + || (BOOST_MATH_NAMESPACE::lgamma(T(n), pol) < tools::log_max_value()); + int x_exponent = 0; + T x_mantissa = frexp(x, &x_exponent); + int factorial_exponent = 0; + T factorial_mantissa = 0; + long long exponent = 0; + T mantissa = 0; + // Exponents are summed as long long, then clamped so that ldexp gets an int: + auto clamped = [](long long e) { return static_cast((std::max)((std::min)(e, static_cast((std::numeric_limits::max)() / 2)), static_cast((std::numeric_limits::min)() / 2))); }; + if(use_factorial) + { + factorial_mantissa = frexp(BOOST_MATH_NAMESPACE::factorial(n - 1, pol), &factorial_exponent); + mantissa = factorial_mantissa * static_cast(pow(x_mantissa, T(-n - 1))); + exponent = factorial_exponent - static_cast(n + 1) * x_exponent; + } if(n + x == x) { - // x is crazy large, just concentrate on the first part of the expression and use logs: + // x is crazy large, just concentrate on the first part of the expression: if(n == 1) return 1 / x; - T nlx = n * log(x); - if((nlx < tools::log_max_value()) && (n < (int)max_factorial::value)) - return ((n & 1) ? 1 : -1) * boost::math::factorial(n - 1, pol) * static_cast(pow(x, T(-n))); + if(use_factorial) + return ((n & 1) ? 1 : -1) * ldexp(factorial_mantissa * static_cast(pow(x_mantissa, T(-n))), clamped(factorial_exponent - static_cast(n) * x_exponent)); else - return ((n & 1) ? 1 : -1) * exp(boost::math::lgamma(T(n), pol) - n * log(x)); + return ((n & 1) ? 1 : -1) * exp(BOOST_MATH_NAMESPACE::lgamma(T(n), pol) - n * log(x)); } T term, sum, part_term; T x_squared = x * x; @@ -75,26 +99,22 @@ namespace boost { namespace math { namespace detail{ // // part_term n * (n + 1) / (2x) // - // If either the factorial would overflow, - // or the power term underflows, this just gets set to 0 and then we - // know that we have to use logs for the initial terms: + // If the factorial would overflow, we have to use logs for the initial terms; + // otherwise use the scaled (n-1)! / x^(n+1) from above: // - part_term = ((n > (int)boost::math::max_factorial::value) && (T(n) * n > tools::log_max_value())) - ? T(0) : static_cast(boost::math::factorial(n - 1, pol) * pow(x, T(-n - 1))); - if(part_term == 0) + if(!use_factorial) { - // Either n is very large, or the power term underflows, - // set the initial values of part_term, term and sum via logs: - part_term = static_cast(T(boost::math::lgamma(n, pol)) - (n + 1) * log(x)); - sum = exp(part_term + log(n + 2 * x) - boost::math::constants::ln_two()); - part_term += log(T(n) * (n + 1)) - boost::math::constants::ln_two() - log(x); + part_term = static_cast(T(BOOST_MATH_NAMESPACE::lgamma(n, pol)) - (n + 1) * log(x)); + sum = exp(part_term + log(n + 2 * x) - BOOST_MATH_NAMESPACE::constants::ln_two()); + part_term += log(T(n) * (n + 1)) - BOOST_MATH_NAMESPACE::constants::ln_two() - log(x); part_term = exp(part_term); } else { - sum = part_term * (n + 2 * x) / 2; - part_term *= (T(n) * (n + 1)) / 2; - part_term /= x; + // (n + 2x) / 2 * (n-1)! / x^(n+1), with n + 2x scaled by 2^-x_exponent: + sum = ldexp(mantissa * ldexp(n + 2 * x, -x_exponent) / 2, clamped(exponent + x_exponent)); + // n (n + 1) / 2x * (n-1)! / x^(n+1): + part_term = ldexp(mantissa * (T(n) * (n + 1) / 2) / x_mantissa, clamped(exponent - x_exponent)); } // // If the leading term is 0, so is the result: @@ -104,7 +124,7 @@ namespace boost { namespace math { namespace detail{ for(unsigned k = 1;;) { - term = part_term * boost::math::bernoulli_b2n(k, pol); + term = part_term * BOOST_MATH_NAMESPACE::bernoulli_b2n(k, pol); sum += term; // // Normal termination condition: @@ -163,13 +183,13 @@ namespace boost { namespace math { namespace detail{ sum0 += z_plus_k_pow_minus_m_minus_one; z += 1; } - sum0 *= boost::math::factorial(n, pol); + sum0 *= BOOST_MATH_NAMESPACE::factorial(n, pol); } else { for(int k = 1; k <= iter; ++k) { - T log_term = log(z) * minus_m_minus_one + boost::math::lgamma(T(n + 1), pol); + T log_term = log(z) * minus_m_minus_one + BOOST_MATH_NAMESPACE::lgamma(T(n + 1), pol); sum0 += exp(log_term); z += 1; } @@ -192,7 +212,7 @@ namespace boost { namespace math { namespace detail{ // // In order to avoid spurious overflow, save the n! term for later, and rescale at the end: // - T scale = boost::math::factorial(n, pol); + T scale = BOOST_MATH_NAMESPACE::factorial(n, pol); // // "factorial_part" contains everything except the zeta function // evaluations in each term: @@ -205,7 +225,7 @@ namespace boost { namespace math { namespace detail{ // T prefix = static_cast(pow(x, T(n + 1))); // Warning supression: Integer power returns at least a double if(prefix == 0) - return boost::math::policies::raise_overflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); prefix = 1 / prefix; // // First term in the series is necessarily < zeta(2) < 2, so @@ -225,10 +245,10 @@ namespace boost { namespace math { namespace detail{ for(unsigned k = 0;;) { // Get the k'th term: - T term = factorial_part * boost::math::zeta(T(k + n + 1), pol); + T term = factorial_part * BOOST_MATH_NAMESPACE::zeta(T(k + n + 1), pol); sum += term; // Termination condition: - if(fabs(term) < fabs(sum * boost::math::policies::get_epsilon())) + if(fabs(term) < fabs(sum * BOOST_MATH_NAMESPACE::policies::get_epsilon())) break; // // Move on k and factorial_part: @@ -244,8 +264,8 @@ namespace boost { namespace math { namespace detail{ // // We need to multiply by the scale, at each stage checking for overflow: // - if(boost::math::tools::max_value() / scale < sum) - return boost::math::policies::raise_overflow_error(function, nullptr, pol); + if(BOOST_MATH_NAMESPACE::tools::max_value() / scale < sum) + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); sum *= scale; return n & 1 ? sum : T(-sum); } @@ -293,106 +313,106 @@ namespace boost { namespace math { namespace detail{ // subscripting the tables in the calculation, but halves the storage space // (and complexity for that matter). // - T s = fabs(x) < fabs(xc) ? boost::math::sin_pi(x, pol) : boost::math::sin_pi(xc, pol); - T c = boost::math::cos_pi(x, pol); + T s = fabs(x) < fabs(xc) ? BOOST_MATH_NAMESPACE::sin_pi(x, pol) : BOOST_MATH_NAMESPACE::sin_pi(xc, pol); + T c = BOOST_MATH_NAMESPACE::cos_pi(x, pol); switch(n) { case 1: return -constants::pi() / (s * s); case 2: { - return 2 * constants::pi() * constants::pi() * c / boost::math::pow<3>(s, pol); + return 2 * constants::pi() * constants::pi() * c / BOOST_MATH_NAMESPACE::pow<3>(s, pol); } case 3: { constexpr int P[] = { -2, -4 }; - return boost::math::pow<3>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<4>(s, pol); + return BOOST_MATH_NAMESPACE::pow<3>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<4>(s, pol); } case 4: { constexpr int P[] = { 16, 8 }; - return boost::math::pow<4>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<5>(s, pol); + return BOOST_MATH_NAMESPACE::pow<4>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<5>(s, pol); } case 5: { constexpr int P[] = { -16, -88, -16 }; - return boost::math::pow<5>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<6>(s, pol); + return BOOST_MATH_NAMESPACE::pow<5>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<6>(s, pol); } case 6: { constexpr int P[] = { 272, 416, 32 }; - return boost::math::pow<6>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<7>(s, pol); + return BOOST_MATH_NAMESPACE::pow<6>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<7>(s, pol); } case 7: { constexpr int P[] = { -272, -2880, -1824, -64 }; - return boost::math::pow<7>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<8>(s, pol); + return BOOST_MATH_NAMESPACE::pow<7>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<8>(s, pol); } case 8: { constexpr int P[] = { 7936, 24576, 7680, 128 }; - return boost::math::pow<8>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<9>(s, pol); + return BOOST_MATH_NAMESPACE::pow<8>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<9>(s, pol); } case 9: { constexpr int P[] = { -7936, -137216, -185856, -31616, -256 }; - return boost::math::pow<9>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<10>(s, pol); + return BOOST_MATH_NAMESPACE::pow<9>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<10>(s, pol); } case 10: { constexpr int P[] = { 353792, 1841152, 1304832, 128512, 512 }; - return boost::math::pow<10>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<11>(s, pol); + return BOOST_MATH_NAMESPACE::pow<10>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<11>(s, pol); } case 11: { constexpr int P[] = { -353792, -9061376, -21253376, -8728576, -518656, -1024}; - return boost::math::pow<11>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<12>(s, pol); + return BOOST_MATH_NAMESPACE::pow<11>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<12>(s, pol); } case 12: { constexpr int P[] = { 22368256, 175627264, 222398464, 56520704, 2084864, 2048 }; - return boost::math::pow<12>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<13>(s, pol); + return BOOST_MATH_NAMESPACE::pow<12>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<13>(s, pol); } #ifndef BOOST_NO_LONG_LONG case 13: { constexpr long long P[] = { -22368256LL, -795300864LL, -2868264960LL, -2174832640LL, -357888000LL, -8361984LL, -4096 }; - return boost::math::pow<13>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<14>(s, pol); + return BOOST_MATH_NAMESPACE::pow<13>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<14>(s, pol); } case 14: { constexpr long long P[] = { 1903757312LL, 21016670208LL, 41731645440LL, 20261765120LL, 2230947840LL, 33497088LL, 8192 }; - return boost::math::pow<14>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<15>(s, pol); + return BOOST_MATH_NAMESPACE::pow<14>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<15>(s, pol); } case 15: { constexpr long long P[] = { -1903757312LL, -89702612992LL, -460858269696LL, -559148810240LL, -182172651520LL, -13754155008LL, -134094848LL, -16384 }; - return boost::math::pow<15>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<16>(s, pol); + return BOOST_MATH_NAMESPACE::pow<15>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<16>(s, pol); } case 16: { constexpr long long P[] = { 209865342976LL, 3099269660672LL, 8885192097792LL, 7048869314560LL, 1594922762240LL, 84134068224LL, 536608768LL, 32768 }; - return boost::math::pow<16>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<17>(s, pol); + return BOOST_MATH_NAMESPACE::pow<16>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<17>(s, pol); } case 17: { constexpr long long P[] = { -209865342976LL, -12655654469632LL, -87815735738368LL, -155964390375424LL, -84842998005760LL, -13684856848384LL, -511780323328LL, -2146926592LL, -65536 }; - return boost::math::pow<17>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<18>(s, pol); + return BOOST_MATH_NAMESPACE::pow<17>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<18>(s, pol); } case 18: { constexpr long long P[] = { 29088885112832LL, 553753414467584LL, 2165206642589696LL, 2550316668551168LL, 985278548541440LL, 115620218667008LL, 3100738912256LL, 8588754944LL, 131072 }; - return boost::math::pow<18>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<19>(s, pol); + return BOOST_MATH_NAMESPACE::pow<18>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<19>(s, pol); } case 19: { constexpr long long P[] = { -29088885112832LL, -2184860175433728LL, -19686087844429824LL, -48165109676113920LL, -39471306959486976LL, -11124607890751488LL, -965271355195392LL, -18733264797696LL, -34357248000LL, -262144 }; - return boost::math::pow<19>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / boost::math::pow<20>(s, pol); + return BOOST_MATH_NAMESPACE::pow<19>(constants::pi(), pol) * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<20>(s, pol); } case 20: { constexpr long long P[] = { 4951498053124096LL, 118071834535526400LL, 603968063567560704LL, 990081991141490688LL, 584901762421358592LL, 122829335169859584LL, 7984436548730880LL, 112949304754176LL, 137433710592LL, 524288 }; - return boost::math::pow<20>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / boost::math::pow<21>(s, pol); + return BOOST_MATH_NAMESPACE::pow<20>(constants::pi(), pol) * c * tools::evaluate_even_polynomial(P, c) / BOOST_MATH_NAMESPACE::pow<21>(s, pol); } #endif } @@ -448,7 +468,7 @@ namespace boost { namespace math { namespace detail{ } } - T sum = boost::math::tools::evaluate_even_polynomial(&table[index][0], c, table[index].size()); + T sum = BOOST_MATH_NAMESPACE::tools::evaluate_even_polynomial(&table[index][0], c, table[index].size()); if(index & 1) sum *= c; // First coefficient is order 1, and really an odd polynomial. if(sum == 0) @@ -457,17 +477,17 @@ namespace boost { namespace math { namespace detail{ // The remaining terms are computed using logs since the powers and factorials // get real large real quick: // - T power_terms = n * log(boost::math::constants::pi()); + T power_terms = n * log(BOOST_MATH_NAMESPACE::constants::pi()); if(s == 0) - return sum * boost::math::policies::raise_overflow_error(function, nullptr, pol); + return sum * BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); power_terms -= log(fabs(s)) * (n + 1); - power_terms += boost::math::lgamma(T(n), pol); + power_terms += BOOST_MATH_NAMESPACE::lgamma(T(n), pol); power_terms += log(fabs(sum)); - if(power_terms > boost::math::tools::log_max_value()) - return sum * boost::math::policies::raise_overflow_error(function, nullptr, pol); + if(power_terms > BOOST_MATH_NAMESPACE::tools::log_max_value()) + return sum * BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); - return exp(power_terms) * ((s < 0) && ((n + 1) & 1) ? -1 : 1) * boost::math::sign(sum); + return exp(power_terms) * ((s < 0) && ((n + 1) & 1) ? -1 : 1) * BOOST_MATH_NAMESPACE::sign(sum); } template @@ -512,13 +532,13 @@ namespace boost { namespace math { namespace detail{ } else if(x == 1) { - return (n & 1 ? 1 : -1) * boost::math::factorial(n, pol) * boost::math::zeta(T(n + 1), pol); + return (n & 1 ? 1 : -1) * BOOST_MATH_NAMESPACE::factorial(n, pol) * BOOST_MATH_NAMESPACE::zeta(T(n + 1), pol); } else if(x == 0.5f) { - T result = (n & 1 ? 1 : -1) * boost::math::factorial(n, pol) * boost::math::zeta(T(n + 1), pol); + T result = (n & 1 ? 1 : -1) * BOOST_MATH_NAMESPACE::factorial(n, pol) * BOOST_MATH_NAMESPACE::zeta(T(n + 1), pol); if(fabs(result) >= ldexp(tools::max_value(), -n - 1)) - return boost::math::sign(result) * policies::raise_overflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::sign(result) * policies::raise_overflow_error(function, nullptr, pol); result *= ldexp(T(1), n + 1) - 1; return result; } @@ -528,7 +548,7 @@ namespace boost { namespace math { namespace detail{ } } -} } } // namespace boost::math::detail +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/detail/prime_sieve/big_range.hpp b/include/boost/math/special_functions/detail/prime_sieve/big_range.hpp new file mode 100644 index 0000000000..1fb8bf28ac --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/big_range.hpp @@ -0,0 +1,324 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Ranges beyond 2^64 and short intervals at large magnitudes: sieve a window of odd +// numbers by the primes up to a modest depth, then test each survivor individually +// (deterministic Miller-Rabin below 2^64, the pseudosquares test while the table +// covers n / depth, Baillie-PSW beyond). Sorenson, "The pseudosquares prime sieve" (2006). + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_BIG_RANGE_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_BIG_RANGE_HPP + +#include + +#ifndef BOOST_MATH_HAS_NVRTC + +#include +#include +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +inline constexpr std::uint64_t window_min_depth {100000}; +inline constexpr std::uint64_t window_max_depth {100000000}; +inline constexpr std::size_t window_max_bits {std::size_t(1) << 24}; // odd candidates per window (2 MiB) + +// The short-interval heuristic for 64-bit ranges: when (width * ln(stop))^2 < stop the +// per-candidate tests are cheaper than generating pi(sqrt(stop)) sieving primes. +inline bool prefer_test_path(std::uint64_t start, std::uint64_t stop, const prime_sieve_options& options) noexcept +{ + if (options.range_strategy == prime_range_strategy::full_sieve) + { + return false; + } + if (options.range_strategy == prime_range_strategy::test_survivors) + { + return true; + } + const double width {static_cast(stop - start) + 1.0}; + const double t {width * std::log(static_cast(stop))}; + return t * t < static_cast(stop); +} + +// Sieving depth s balancing pi(s) modular reductions against the tests on the survivors, +// whose density after sieving to s is about 0.56 / ln(s) (Mertens' theorem). +// test_cost is the cost of one primality test relative to one modular reduction. +inline std::uint64_t choose_window_depth(double window_width, double test_cost, std::uint64_t sqrt_upper) noexcept +{ + double s {window_min_depth}; + for (int i {0}; i < 8; ++i) + { + const double ln_s {std::log(s)}; + s = 0.5615 * window_width * test_cost / ln_s; + s = (std::max)(s, static_cast(window_min_depth)); + s = (std::min)(s, static_cast(window_max_depth)); + } + std::uint64_t depth {static_cast(s)}; + depth = (std::min)(depth, sqrt_upper); + depth = (std::max)(depth, std::uint64_t(7)); + return depth; +} + +// All odd primes up to depth. +inline std::vector window_sieving_primes(std::uint64_t depth) +{ + std::vector primes; + for (std::size_t i {1}; i < 71 && small_primes_to_353[i] <= presieve_max_prime && small_primes_to_353[i] <= depth; ++i) + { + primes.push_back(small_primes_to_353[i]); + } + const std::vector rest {sieving_primes_upto(depth)}; + primes.insert(primes.end(), rest.begin(), rest.end()); + return primes; +} + +// Residue of the (odd) window base modulo small primes, specialized per base representation. +struct base_mod_u64 +{ + std::uint64_t base; + + std::uint32_t operator()(std::uint32_t p) const noexcept + { + return static_cast(base % p); + } +}; + +// base = high * 2^64 + low, reduced with 64-bit arithmetic only. +struct base_mod_u128 +{ + std::uint64_t high; + std::uint64_t low; + + std::uint32_t operator()(std::uint32_t p) const noexcept + { + const std::uint64_t two64_mod_p {((std::numeric_limits::max)() % p + 1) % p}; + const std::uint64_t r {((high % p) * two64_mod_p + low % p) % p}; + return static_cast(r); + } +}; + +template +struct base_mod_generic +{ + const Integer& base; + + std::uint32_t operator()(std::uint32_t p) const + { + return static_cast(base % Integer(p)); + } +}; + +// Marks composites among the odd numbers base + 2 i, i < bits, using the given primes. +// A prime equal to a candidate is left standing. +template +void sieve_window(std::vector& composite, std::size_t bits, const BaseMod& base_mod, + const std::vector& primes, std::uint64_t small_base) +{ + composite.assign(bits, 0); + for (const std::uint32_t p : primes) + { + const std::uint32_t r {base_mod(p)}; + // first multiple >= base, made odd + std::uint64_t offset {r == 0 ? 0 : static_cast(p - r)}; + if (offset & 1u) + { + offset += p; + } + const std::uint64_t square {static_cast(p) * p}; + if (small_base != 0 && small_base < square) + { + // p * p is an odd multiple of p at or above the base, so this only moves the start up + offset = square - small_base; + } + for (std::uint64_t i {offset / 2}; i < bits; i += p) + { + composite[static_cast(i)] = 1; + } + } +} + +// Sieves [start, stop] (start >= 7, both < 2^64) by the window method and passes batches +// of primes to consume(const std::uint64_t*, std::size_t). +template +void test_range_u64(std::uint64_t start, std::uint64_t stop, Consumer& consume) +{ + if (stop < start) + { + return; + } + const std::uint64_t root {BOOST_MATH_NAMESPACE::tools::isqrt(stop)}; + const double width {static_cast(stop - start) + 1.0}; + const std::uint64_t depth {choose_window_depth((std::min)(width, 2.0 * static_cast(window_max_bits)), 100.0, root)}; + const std::vector primes {window_sieving_primes(depth)}; + std::vector composite; + std::vector batch; + batch.reserve(4096); + + std::uint64_t base {start | 1u}; + while (base <= stop) + { + const std::uint64_t remaining {(stop - base) / 2 + 1}; + const std::size_t bits {static_cast((std::min)(remaining, static_cast(window_max_bits)))}; + sieve_window(composite, bits, base_mod_u64 {base}, primes, base); + for (std::size_t i {0}; i < bits; ++i) + { + if (!composite[i]) + { + const std::uint64_t n {base + 2u * static_cast(i)}; + if (is_prime_u64(n)) + { + batch.push_back(n); + if (batch.size() == batch.capacity()) + { + consume(batch.data(), batch.size()); + batch.clear(); + } + } + } + } + if (bits == window_max_bits && base <= stop - 2u * static_cast(window_max_bits)) + { + base += 2u * static_cast(window_max_bits); + } + else + { + break; + } + } + if (!batch.empty()) + { + consume(batch.data(), batch.size()); + } +} + +// Classifies a survivor above 2^64. +template +bool survivor_is_prime(const Integer& n, std::size_t pss_index, std::uint64_t depth, bool probable_only) +{ + if (!probable_only && pss_index < 49) + { + return pseudosquares_prime_test(n, pss_index, depth); + } + return is_probable_prime_bpsw(n); +} + +// Primes in [lower, upper] (inclusive, lower >= 7, upper >= 2^64) passed one at a time to +// emit(const Integer&). +template +void big_range_impl(const Integer& lower, const Integer& upper, const prime_sieve_options& options, Emit&& emit) +{ + if (upper < lower) + { + return; + } + const Integer two64 {Integer((std::numeric_limits::max)()) + Integer(1)}; + const bool fits_128 {upper < two64 * two64}; + + const Integer total_width {upper - lower}; + const double width {total_width > Integer(2u * window_max_bits) ? 2.0 * static_cast(window_max_bits) : static_cast(total_width) + 1.0}; + const double test_cost {options.probable_prime_only ? 2000.0 : 40000.0}; + const std::uint64_t depth {choose_window_depth(width, test_cost, window_max_depth)}; + const std::vector primes {window_sieving_primes(depth)}; + std::vector composite; + + Integer base {lower % 2 == 0 ? lower + Integer(1) : lower}; + while (base <= upper) + { + const Integer remaining {(upper - base) / 2 + 1}; + const std::size_t bits {remaining > Integer(window_max_bits) ? window_max_bits : static_cast(static_cast(remaining))}; + const Integer window_high {base + Integer(2u) * Integer(bits - 1)}; + + if (fits_128) + { + const std::uint64_t high {static_cast((base / two64) % two64)}; + const std::uint64_t low {static_cast(base % two64)}; + sieve_window(composite, bits, base_mod_u128 {high, low}, primes, 0); + } + else + { + sieve_window(composite, bits, base_mod_generic {base}, primes, 0); + } + + const Integer n_over_s {window_high / Integer(depth)}; + const std::size_t pss_index {pseudosquare_index_for(n_over_s)}; + for (std::size_t i {0}; i < bits; ++i) + { + if (!composite[i]) + { + const Integer n {base + Integer(2u) * Integer(i)}; + if (fits_u64(n)) + { + if (is_prime_u64(to_u64(n))) + { + emit(n); + } + } + else if (survivor_is_prime(n, pss_index, depth, options.probable_prime_only)) + { + emit(n); + } + } + } + if (bits < window_max_bits) + { + break; + } + base += Integer(2u) * Integer(window_max_bits); + } +} + +// Primes in [lower, upper] (inclusive) for bounds that do not fit 64 bits. Builtin types +// can never reach this point, so they get an empty instantiation. +template +OutputIterator big_range(const Integer& lower, const Integer& upper, OutputIterator out, const prime_sieve_options& options) +{ + if constexpr (std::is_integral::value) + { + (void)lower; + (void)upper; + (void)options; + return out; + } + else + { + big_range_impl(lower, upper, options, [&](const Integer& p) { *out = p; ++out; }); + return out; + } +} + +template +std::uint64_t big_count(const Integer& lower, const Integer& upper, const prime_sieve_options& options) +{ + if constexpr (std::is_integral::value) + { + (void)lower; + (void)upper; + (void)options; + return 0; + } + else + { + std::uint64_t count {0}; + big_range_impl(lower, upper, options, [&](const Integer&) { ++count; }); + return count; + } +} + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_HAS_NVRTC +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_BIG_RANGE_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/cpu_cache.hpp b/include/boost/math/special_functions/detail/prime_sieve/cpu_cache.hpp new file mode 100644 index 0000000000..acf4591bf3 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/cpu_cache.hpp @@ -0,0 +1,115 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Best-effort detection of the data cache sizes that drive the segment geometry. +// Falls back to 32 KiB L1 and 1 MiB L2 per core where nothing can be queried. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_CPU_CACHE_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_CPU_CACHE_HPP + +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif + +#if defined(__APPLE__) +# include +# include +#elif defined(__linux__) +# include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +struct cache_info +{ + std::size_t l1d_bytes {32768}; + std::size_t l2_bytes {1048576}; // per core (L2 size divided by the cores sharing it) +}; + +inline cache_info detect_cache_info() noexcept +{ + cache_info info {}; + +#if defined(__APPLE__) + std::int64_t value {0}; + std::size_t size {sizeof(value)}; + if (sysctlbyname("hw.perflevel0.l1dcachesize", &value, &size, nullptr, 0) == 0 && value > 0) + { + info.l1d_bytes = static_cast(value); + } + else + { + value = 0; + size = sizeof(value); + if (sysctlbyname("hw.l1dcachesize", &value, &size, nullptr, 0) == 0 && value > 0) + { + info.l1d_bytes = static_cast(value); + } + } + value = 0; + size = sizeof(value); + std::int64_t l2 {0}; + if (sysctlbyname("hw.perflevel0.l2cachesize", &value, &size, nullptr, 0) == 0 && value > 0) + { + l2 = value; + std::int64_t sharing {0}; + size = sizeof(sharing); + if (sysctlbyname("hw.perflevel0.cpusperl2", &sharing, &size, nullptr, 0) == 0 && sharing > 1) + { + l2 /= sharing; + } + } + else + { + value = 0; + size = sizeof(value); + if (sysctlbyname("hw.l2cachesize", &value, &size, nullptr, 0) == 0 && value > 0) + { + l2 = value; + } + } + if (l2 > 0) + { + info.l2_bytes = static_cast(l2); + } +#elif defined(__linux__) && defined(_SC_LEVEL1_DCACHE_SIZE) + const long l1 {sysconf(_SC_LEVEL1_DCACHE_SIZE)}; + if (l1 > 0) + { + info.l1d_bytes = static_cast(l1); + } +# if defined(_SC_LEVEL2_CACHE_SIZE) + const long l2 {sysconf(_SC_LEVEL2_CACHE_SIZE)}; + if (l2 > 0) + { + info.l2_bytes = static_cast(l2); + } +# endif +#endif + + // Guard against nonsense from virtual machines + if (info.l1d_bytes < 4096 || info.l1d_bytes > (1u << 20)) + { + info.l1d_bytes = 32768; + } + if (info.l2_bytes < info.l1d_bytes || info.l2_bytes > (std::size_t(1) << 30)) + { + info.l2_bytes = 1048576; + } + return info; +} + +inline const cache_info& cached_cache_info() noexcept +{ + static const cache_info info {detect_cache_info()}; + return info; +} + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_CPU_CACHE_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/cuda.hpp b/include/boost/math/special_functions/detail/prime_sieve/cuda.hpp new file mode 100644 index 0000000000..3ff70f79d0 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/cuda.hpp @@ -0,0 +1,889 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// CUDA backend of the prime sieve. Only compiled by nvcc with BOOST_MATH_ENABLE_CUDA. +// +// The range is processed in chunks of up to 2^32 integers. Each chunk is sieved by a grid of +// thread blocks, one block per 32 KiB shared-memory segment (983040 integers) in the same +// mod-30 byte layout as the CPU engine: primes 7..37 are removed by ANDing periodic tables, +// primes 41..1024 are handled one warp per prime, and primes up to the segment span one +// thread per prime with atomicAnd on shared memory. Primes above the segment span (at most +// one multiple per segment) are applied in a second kernel directly on the chunk's bitset in +// global memory. Counting uses __popc with a block reduction; generation compacts the set +// bits into a sorted 64-bit array through a two-level exclusive scan. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_CUDA_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_CUDA_HPP + +#include + +#if defined(__CUDACC__) && defined(BOOST_MATH_ENABLE_CUDA) && !defined(BOOST_MATH_HAS_NVRTC) + +#define BOOST_MATH_HAS_CUDA_PRIME_SIEVE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +namespace cuda_detail { + +inline constexpr unsigned segment_bytes {32768}; // shared memory per block +inline constexpr unsigned segment_span {segment_bytes * 30u}; // integers per segment +inline constexpr unsigned block_threads {256}; +inline constexpr unsigned warp_prime_limit {1024}; // primes up to this: one warp per prime +inline constexpr unsigned presieve_limit {37}; // primes up to this: periodic tables +inline constexpr unsigned segments_per_chunk {4369}; // about 2^32 integers per device chunk +inline constexpr std::size_t chunk_bytes {static_cast(segments_per_chunk) * segment_bytes}; +inline constexpr std::uint64_t chunk_numbers {static_cast(chunk_bytes) * 30u}; // multiple of 30 + +// Reports a failed CUDA call. Without host exceptions there is nowhere to return the +// error to, so the message goes to stderr and the process aborts. +inline void cuda_check(cudaError_t e, const char* what) +{ + if (e != cudaSuccess) + { +#ifndef BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS + throw std::runtime_error(std::string("boost::math::prime_sieve CUDA error in ") + what + ": " + cudaGetErrorString(e)); +#else + std::fprintf(stderr, "boost::math::prime_sieve CUDA error in %s: %s\n", what, cudaGetErrorString(e)); + std::abort(); +#endif + } +} + +template +class device_buffer +{ +public: + device_buffer() = default; + + explicit device_buffer(std::size_t n) + { + allocate(n); + } + + ~device_buffer() + { + release(); + } + + device_buffer(const device_buffer&) = delete; + device_buffer& operator=(const device_buffer&) = delete; + + void allocate(std::size_t n) + { + release(); + if (n != 0) + { + void* p {nullptr}; + cuda_check(cudaMalloc(&p, n * sizeof(T)), "cudaMalloc"); + ptr_ = static_cast(p); + size_ = n; + } + } + + void release() noexcept + { + if (ptr_ != nullptr) + { + cudaFree(ptr_); + ptr_ = nullptr; + size_ = 0; + } + } + + void upload(const T* host, std::size_t n) + { + cuda_check(cudaMemcpy(ptr_, host, n * sizeof(T), cudaMemcpyHostToDevice), "cudaMemcpy H2D"); + } + + void download(T* host, std::size_t n) const + { + cuda_check(cudaMemcpy(host, ptr_, n * sizeof(T), cudaMemcpyDeviceToHost), "cudaMemcpy D2H"); + } + + T* get() noexcept + { + return ptr_; + } + + const T* get() const noexcept + { + return ptr_; + } + + std::size_t size() const noexcept + { + return size_; + } + +private: + T* ptr_ {nullptr}; + std::size_t size_ {0}; +}; + +// Page-locked host memory for fast device to host copies; falls back to pageable memory. +class pinned_buffer +{ +public: + pinned_buffer() = default; + + ~pinned_buffer() + { + release(); + } + + pinned_buffer(const pinned_buffer&) = delete; + pinned_buffer& operator=(const pinned_buffer&) = delete; + + void reserve(std::size_t n) + { + if (n <= size_) + { + return; + } + release(); + void* p {nullptr}; + if (cudaMallocHost(&p, n * sizeof(std::uint64_t)) == cudaSuccess) + { + ptr_ = static_cast(p); + pinned_ = true; + } + else + { + (void)cudaGetLastError(); + fallback_.resize(n); + ptr_ = fallback_.data(); + pinned_ = false; + } + size_ = n; + } + + std::uint64_t* data() noexcept + { + return ptr_; + } + +private: + void release() noexcept + { + if (pinned_ && ptr_ != nullptr) + { + cudaFreeHost(ptr_); + } + fallback_.clear(); + fallback_.shrink_to_fit(); + ptr_ = nullptr; + size_ = 0; + pinned_ = false; + } + + std::uint64_t* ptr_ {nullptr}; + std::size_t size_ {0}; + bool pinned_ {false}; + std::vector fallback_; +}; + +// Tables the kernels need, passed by value so no device globals are required. Kernels copy +// them into shared memory first: constant memory serializes lane-divergent indexing. +struct alignas(4) device_tables +{ + std::uint8_t unset_bit[8]; + std::uint8_t bit_values[64]; + std::uint8_t keep_low[37]; + std::uint8_t keep_high[37]; + std::uint8_t class_of_residue[30]; // bit_of_residue for residues coprime to 30 + std::uint8_t inverse_mod_30[30]; // multiplicative inverse for residues coprime to 30 + std::uint8_t init_factor[30]; // wheel30 init: distance to the next coprime multiplier + std::uint8_t init_phase[30]; // wheel30 init: phase of that multiplier + std::uint8_t padding[2]; + std::uint32_t wheel[64]; // wheel30 element by state: unset | factor << 8 | correct << 16 | next << 24 +}; + +__device__ __forceinline__ std::uint8_t wheel_unset(std::uint32_t w) { return static_cast(w); } +__device__ __forceinline__ std::uint32_t wheel_factor(std::uint32_t w) { return (w >> 8) & 0xffu; } +__device__ __forceinline__ std::uint32_t wheel_correct(std::uint32_t w) { return (w >> 16) & 0xffu; } +__device__ __forceinline__ unsigned wheel_next(std::uint32_t w) { return w >> 24; } + +static_assert(sizeof(device_tables) % 4 == 0, "device_tables must be copyable in 32-bit words"); + +// Block-cooperative copy of the kernel's table argument into shared memory. +__device__ __forceinline__ void load_tables(const device_tables& from, device_tables& to) +{ + const std::uint32_t* src {reinterpret_cast(&from)}; + std::uint32_t* dst {reinterpret_cast(&to)}; + for (unsigned i {threadIdx.x}; i < sizeof(device_tables) / 4; i += blockDim.x) + { + dst[i] = src[i]; + } + __syncthreads(); +} + +constexpr device_tables make_device_tables() noexcept +{ + device_tables t {}; + for (unsigned k {0}; k < 8; ++k) + { + t.unset_bit[k] = unset_bit[k]; + } + for (unsigned b {0}; b < 64; ++b) + { + t.bit_values[b] = bit_values[b]; + t.wheel[b] = static_cast(wheel30.wheel[b].unset_bit) + | (static_cast(wheel30.wheel[b].next_multiple_factor) << 8) + | (static_cast(wheel30.wheel[b].correct) << 16) + | (static_cast(wheel30.wheel[b].next) << 24); + } + for (unsigned d {0}; d < 37; ++d) + { + t.keep_low[d] = keep_low[d]; + t.keep_high[d] = keep_high[d]; + } + for (unsigned r {0}; r < 30; ++r) + { + t.class_of_residue[r] = bit_of_residue(r); + t.init_factor[r] = wheel30.init[r].next_multiple_factor; + t.init_phase[r] = wheel30.init[r].wheel_index; + t.inverse_mod_30[r] = 0; + for (unsigned x {1}; x < 30; ++x) + { + if ((r * x) % 30 == 1) + { + t.inverse_mod_30[r] = static_cast(x); + } + } + } + return t; +} + +// Built at compile time; copied into a kernel argument per launch. +inline constexpr device_tables device_tables_value = make_device_tables(); + +// Per sieving prime: p, chunk_low mod p (advanced per chunk) and the Barrett constant for p, +// so that segment_low mod p needs no 64-bit division. +struct device_prime +{ + std::uint32_t p; + std::uint32_t residue; // chunk_low mod p + std::uint64_t barrett; // floor(2^64 / p) +}; + +// r = t mod p for t < 2^63 using the precomputed floor(2^64 / p). +__device__ __forceinline__ std::uint32_t barrett_mod(std::uint64_t t, std::uint32_t p, std::uint64_t m) +{ + std::uint64_t q {__umul64hi(t, m)}; + std::uint64_t r {t - q * p}; + if (r >= p) + { + r -= p; + } + return static_cast(r); +} + +// Integer offset from segment_low and wheel state of the first multiple of p that is at least +// max(segment_low, p * p) and coprime to 30. segment_low_mod_p is segment_low modulo p. +__device__ __forceinline__ void first_multiple_offset(const device_tables& t, std::uint32_t p, std::uint64_t segment_low, + std::uint32_t segment_low_mod_p, std::uint64_t& d, unsigned& state) +{ + // d0: offset (in integers) of the first multiple >= segment_low + d = segment_low_mod_p == 0 ? 0u : p - segment_low_mod_p; + const unsigned p_mod_30 {p % 30u}; + unsigned q_mod_30 {}; + const std::uint64_t square {static_cast(p) * p}; + if (segment_low + d < square) + { + // never cross off the prime itself or multiples a smaller prime already removed + d = square - segment_low; + q_mod_30 = p_mod_30; + } + else + { + // q0 mod 30 from d0 mod 30 (segment_low is a multiple of 30) and the inverse of p mod 30 + q_mod_30 = static_cast((d % 30u) * t.inverse_mod_30[p_mod_30] % 30u); + } + d += static_cast(t.init_factor[q_mod_30]) * p; + state = t.class_of_residue[p_mod_30] * 8u + t.init_phase[q_mod_30]; + // offsets below 7 belong to the previous segment's last byte: step once more + while (d < 7) + { + const std::uint32_t w {t.wheel[state]}; + d += static_cast(wheel_factor(w)) * p; + state = wheel_next(w); + } +} + +// Byte index (relative to the segment) and wheel state of the first multiple in a segment. +// Multiples beyond the segment yield an index >= segment_bytes. +__device__ __forceinline__ void first_multiple_device(const device_tables& t, std::uint32_t p, std::uint64_t segment_low, + std::uint32_t segment_low_mod_p, std::uint32_t& byte_index, std::uint32_t& state) +{ + std::uint64_t d {}; + unsigned s {}; + first_multiple_offset(t, p, segment_low, segment_low_mod_p, d, s); + const std::uint64_t byte {(d - 7) / 30}; + byte_index = byte > segment_bytes ? segment_bytes : static_cast(byte); + state = s; +} + +__device__ __forceinline__ void clear_bit(std::uint32_t* words, std::uint32_t byte_index, std::uint8_t mask) +{ + const std::uint32_t word_mask {~(static_cast(static_cast(~mask)) << (8u * (byte_index & 3u)))}; + atomicAnd(&words[byte_index >> 2], word_mask); +} + +// One block sieves one segment of the chunk. primes[0, n_warp) are handled per warp, primes +// [n_warp, n_thread) per thread. The finished segment is written to chunk_words. +__global__ void __launch_bounds__(block_threads) +sieve_segments_kernel(device_tables table_arg, const device_prime* primes, std::uint32_t n_warp, std::uint32_t n_thread, + const std::uint8_t* presieve0, std::uint32_t period0, const std::uint8_t* presieve1, std::uint32_t period1, + const std::uint8_t* presieve2, std::uint32_t period2, + std::uint32_t* chunk_words, std::uint64_t chunk_low, std::uint64_t start, std::uint64_t stop, std::uint32_t n_segments) +{ + __shared__ std::uint32_t words[segment_bytes / 4]; + __shared__ device_tables tables; + const std::uint32_t segment {blockIdx.x}; + if (segment >= n_segments) + { + return; + } + load_tables(table_arg, tables); + const std::uint64_t segment_low {chunk_low + static_cast(segment) * segment_span}; + std::uint8_t* bytes {reinterpret_cast(words)}; + + // bytes actually covering [segment_low + 7, stop] + std::uint32_t used_bytes {segment_bytes}; + if (stop - segment_low < static_cast(segment_span) + 1) + { + const std::uint64_t remaining {stop - segment_low}; + used_bytes = remaining < 7 ? 0u : static_cast((remaining - 7) / 30 + 1); + } + + // phase 0: pre-sieve 7..37 from the periodic tables + { + const std::uint32_t byte_low {static_cast((segment_low / 30) % period0)}; + const std::uint32_t byte_low1 {static_cast((segment_low / 30) % period1)}; + const std::uint32_t byte_low2 {static_cast((segment_low / 30) % period2)}; + for (std::uint32_t i {threadIdx.x}; i < segment_bytes; i += block_threads) + { + std::uint32_t p0 {byte_low + i}; + if (p0 >= period0) { p0 -= period0; if (p0 >= period0) { p0 %= period0; } } + std::uint32_t p1 {byte_low1 + i}; + if (p1 >= period1) { p1 -= period1; if (p1 >= period1) { p1 %= period1; } } + std::uint32_t p2 {byte_low2 + i}; + if (p2 >= period2) { p2 -= period2; if (p2 >= period2) { p2 %= period2; } } + bytes[i] = presieve0[p0] & presieve1[p1] & presieve2[p2]; + } + } + // the first segments of the number line contain the pre-sieved primes themselves + if (threadIdx.x == 0 && segment_low <= presieve_limit) + { + const std::uint8_t small[9] = {7, 11, 13, 17, 19, 23, 29, 31, 37}; + for (unsigned k {0}; k < 9; ++k) + { + if (small[k] >= segment_low + 7) + { + bytes[(small[k] - segment_low - 7) / 30] |= static_cast(1u << tables.class_of_residue[small[k] % 30]); + } + } + } + __syncthreads(); + + // phase 1: warp per prime for the small primes + { + const unsigned lane {threadIdx.x & 31u}; + const unsigned warp {threadIdx.x >> 5}; + const unsigned warps {block_threads / 32u}; + for (std::uint32_t idx {warp}; idx < n_warp; idx += warps) + { + const device_prime pr {primes[idx]}; + const std::uint32_t span_mod {barrett_mod(segment_span, pr.p, pr.barrett)}; + const std::uint32_t low_mod {barrett_mod(static_cast(pr.residue) + static_cast(segment) * span_mod, pr.p, pr.barrett)}; + std::uint32_t i {}; + std::uint32_t state {}; + first_multiple_device(tables, pr.p, segment_low, low_mod, i, state); + // one wheel turn is exactly p bytes; the eight offsets within a turn are fixed + std::uint32_t offsets[8]; + std::uint8_t masks[8]; + const std::uint32_t p30 {pr.p / 30u}; + std::uint32_t o {0}; + for (unsigned k {0}; k < 8; ++k) + { + const std::uint32_t w {tables.wheel[state]}; + offsets[k] = o; + masks[k] = wheel_unset(w); + o += p30 * wheel_factor(w) + wheel_correct(w); + state = wheel_next(w); + } + for (std::uint32_t turn_start {i + lane * pr.p}; turn_start < segment_bytes; turn_start += 32u * pr.p) + { + for (unsigned k {0}; k < 8; ++k) + { + const std::uint32_t b {turn_start + offsets[k]}; + if (b < segment_bytes) + { + clear_bit(words, b, masks[k]); + } + } + } + } + } + + // phase 2: thread per prime for the medium primes + for (std::uint32_t idx {n_warp + threadIdx.x}; idx < n_thread; idx += block_threads) + { + const device_prime pr {primes[idx]}; + const std::uint32_t span_mod {barrett_mod(segment_span, pr.p, pr.barrett)}; + const std::uint32_t low_mod {barrett_mod(static_cast(pr.residue) + static_cast(segment) * span_mod, pr.p, pr.barrett)}; + std::uint32_t i {}; + std::uint32_t state {}; + first_multiple_device(tables, pr.p, segment_low, low_mod, i, state); + const std::uint32_t p30 {pr.p / 30u}; + while (i < segment_bytes) + { + const std::uint32_t w {tables.wheel[state]}; + clear_bit(words, i, wheel_unset(w)); + i += p30 * wheel_factor(w) + wheel_correct(w); + state = wheel_next(w); + } + } + __syncthreads(); + + // phase 3: range masks, tail zeroing, store to global memory + if (threadIdx.x == 0) + { + if (segment_low < start && start - segment_low < 37) + { + bytes[0] &= tables.keep_low[start - segment_low]; + } + if (used_bytes != 0 && used_bytes < segment_bytes) + { + const std::uint64_t e {stop - segment_low - 30u * static_cast(used_bytes - 1)}; + bytes[used_bytes - 1] &= tables.keep_high[e > 36 ? 36 : static_cast(e)]; + } + else if (used_bytes == segment_bytes && stop - segment_low < static_cast(segment_span) + 1) + { + const std::uint64_t e {stop - segment_low - 30u * static_cast(segment_bytes - 1)}; + bytes[segment_bytes - 1] &= tables.keep_high[e > 36 ? 36 : static_cast(e)]; + } + } + __syncthreads(); + for (std::uint32_t i {threadIdx.x}; i < segment_bytes; i += block_threads) + { + if (i >= used_bytes) + { + bytes[i] = 0; + } + } + __syncthreads(); + std::uint32_t* out {chunk_words + static_cast(segment) * (segment_bytes / 4)}; + for (std::uint32_t w {threadIdx.x}; w < segment_bytes / 4; w += block_threads) + { + out[w] = words[w]; + } +} + +// Primes above the segment span: one thread per prime over the whole chunk bitset. +__global__ void __launch_bounds__(block_threads) +sieve_big_kernel(device_tables table_arg, const device_prime* primes, std::uint32_t first, std::uint32_t count, + std::uint32_t* chunk_words, std::uint64_t chunk_low, std::uint64_t stop, std::uint64_t chunk_bytes_used) +{ + __shared__ device_tables tables; + load_tables(table_arg, tables); + const std::uint32_t idx {first + blockIdx.x * block_threads + threadIdx.x}; + if (idx >= count) + { + return; + } + const device_prime pr {primes[idx]}; + std::uint64_t d {}; + unsigned state {}; + first_multiple_offset(tables, pr.p, chunk_low, pr.residue, d, state); + const std::uint64_t limit {stop - chunk_low}; + while (d <= limit) + { + const std::uint64_t byte {(d - 7) / 30}; + if (byte >= chunk_bytes_used) + { + break; + } + const std::uint32_t w {tables.wheel[state]}; + const std::uint32_t word_mask {~(static_cast(static_cast(~wheel_unset(w))) << (8u * static_cast(byte & 3u)))}; + atomicAnd(&chunk_words[byte >> 2], word_mask); + d += static_cast(wheel_factor(w)) * pr.p; + state = wheel_next(w); + } +} + +// residue = (residue + chunk_mod) mod p after a chunk advanced by chunk_numbers. +__global__ void advance_residues_kernel(device_prime* primes, std::uint32_t count) +{ + const std::uint32_t idx {blockIdx.x * block_threads + threadIdx.x}; + if (idx < count) + { + const std::uint32_t p {primes[idx].p}; + std::uint32_t r {primes[idx].residue + static_cast(chunk_numbers % p)}; + if (r >= p) + { + r -= p; + } + primes[idx].residue = r; + } +} + +// Per-block popcounts over 256 * 4 words each (block_totals) and a global total. +__global__ void __launch_bounds__(block_threads) +count_kernel(const std::uint32_t* words, std::uint32_t n_words, std::uint32_t* block_totals, unsigned long long* total) +{ + __shared__ std::uint32_t partial[block_threads / 32]; + std::uint32_t c {0}; + const std::uint32_t base {blockIdx.x * block_threads * 4u}; + for (unsigned k {0}; k < 4; ++k) + { + const std::uint32_t w {base + k * block_threads + threadIdx.x}; + if (w < n_words) + { + c += static_cast(__popc(words[w])); + } + } + for (unsigned offset {16}; offset > 0; offset >>= 1) + { + c += __shfl_down_sync(0xffffffffu, c, offset); + } + if ((threadIdx.x & 31u) == 0) + { + partial[threadIdx.x >> 5] = c; + } + __syncthreads(); + if (threadIdx.x == 0) + { + std::uint32_t sum {0}; + for (unsigned i {0}; i < block_threads / 32; ++i) + { + sum += partial[i]; + } + if (block_totals != nullptr) + { + block_totals[blockIdx.x] = sum; + } + if (total != nullptr) + { + atomicAdd(total, static_cast(sum)); + } + } +} + +// Exclusive scan of the block totals in place (single block), writing the grand total. +__global__ void scan_totals_kernel(std::uint32_t* totals, std::uint32_t n, unsigned long long* grand_total) +{ + __shared__ unsigned long long carry; + __shared__ std::uint32_t values[1024]; + if (threadIdx.x == 0) + { + carry = 0; + } + __syncthreads(); + for (std::uint32_t base {0}; base < n; base += 1024) + { + const std::uint32_t i {base + threadIdx.x}; + const std::uint32_t v {i < n ? totals[i] : 0u}; + values[threadIdx.x] = v; + __syncthreads(); + // Hillis-Steele inclusive scan in shared memory + for (unsigned offset {1}; offset < 1024; offset <<= 1) + { + const std::uint32_t add {threadIdx.x >= offset ? values[threadIdx.x - offset] : 0u}; + __syncthreads(); + values[threadIdx.x] += add; + __syncthreads(); + } + const unsigned long long exclusive {carry + values[threadIdx.x] - v}; + if (i < n) + { + totals[i] = static_cast(exclusive); + } + __syncthreads(); + if (threadIdx.x == 1023) + { + carry += values[1023]; + } + __syncthreads(); + } + if (threadIdx.x == 0 && grand_total != nullptr) + { + *grand_total = carry; + } +} + +// Writes the integers of the set bits, in order, using the scanned block offsets. +__global__ void __launch_bounds__(block_threads) +compact_kernel(device_tables table_arg, const std::uint32_t* words, std::uint32_t n_words, const std::uint32_t* block_offsets, + std::uint64_t chunk_low, std::uint64_t* out) +{ + __shared__ std::uint32_t thread_counts[block_threads]; + __shared__ device_tables tables; + load_tables(table_arg, tables); + const std::uint32_t base {blockIdx.x * block_threads * 4u}; + std::uint32_t c {0}; + // each thread owns four consecutive words so that the output stays sorted + for (unsigned k {0}; k < 4; ++k) + { + const std::uint32_t w {base + 4u * threadIdx.x + k}; + if (w < n_words) + { + c += static_cast(__popc(words[w])); + } + } + thread_counts[threadIdx.x] = c; + __syncthreads(); + for (unsigned offset {1}; offset < block_threads; offset <<= 1) + { + const std::uint32_t add {threadIdx.x >= offset ? thread_counts[threadIdx.x - offset] : 0u}; + __syncthreads(); + thread_counts[threadIdx.x] += add; + __syncthreads(); + } + std::uint64_t pos {block_offsets[blockIdx.x] + (thread_counts[threadIdx.x] - c)}; + for (unsigned k {0}; k < 4; ++k) + { + const std::uint32_t w {base + 4u * threadIdx.x + k}; + if (w < n_words) + { + std::uint32_t bits {words[w]}; + const std::uint64_t low {chunk_low + static_cast(w) * 120u}; + while (bits != 0) + { + const int b {__ffs(bits) - 1}; + out[pos++] = low + tables.bit_values[b]; + bits &= bits - 1; + } + } + } +} + +// Host-side state for one call. +class cuda_sieve +{ +public: + cuda_sieve(std::uint64_t start, std::uint64_t stop) : start_(start), stop_(stop), tables_(device_tables_value) + { + // the chunk grid begins at a multiple of 30 covering start + chunk_low_ = 30u * ((start - 7) / 30); + + // sieving primes: 41..163 from the small table, 167.. from the CPU engine + const std::uint64_t root {BOOST_MATH_NAMESPACE::tools::isqrt(stop)}; + std::vector primes; + for (std::size_t i {0}; i < 71 && small_primes_to_353[i] <= presieve_max_prime; ++i) + { + if (small_primes_to_353[i] > presieve_limit && small_primes_to_353[i] <= root) + { + primes.push_back(small_primes_to_353[i]); + } + } +#ifdef BOOST_MATH_PRIME_SIEVE_HAS_THREADS + const std::vector rest {sieving_primes_upto_parallel(root, prime_sieve_options {})}; +#else + const std::vector rest {sieving_primes_upto(root)}; +#endif + primes.insert(primes.end(), rest.begin(), rest.end()); + + std::vector records(primes.size()); + n_warp_ = 0; + n_thread_ = 0; + for (std::size_t i {0}; i < primes.size(); ++i) + { + const std::uint32_t p {primes[i]}; + records[i].p = p; + records[i].residue = static_cast(chunk_low_ % p); + records[i].barrett = (std::numeric_limits::max)() / p; + if (p <= warp_prime_limit) + { + n_warp_ = static_cast(i + 1); + } + if (p <= segment_span) + { + n_thread_ = static_cast(i + 1); + } + } + n_primes_ = static_cast(records.size()); + if (!records.empty()) + { + primes_.allocate(records.size()); + primes_.upload(records.data(), records.size()); + } + + // pre-sieve tables for 7..37 + const std::uint8_t groups[3][3] = {{7, 11, 13}, {17, 19, 23}, {29, 31, 37}}; + for (unsigned g {0}; g < 3; ++g) + { + std::size_t period {1}; + for (const std::uint8_t p : groups[g]) + { + period *= p; + } + std::vector pattern(period, 0xff); + for (const std::uint8_t p : groups[g]) + { + presieve_mark(pattern.data(), period, p); + } + presieve_period_[g] = static_cast(period); + presieve_[g].allocate(period); + presieve_[g].upload(pattern.data(), period); + } + + words_.allocate(chunk_bytes / 4); + const std::size_t count_blocks {(chunk_bytes / 4 + block_threads * 4 - 1) / (block_threads * 4)}; + block_totals_.allocate(count_blocks); + totals_.allocate(1); + } + + // Runs f(chunk_low, chunk_stop) for every chunk with the chunk's bitset sieved into words_. + template + void for_each_chunk(F&& f) + { + std::uint64_t chunk_low {chunk_low_}; + while (true) + { + const std::uint64_t remaining {stop_ - chunk_low}; + if (remaining < 7) + { + break; + } + const std::uint64_t needed_bytes {(remaining - 7) / 30 + 1}; + const bool last {needed_bytes <= chunk_bytes}; + const std::uint64_t used_bytes {last ? needed_bytes : chunk_bytes}; + // A full chunk covers every candidate of its bytes, including offset 31 of the last + // byte (chunk_low + chunk_numbers + 1), which the next chunk cannot represent. + const std::uint64_t chunk_stop {last ? stop_ : chunk_low + chunk_numbers + 1}; + const std::uint32_t n_segments {static_cast((used_bytes + segment_bytes - 1) / segment_bytes)}; + const std::size_t n_words {static_cast(n_segments) * (segment_bytes / 4)}; + + sieve_segments_kernel<<>>(tables_, primes_.get(), n_warp_, n_thread_, + presieve_[0].get(), presieve_period_[0], presieve_[1].get(), presieve_period_[1], presieve_[2].get(), presieve_period_[2], + words_.get(), chunk_low, start_, chunk_stop, n_segments); + cuda_check(cudaGetLastError(), "sieve_segments_kernel launch"); + if (n_primes_ > n_thread_) + { + const std::uint32_t big {n_primes_ - n_thread_}; + sieve_big_kernel<<<(big + block_threads - 1) / block_threads, block_threads>>>(tables_, primes_.get(), n_thread_, n_primes_, + words_.get(), chunk_low, chunk_stop, used_bytes); + cuda_check(cudaGetLastError(), "sieve_big_kernel launch"); + } + f(chunk_low, chunk_stop, static_cast(n_words)); + if (last) + { + break; + } + advance_residues_kernel<<<(n_primes_ + block_threads - 1) / block_threads, block_threads>>>(primes_.get(), n_primes_); + cuda_check(cudaGetLastError(), "advance_residues_kernel launch"); + chunk_low += chunk_numbers; + } + } + + std::uint64_t count() + { + unsigned long long total {0}; + for_each_chunk([&](std::uint64_t, std::uint64_t, std::uint32_t n_words) + { + const unsigned long long zero {0}; + cuda_check(cudaMemcpy(totals_.get(), &zero, sizeof(zero), cudaMemcpyHostToDevice), "cudaMemcpy total"); + const std::uint32_t blocks {(n_words + block_threads * 4 - 1) / (block_threads * 4)}; + count_kernel<<>>(words_.get(), n_words, nullptr, totals_.get()); + cuda_check(cudaGetLastError(), "count_kernel launch"); + unsigned long long chunk_total {0}; + cuda_check(cudaMemcpy(&chunk_total, totals_.get(), sizeof(chunk_total), cudaMemcpyDeviceToHost), "cudaMemcpy total"); + total += chunk_total; + }); + return total; + } + + template + void generate(Consumer& consume) + { + pinned_buffer host; + for_each_chunk([&](std::uint64_t chunk_low, std::uint64_t, std::uint32_t n_words) + { + const std::uint32_t blocks {(n_words + block_threads * 4 - 1) / (block_threads * 4)}; + count_kernel<<>>(words_.get(), n_words, block_totals_.get(), nullptr); + cuda_check(cudaGetLastError(), "count_kernel launch"); + scan_totals_kernel<<<1, 1024>>>(block_totals_.get(), blocks, totals_.get()); + cuda_check(cudaGetLastError(), "scan_totals_kernel launch"); + unsigned long long chunk_total {0}; + cuda_check(cudaMemcpy(&chunk_total, totals_.get(), sizeof(chunk_total), cudaMemcpyDeviceToHost), "cudaMemcpy total"); + if (chunk_total == 0) + { + return; + } + if (output_.size() < chunk_total) + { + output_.allocate(static_cast(chunk_total)); + } + compact_kernel<<>>(tables_, words_.get(), n_words, block_totals_.get(), chunk_low, output_.get()); + cuda_check(cudaGetLastError(), "compact_kernel launch"); + host.reserve(static_cast(chunk_total)); + output_.download(host.data(), static_cast(chunk_total)); + consume(host.data(), static_cast(chunk_total)); + }); + } + +private: + std::uint64_t start_; + std::uint64_t stop_; + std::uint64_t chunk_low_ {0}; + device_tables tables_; + device_buffer primes_; + std::uint32_t n_primes_ {0}; + std::uint32_t n_warp_ {0}; + std::uint32_t n_thread_ {0}; + device_buffer presieve_[3]; + std::uint32_t presieve_period_[3] {}; + device_buffer words_; + device_buffer block_totals_; + device_buffer totals_; + device_buffer output_; +}; + +} // namespace cuda_detail + +// Counts the primes in [start, stop] (start >= 7) on the device. +inline std::uint64_t cuda_count(std::uint64_t start, std::uint64_t stop, const prime_sieve_options&) +{ + if (stop < start) + { + return 0; + } + cuda_detail::cuda_sieve sieve {start, stop}; + return sieve.count(); +} + +// Passes the primes in [start, stop] (start >= 7) in ascending batches to consume(const std::uint64_t*, std::size_t). +template +void cuda_range(std::uint64_t start, std::uint64_t stop, const prime_sieve_options&, Consumer& consume) +{ + if (stop < start) + { + return; + } + cuda_detail::cuda_sieve sieve {start, stop}; + sieve.generate(consume); +} + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // __CUDACC__ && BOOST_MATH_ENABLE_CUDA && !BOOST_MATH_HAS_NVRTC +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_CUDA_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/driver.hpp b/include/boost/math/special_functions/detail/prime_sieve/driver.hpp new file mode 100644 index 0000000000..2e585d2406 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/driver.hpp @@ -0,0 +1,136 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Sieving prime generation and the single-threaded 64-bit driver. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_DRIVER_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_DRIVER_HPP + +#include +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +// Upper bound on the number of primes <= x (Dusart 2010 for x >= 60184). +inline std::uint64_t prime_count_upper_bound(std::uint64_t x) noexcept +{ + if (x < 2) + { + return 0; + } + if (x < 60184) + { + return static_cast(1.25 * static_cast(x) / std::log(static_cast(x))) + 1; + } + const double d {static_cast(x)}; + return static_cast(d / (std::log(d) - 1.1)) + 1; +} + +// Upper bound on the number of primes in [lower, upper]. +inline std::uint64_t prime_count_upper_bound(std::uint64_t lower, std::uint64_t upper) noexcept +{ + if (upper < lower) + { + return 0; + } + if (lower < 60184) + { + return prime_count_upper_bound(upper); + } + // pi(upper) - pi(lower) <= (upper - lower) / (ln lower - 1.1) since density decreases + const double width {static_cast(upper - lower) + 1.0}; + return static_cast(width / (std::log(static_cast(lower)) - 1.1)) + 1; +} + +// Odd-only byte sieve for the primes in [167, n] with n <= 2^32 - 1 (used for n up to 65535 +// to seed the segmented generator, but correct for any n that fits memory). +inline std::vector simple_primes_from_167(std::uint32_t n) +{ + std::vector out; + if (n < 167) + { + return out; + } + std::vector composite((n / 2) + 1, 0); + for (std::uint32_t i {3}; static_cast(i) * i <= n; i += 2) + { + if (!composite[i / 2]) + { + for (std::uint64_t j {static_cast(i) * i}; j <= n; j += 2u * i) + { + composite[static_cast(j / 2)] = 1; + } + } + } + out.reserve(static_cast(prime_count_upper_bound(n))); + for (std::uint32_t i {167}; i <= n; i += 2) + { + if (!composite[i / 2]) + { + out.push_back(i); + } + } + return out; +} + +// Primes in [167, n] for n < 2^32, produced by the segmented engine itself. +inline std::vector sieving_primes_upto(std::uint64_t n) +{ + std::vector out; + if (n < 167) + { + return out; + } + if (n < 100000) + { + return simple_primes_from_167(static_cast(n)); + } + const std::uint32_t root {static_cast(BOOST_MATH_NAMESPACE::tools::isqrt(n))}; + const std::vector seed {simple_primes_from_167(root)}; + + prime_sieve_options options {}; + const sieve_geometry g {make_geometry(167, n, options)}; + extract_sink_u32 sink {out, static_cast(prime_count_upper_bound(n)) + extract_sink::slack}; + segment_sieve engine {g, seed}; + engine.run(sink); + return out; +} + +// Sieves [start, stop] (start >= 7) sequentially into sink. +template +void run_u64(std::uint64_t start, std::uint64_t stop, const prime_sieve_options& options, Sink& sink) +{ + if (stop < start) + { + sink.flush(); + return; + } + const sieve_geometry g {make_geometry(start, stop, options)}; + const std::vector primes {sieving_primes_upto(g.sqrt_stop)}; + segment_sieve engine {g, primes}; + engine.run(sink); +} + +// Counts the primes in [start, stop] (start >= 7) sequentially. +inline std::uint64_t count_u64(std::uint64_t start, std::uint64_t stop, const prime_sieve_options& options) +{ + count_sink sink {}; + run_u64(start, stop, options, sink); + return sink.count; +} + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_DRIVER_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/engine.hpp b/include/boost/math/special_functions/detail/prime_sieve/engine.hpp new file mode 100644 index 0000000000..28aae4dfd8 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/engine.hpp @@ -0,0 +1,157 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// The segmented sieve engine: iterates segments of sieve_bytes bytes over [start, stop], +// pre-sieves, feeds sieving primes lazily (a prime joins when the segment reaches p * p), +// runs the size classes, masks the range ends and hands each finished segment to a sink. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ENGINE_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ENGINE_HPP + +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +class segment_sieve +{ +public: + // sieving_primes must hold the primes in [167, sqrt(stop)] in ascending order. + segment_sieve(const sieve_geometry& geometry, const std::vector& sieving_primes) + : geo_(geometry), primes_(&sieving_primes) + { + words_.resize(geo_.sieve_bytes / 8); + reset_range(geo_.start, geo_.stop); + } + + // Prepares a new sub-range with the same geometry; the range must lie within the + // geometry's [start, stop] so that sieving primes up to sqrt(stop) suffice. + void reset_range(std::uint64_t start, std::uint64_t stop) + { + start_ = start < 7 ? 7 : start; + stop_ = stop; + next_prime_ = 0; + small_.init(stop_, geo_.l1_bytes); + medium_.init(stop_); + big_.init(stop_, geo_.sqrt_stop, geo_.sieve_bytes, geo_.has_big); + } + + template + void run(Sink& sink) + { + if (stop_ < start_) + { + return; + } + // The byte holding start_ covers offsets 7..36 above segment_low + std::uint64_t segment_low {30u * ((start_ - 7) / 30)}; + std::uint8_t* sieve {reinterpret_cast(words_.data())}; + const std::size_t sieve_bytes {geo_.sieve_bytes}; + + while (true) + { + const std::uint64_t remaining {stop_ - segment_low}; + if (remaining < 7) + { + break; + } + const std::uint64_t needed {(remaining - 7) / 30 + 1}; + const bool last {needed <= sieve_bytes}; + const std::size_t bytes {last ? static_cast(needed) : sieve_bytes}; + const std::uint64_t span {30u * static_cast(bytes) + 1}; + const std::uint64_t segment_high {span <= remaining ? segment_low + span : stop_}; + + presieve_segment(sieve, bytes, segment_low); + feed(segment_low, segment_high); + + small_.cross_off(sieve, bytes); + medium_.cross_off(sieve, bytes); + if (geo_.has_big) + { + big_.cross_off(sieve); + } + + if (segment_low < start_) + { + sieve[0] &= keep_low[static_cast(start_ - segment_low)]; + } + if (last) + { + const std::uint64_t e {stop_ - segment_low - 30u * static_cast(bytes - 1)}; + sieve[bytes - 1] &= keep_high[e > 36 ? 36 : static_cast(e)]; + } + + const std::size_t n_words {(bytes + 7) / 8}; + std::fill(sieve + bytes, sieve + n_words * 8, std::uint8_t {0}); + sink.segment(words_.data(), n_words, segment_low); + + if (last) + { + break; + } + segment_low += 30u * static_cast(sieve_bytes); + } + sink.flush(); + } + + const sieve_geometry& geometry() const noexcept + { + return geo_; + } + +private: + // Adds the sieving primes whose square lies at or below segment_high. + void feed(std::uint64_t segment_low, std::uint64_t segment_high) + { + const std::vector& primes {*primes_}; + while (next_prime_ < primes.size()) + { + const std::uint64_t p {primes[next_prime_]}; + if (p * p > segment_high) + { + break; + } + if (p <= geo_.max_small) + { + small_.add(p, segment_low); + } + else if (p <= geo_.max_medium) + { + medium_.add(p, segment_low); + } + else + { + big_.add(p, segment_low); + } + ++next_prime_; + } + } + + sieve_geometry geo_; + const std::vector* primes_; + std::vector words_; + erat_small small_; + erat_medium medium_; + erat_big big_; + std::uint64_t start_ {7}; + std::uint64_t stop_ {7}; + std::size_t next_prime_ {0}; +}; + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ENGINE_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/erat_big.hpp b/include/boost/math/special_functions/detail/prime_sieve/erat_big.hpp new file mode 100644 index 0000000000..ef28700978 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/erat_big.hpp @@ -0,0 +1,273 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Big sieving primes (at most one multiple per segment): Oliveira e Silva's bucket sieve. +// Each prime is filed in the list of the segment holding its next multiple, so a segment +// only touches the primes that actually hit it. Lists are chains of fixed 8 KiB buckets +// from a memory pool; a write pointer sitting on an 8 KiB boundary means "bucket full". +// Uses the mod 210 wheel. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ERAT_BIG_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ERAT_BIG_HPP + +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +inline constexpr std::size_t bucket_bytes {8192}; + +// Entries looked ahead in a bucket; reading past a bucket's end stays inside the 8 KiB block +// (or the following one) and is harmless. +inline constexpr std::size_t prefetch_distance {16}; + +inline void prefetch_byte(const std::uint8_t* p) noexcept +{ +#if defined(__GNUC__) || defined(__clang__) + __builtin_prefetch(p, 1, 0); +#else + (void)p; +#endif +} + +// A bucket is exactly bucket_bytes long and aligned to bucket_bytes, so the bucket owning +// a write pointer is found by masking, and a pointer that reached the next boundary is full. +struct alignas(bucket_bytes) bucket +{ + static constexpr std::size_t capacity {(bucket_bytes - 2 * sizeof(void*)) / sizeof(sieving_prime)}; + + sieving_prime* end; // one past the last used slot, valid while the bucket is processed + bucket* previous; // older bucket of the same list + sieving_prime primes[capacity]; + + static bool is_full(const sieving_prime* write) noexcept + { + // also true for nullptr, which makes an empty list allocate its first bucket + return (reinterpret_cast(write) & (bucket_bytes - 1)) == 0; + } + + static bucket* owner(const sieving_prime* write) noexcept + { + return reinterpret_cast((reinterpret_cast(write) - 1) & ~static_cast(bucket_bytes - 1)); + } +}; + +static_assert(sizeof(bucket) == bucket_bytes, "bucket must be exactly one block"); + +// Hands out aligned buckets from large blocks; freed buckets go to a free list. +class bucket_pool +{ +public: + bucket* get() + { + if (free_ == nullptr) + { + grow(); + } + bucket* b {free_}; + free_ = b->previous; + b->previous = nullptr; + return b; + } + + void put(bucket* b) noexcept + { + b->previous = free_; + free_ = b; + } + + // Returns every bucket to the free list, keeping the blocks + void release_all() noexcept + { + free_ = nullptr; + for (const block& blk : blocks_) + { + for (std::size_t i {0}; i < blk.count; ++i) + { + put(blk.first + i); + } + } + } + +private: + struct block + { + std::unique_ptr storage; + bucket* first; + std::size_t count; + }; + + void grow() + { + // 512 KiB, then doubling up to 16 MiB per block + const std::size_t count {blocks_.empty() ? std::size_t(64) : (std::min)(blocks_.back().count * 2, std::size_t(2048))}; + block blk {}; + blk.storage.reset(new std::uint8_t[(count + 2) * bucket_bytes]); // one bucket of padding for alignment, one for the look-ahead reads + const std::uintptr_t raw {reinterpret_cast(blk.storage.get())}; + const std::uintptr_t aligned {(raw + bucket_bytes - 1) & ~static_cast(bucket_bytes - 1)}; + blk.first = reinterpret_cast(aligned); + blk.count = count; + for (std::size_t i {0}; i < count; ++i) + { + put(blk.first + i); + } + blocks_.push_back(std::move(blk)); + } + + std::vector blocks_; + bucket* free_ {nullptr}; +}; + +class erat_big +{ + // Dusart's bound on pi(x), used only for sizing + static std::uint64_t prime_count_upper_bound_local(std::uint64_t x) noexcept + { + if (x < 60184) + { + return x / 8 + 64; + } + const double d {static_cast(x)}; + return static_cast(d / (std::log(d) - 1.1)) + 1; + } + +public: + void init(std::uint64_t stop, std::uint64_t max_prime, std::size_t sieve_bytes, bool enabled) + { + stop_ = stop; + enabled_ = enabled; + staged_ = 0; + pool_.release_all(); + lists_.clear(); + if (!enabled) + { + return; + } + sieve_bytes_ = sieve_bytes; + log2_sieve_bytes_ = static_cast(63 - BOOST_MATH_NAMESPACE::tools::countl_zero(sieve_bytes)); + mask_ = sieve_bytes - 1; + // Enough lists for the largest possible jump: 10 wheel steps of the largest prime + const std::size_t lists {static_cast(((max_prime / 30 + 1) * 10 + sieve_bytes) / sieve_bytes) + 2}; + lists_.assign(lists, nullptr); + head_ = 0; + staging_.reserve(static_cast((std::min)(prime_count_upper_bound_local(max_prime), std::uint64_t(1u << 20)))); + } + + // Primes are staged unconditionally and the staging index advances by the accept flag: + // for short windows at large magnitudes about half of the primes have no multiple in + // range, and a branch on that outcome mispredicts (about 3 ns per prime measured). + void add(std::uint64_t prime, std::uint64_t segment_low) + { + if (staged_ == staging_.size()) + { + staging_.resize(staged_ + 65536); + } + staged_prime& st {staging_[staged_]}; + const bool hit {first_multiple(wheel210, prime, segment_low, stop_, st.multiple_index, st.wheel_index)}; + st.prime30 = static_cast(prime / 30); + staged_ += hit ? 1u : 0u; + } + + void cross_off(std::uint8_t* sieve) + { + flush_staging(); + // A prime whose next multiple is still inside this segment is re-filed into the + // current list, so keep draining it until nothing is left. + while (lists_[head_] != nullptr) + { + sieving_prime* write {lists_[head_]}; + lists_[head_] = nullptr; + bucket* b {bucket::owner(write)}; + b->end = write; + while (b != nullptr) + { + for (const sieving_prime* sp {b->primes}; sp != b->end; ++sp) + { + // the byte touched a few entries ahead is known: hide the cache miss + prefetch_byte(sieve + sp[prefetch_distance].multiple_index()); + const auto& e = wheel210.wheel[sp->wheel_index()]; + const std::size_t i {sp->multiple_index()}; + sieve[i] &= e.unset_bit; + const std::uint64_t next {static_cast(i) + static_cast(sp->prime30) * e.next_multiple_factor + e.correct}; + sieving_prime moved {*sp}; + store(moved, next, e.next); + } + bucket* done {b}; + b = b->previous; + if (b != nullptr) + { + b->end = b->primes + bucket::capacity; + } + pool_.put(done); + } + } + head_ = head_ + 1 == lists_.size() ? 0 : head_ + 1; + } + +private: + struct staged_prime + { + std::uint64_t multiple_index; + std::uint32_t prime30; + unsigned wheel_index; + }; + + // Distributes the accepted staged primes into their lists (a predictable loop). + void flush_staging() + { + for (std::size_t i {0}; i < staged_; ++i) + { + const staged_prime& st {staging_[i]}; + sieving_prime sp {}; + sp.prime30 = st.prime30; + store(sp, st.multiple_index, st.wheel_index); + } + staged_ = 0; + } + + // Files the prime in the list of the segment (relative to the current one) that holds + // the byte index, keeping only the offset inside that segment. + void store(sieving_prime& sp, std::uint64_t multiple_index, unsigned wheel_index) + { + const std::size_t segment {static_cast(multiple_index >> log2_sieve_bytes_)}; + sp.set(static_cast(multiple_index & mask_), wheel_index); + // segment is below the list count by construction; the wrap compiles to a select + const std::size_t slot {head_ + segment}; + const std::size_t wrapped {slot >= lists_.size() ? slot - lists_.size() : slot}; + sieving_prime*& write {lists_[wrapped]}; + if (bucket::is_full(write)) + { + bucket* b {pool_.get()}; + b->previous = write == nullptr ? nullptr : bucket::owner(write); + write = b->primes; + } + *write++ = sp; + } + + std::vector lists_; + bucket_pool pool_; + std::vector staging_; + std::size_t staged_ {0}; + std::size_t head_ {0}; + std::size_t sieve_bytes_ {0}; + std::size_t mask_ {0}; + unsigned log2_sieve_bytes_ {0}; + std::uint64_t stop_ {0}; + bool enabled_ {false}; +}; + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ERAT_BIG_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/erat_medium.hpp b/include/boost/math/special_functions/detail/prime_sieve/erat_medium.hpp new file mode 100644 index 0000000000..b9a38a98fc --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/erat_medium.hpp @@ -0,0 +1,180 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Medium sieving primes (a handful of multiples per segment). Primes are kept in 64 lists +// keyed by wheel state; each list is processed by one function specialized for that state +// (Duff's device over the eight phases), so the branch predictor sees one pattern and the +// per-prime overhead is a loop iteration rather than a call. After a segment each prime is +// re-filed under its new state. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ERAT_MEDIUM_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ERAT_MEDIUM_HPP + +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +namespace medium_detail { + +using list_array = std::array, 64>; + +// Crosses off the multiples of every prime in [first, last) (all in wheel state State) over +// sieve[0, n) and files each prime, with its offset into the next segment, into next. +template +void cross_off_list(std::uint8_t* sieve, std::size_t n, const sieving_prime* first, const sieving_prime* last, list_array& next) noexcept +{ + constexpr unsigned base {(State / 8) * 8}; + constexpr const auto& w = wheel30.wheel; + + for (const sieving_prime* sp {first}; sp != last; ++sp) + { + const std::size_t p {static_cast(sp->prime30)}; + std::size_t i {sp->multiple_index()}; + unsigned state {State}; + if (i < n) + { + const std::size_t d0 {p * w[base + 0].next_multiple_factor + w[base + 0].correct}; + const std::size_t d1 {p * w[base + 1].next_multiple_factor + w[base + 1].correct}; + const std::size_t d2 {p * w[base + 2].next_multiple_factor + w[base + 2].correct}; + const std::size_t d3 {p * w[base + 3].next_multiple_factor + w[base + 3].correct}; + const std::size_t d4 {p * w[base + 4].next_multiple_factor + w[base + 4].correct}; + const std::size_t d5 {p * w[base + 5].next_multiple_factor + w[base + 5].correct}; + const std::size_t d6 {p * w[base + 6].next_multiple_factor + w[base + 6].correct}; + const std::size_t d7 {p * w[base + 7].next_multiple_factor + w[base + 7].correct}; + switch (State % 8) + { + for (;;) + { + case 0: + if (i >= n) { state = base + 0; break; } + sieve[i] &= w[base + 0].unset_bit; + i += d0; + [[fallthrough]]; + case 1: + if (i >= n) { state = base + 1; break; } + sieve[i] &= w[base + 1].unset_bit; + i += d1; + [[fallthrough]]; + case 2: + if (i >= n) { state = base + 2; break; } + sieve[i] &= w[base + 2].unset_bit; + i += d2; + [[fallthrough]]; + case 3: + if (i >= n) { state = base + 3; break; } + sieve[i] &= w[base + 3].unset_bit; + i += d3; + [[fallthrough]]; + case 4: + if (i >= n) { state = base + 4; break; } + sieve[i] &= w[base + 4].unset_bit; + i += d4; + [[fallthrough]]; + case 5: + if (i >= n) { state = base + 5; break; } + sieve[i] &= w[base + 5].unset_bit; + i += d5; + [[fallthrough]]; + case 6: + if (i >= n) { state = base + 6; break; } + sieve[i] &= w[base + 6].unset_bit; + i += d6; + [[fallthrough]]; + case 7: + if (i >= n) { state = base + 7; break; } + sieve[i] &= w[base + 7].unset_bit; + i += d7; + } + } + } + sieving_prime moved {*sp}; + moved.set(i - n, state); + next[state].push_back(moved); + } +} + +using cross_off_fn = void (*)(std::uint8_t*, std::size_t, const sieving_prime*, const sieving_prime*, list_array&) noexcept; + +// Indirection keeps the pack expansion simple enough for every front end (nvcc included) +template +constexpr cross_off_fn list_function() noexcept +{ + return &cross_off_list; +} + +template +constexpr std::array make_table(std::index_sequence) noexcept +{ + return {{list_function(I)>()...}}; +} + +inline constexpr std::array table = make_table(std::make_index_sequence<64>{}); + +} // namespace medium_detail + +class erat_medium +{ +public: + void init(std::uint64_t stop) + { + stop_ = stop; + for (auto& l : lists_) + { + l.clear(); + } + for (auto& l : next_) + { + l.clear(); + } + } + + void add(std::uint64_t prime, std::uint64_t segment_low) + { + std::uint64_t multiple_index {}; + unsigned wheel_index {}; + if (first_multiple(wheel30, prime, segment_low, stop_, multiple_index, wheel_index)) + { + sieving_prime sp {}; + sp.prime30 = static_cast(prime / 30); + sp.set(static_cast(multiple_index), wheel_index); + lists_[wheel_index].push_back(sp); + } + } + + void cross_off(std::uint8_t* sieve, std::size_t bytes) + { + for (unsigned w {0}; w < 64; ++w) + { + const std::vector& list {lists_[w]}; + if (!list.empty()) + { + medium_detail::table[w](sieve, bytes, list.data(), list.data() + list.size(), next_); + } + } + for (auto& l : lists_) + { + l.clear(); + } + lists_.swap(next_); + } + +private: + medium_detail::list_array lists_ {}; + medium_detail::list_array next_ {}; + std::uint64_t stop_ {0}; +}; + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ERAT_MEDIUM_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/erat_small.hpp b/include/boost/math/special_functions/detail/prime_sieve/erat_small.hpp new file mode 100644 index 0000000000..04d8e0a7e6 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/erat_small.hpp @@ -0,0 +1,228 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Small sieving primes (many multiples per segment). The segment is processed in L1-sized +// chunks; for each prime one full wheel turn (8 multiples, exactly p bytes) is unrolled, and +// the state is carried into the next chunk. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ERAT_SMALL_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ERAT_SMALL_HPP + +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +namespace small_detail { + +// Cumulative byte offsets, bit masks and wheel states of the eight multiples of one wheel turn +// starting at State. +struct turn_chain +{ + std::array factor {}; // multiply by p / 30 + std::array correct {}; // add + std::array mask {}; + std::array state {}; +}; + +template +constexpr turn_chain make_chain() noexcept +{ + turn_chain c {}; + unsigned s {State}; + unsigned f {0}; + unsigned k {0}; + for (unsigned j {0}; j < 8; ++j) + { + c.factor[j] = f; + c.correct[j] = k; + c.mask[j] = wheel30.wheel[s].unset_bit; + c.state[j] = s; + f += wheel30.wheel[s].next_multiple_factor; + k += wheel30.wheel[s].correct; + s = wheel30.wheel[s].next; + } + return c; +} + +// Full wheel turns of a prime in state State over sieve[i, n): eight multiples per iteration +// with one bounds check. Leaves i at the first multiple that does not have a whole turn of room. +template +BOOST_MATH_FORCEINLINE void turn_loop(std::uint8_t* sieve, std::size_t n, std::size_t& i, std::size_t p) noexcept +{ + constexpr turn_chain c {make_chain()}; + constexpr unsigned cls {State / 8}; + const std::size_t turn {30u * p + class_residue(cls)}; + const std::size_t o1 {c.factor[1] * p + c.correct[1]}; + const std::size_t o2 {c.factor[2] * p + c.correct[2]}; + const std::size_t o3 {c.factor[3] * p + c.correct[3]}; + const std::size_t o4 {c.factor[4] * p + c.correct[4]}; + const std::size_t o5 {c.factor[5] * p + c.correct[5]}; + const std::size_t o6 {c.factor[6] * p + c.correct[6]}; + const std::size_t o7 {c.factor[7] * p + c.correct[7]}; + if (n > o7) + { + const std::size_t limit {n - o7}; + std::size_t j {i}; + for (; j < limit; j += turn) + { + sieve[j] &= c.mask[0]; + sieve[j + o1] &= c.mask[1]; + sieve[j + o2] &= c.mask[2]; + sieve[j + o3] &= c.mask[3]; + sieve[j + o4] &= c.mask[4]; + sieve[j + o5] &= c.mask[5]; + sieve[j + o6] &= c.mask[6]; + sieve[j + o7] &= c.mask[7]; + } + i = j; + } +} + +// One step of the chain of class C at phase K: exits with the state when the multiple leaves +// the chunk, otherwise clears the bit and advances to the next phase. +#define BOOST_MATH_PRIME_SIEVE_STEP_BODY(C, K) \ + if (i >= n) \ + { \ + state = (C) * 8 + (K); \ + goto done; \ + } \ + sieve[i] &= wheel30.wheel[(C) * 8 + (K)].unset_bit; \ + i += p * wheel30.wheel[(C) * 8 + (K)].next_multiple_factor + wheel30.wheel[(C) * 8 + (K)].correct; + +#define BOOST_MATH_PRIME_SIEVE_STEP(C, K) \ + step_##C##_##K: \ + BOOST_MATH_PRIME_SIEVE_STEP_BODY(C, K) + +// Entry points of class C: phase 0 goes straight to the unrolled loop, other phases take +// single steps down the chain until it wraps to phase 0. +#define BOOST_MATH_PRIME_SIEVE_CASES(C) \ + case (C) * 8 + 0: goto loop_##C; \ + case (C) * 8 + 1: goto step_##C##_1; \ + case (C) * 8 + 2: goto step_##C##_2; \ + case (C) * 8 + 3: goto step_##C##_3; \ + case (C) * 8 + 4: goto step_##C##_4; \ + case (C) * 8 + 5: goto step_##C##_5; \ + case (C) * 8 + 6: goto step_##C##_6; \ + case (C) * 8 + 7: goto step_##C##_7; + +// The body of class C: whole turns from phase 0, then one chain of single steps that wraps. +// One unrolled loop per class (eight in total) keeps the function within the micro-op cache; +// a loop per state (64) measured 20 percent slower on x86. +#define BOOST_MATH_PRIME_SIEVE_CHAIN(C) \ + loop_##C: \ + turn_loop<(C) * 8>(sieve, n, i, p); \ + BOOST_MATH_PRIME_SIEVE_STEP_BODY(C, 0) \ + BOOST_MATH_PRIME_SIEVE_STEP(C, 1) \ + BOOST_MATH_PRIME_SIEVE_STEP(C, 2) \ + BOOST_MATH_PRIME_SIEVE_STEP(C, 3) \ + BOOST_MATH_PRIME_SIEVE_STEP(C, 4) \ + BOOST_MATH_PRIME_SIEVE_STEP(C, 5) \ + BOOST_MATH_PRIME_SIEVE_STEP(C, 6) \ + BOOST_MATH_PRIME_SIEVE_STEP(C, 7) \ + goto loop_##C; + +// Crosses off every prime of [first, last) over the chunk sieve[0, n) and stores each prime's +// offset into the next chunk. One function for all 64 states (the switch is a jump table). +inline void cross_off_primes(std::uint8_t* sieve, std::size_t n, sieving_prime* first, sieving_prime* last) noexcept +{ + for (sieving_prime* sp {first}; sp != last; ++sp) + { + std::size_t i {sp->multiple_index()}; + unsigned state {sp->wheel_index()}; + if (i >= n) + { + sp->set(i - n, state); + continue; + } + const std::size_t p {static_cast(sp->prime30)}; + switch (state) + { + BOOST_MATH_PRIME_SIEVE_CASES(0) + BOOST_MATH_PRIME_SIEVE_CASES(1) + BOOST_MATH_PRIME_SIEVE_CASES(2) + BOOST_MATH_PRIME_SIEVE_CASES(3) + BOOST_MATH_PRIME_SIEVE_CASES(4) + BOOST_MATH_PRIME_SIEVE_CASES(5) + BOOST_MATH_PRIME_SIEVE_CASES(6) + BOOST_MATH_PRIME_SIEVE_CASES(7) + default: goto done; + } + BOOST_MATH_PRIME_SIEVE_CHAIN(0) + BOOST_MATH_PRIME_SIEVE_CHAIN(1) + BOOST_MATH_PRIME_SIEVE_CHAIN(2) + BOOST_MATH_PRIME_SIEVE_CHAIN(3) + BOOST_MATH_PRIME_SIEVE_CHAIN(4) + BOOST_MATH_PRIME_SIEVE_CHAIN(5) + BOOST_MATH_PRIME_SIEVE_CHAIN(6) + BOOST_MATH_PRIME_SIEVE_CHAIN(7) + done: + sp->set(i - n, state); + } +} + +#undef BOOST_MATH_PRIME_SIEVE_CHAIN +#undef BOOST_MATH_PRIME_SIEVE_CASES +#undef BOOST_MATH_PRIME_SIEVE_STEP +#undef BOOST_MATH_PRIME_SIEVE_STEP_BODY + +} // namespace small_detail + +class erat_small +{ +public: + void init(std::uint64_t stop, std::size_t chunk_bytes) + { + stop_ = stop; + chunk_bytes_ = chunk_bytes; + primes_.clear(); + } + + void add(std::uint64_t prime, std::uint64_t segment_low) + { + std::uint64_t multiple_index {}; + unsigned wheel_index {}; + if (first_multiple(wheel30, prime, segment_low, stop_, multiple_index, wheel_index)) + { + sieving_prime sp {}; + sp.prime30 = static_cast(prime / 30); + sp.set(static_cast(multiple_index), wheel_index); + primes_.push_back(sp); + } + } + + void cross_off(std::uint8_t* sieve, std::size_t bytes) noexcept + { + for (std::size_t chunk {0}; chunk < bytes; chunk += chunk_bytes_) + { + const std::size_t n {(std::min)(chunk_bytes_, bytes - chunk)}; + std::uint8_t* s {sieve + chunk}; + small_detail::cross_off_primes(s, n, primes_.data(), primes_.data() + primes_.size()); + } + } + + bool empty() const noexcept + { + return primes_.empty(); + } + +private: + std::vector primes_; + std::uint64_t stop_ {0}; + std::size_t chunk_bytes_ {32768}; +}; + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_ERAT_SMALL_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/execution.hpp b/include/boost/math/special_functions/detail/prime_sieve/execution.hpp new file mode 100644 index 0000000000..0a1ad55b00 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/execution.hpp @@ -0,0 +1,118 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Execution policy plumbing: std::execution policies plus a CUDA tag, and the feature +// detection the rest of the sieve depends on (threads, std::execution, exceptions). + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_EXECUTION_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_EXECUTION_HPP + +#include + +// Threads are available unless the library configuration disabled them +#if defined(BOOST_MATH_HAS_THREADS) && !defined(BOOST_MATH_DISABLE_THREADS) +# define BOOST_MATH_PRIME_SIEVE_HAS_THREADS +#endif + +// Whether the host compiler accepts try / catch. BOOST_MATH_NO_EXCEPTIONS is not the right +// question here: it is forced on for CUDA and SYCL because device code cannot throw, while +// the host code in these headers still can. +#if defined(BOOST_NO_EXCEPTIONS) || (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_MSC_VER) && !defined(_CPPUNWIND)) +# define BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS +#endif + +// std::execution policies. Only the policy types are used, never the parallel algorithms, +// so no TBB is needed. Besides the library-wide check, accept libstdc++ 10 and later, MSVC, +// and libc++ built with -fexperimental-library (which omits the feature-test macro). +// libstdc++ 9 is excluded: its includes the TBB headers unconditionally, so it +// fails to compile when TBB is not installed (10 falls back to a serial backend). +#if defined(BOOST_MATH_EXEC_COMPATIBLE) +# define BOOST_MATH_PRIME_SIEVE_HAS_STD_EXECUTION +#elif defined(BOOST_MATH_PRIME_SIEVE_HAS_THREADS) && defined(__has_include) +# if __has_include() +# if (defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE >= 10)) || (defined(_MSC_VER) && (_MSC_VER >= 1914)) || (defined(_LIBCPP_VERSION) && defined(_LIBCPP_ENABLE_EXPERIMENTAL)) +# define BOOST_MATH_PRIME_SIEVE_HAS_STD_EXECUTION +# endif +# endif +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#ifdef BOOST_MATH_PRIME_SIEVE_HAS_STD_EXECUTION +#include +#endif +#endif + +BOOST_MATH_NAMESPACE_BEGIN + +namespace execution { + +// Requests the CUDA backend; falls back to the CPU when the translation unit is not +// compiled with nvcc and BOOST_MATH_ENABLE_CUDA (test BOOST_MATH_HAS_CUDA_PRIME_SIEVE). +BOOST_MATH_EXPORT struct cuda_policy +{ +}; + +BOOST_MATH_EXPORT inline constexpr cuda_policy cuda {}; + +} // namespace execution + +namespace detail::prime_sieve { + +enum class exec_mode +{ + sequential, + parallel, + cuda +}; + +template +inline constexpr bool is_cuda_policy_v = std::is_same::value; + +#ifdef BOOST_MATH_PRIME_SIEVE_HAS_STD_EXECUTION +template +inline constexpr bool is_std_policy_v = std::is_execution_policy::value; +#else +template +inline constexpr bool is_std_policy_v = false; +#endif + +template +inline constexpr bool is_execution_policy_v = is_cuda_policy_v || is_std_policy_v; + +template +constexpr exec_mode mode_of() noexcept +{ + if constexpr (is_cuda_policy_v) + { + return exec_mode::cuda; + } +#ifdef BOOST_MATH_PRIME_SIEVE_HAS_STD_EXECUTION + else if constexpr (std::is_same::value) + { + return exec_mode::sequential; + } +#if defined(__cpp_lib_execution) && (__cpp_lib_execution >= 201902L) + else if constexpr (std::is_same::value) + { + return exec_mode::sequential; + } +#endif + else + { + return exec_mode::parallel; + } +#else + else + { + return exec_mode::sequential; + } +#endif +} + +} // namespace detail::prime_sieve +BOOST_MATH_NAMESPACE_END + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_EXECUTION_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/integer_traits.hpp b/include/boost/math/special_functions/detail/prime_sieve/integer_traits.hpp new file mode 100644 index 0000000000..4215085f89 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/integer_traits.hpp @@ -0,0 +1,83 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Traits that let the sieve accept builtin integers and Boost.Multiprecision integers +// without including Boost.Multiprecision. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_INTEGER_TRAITS_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_INTEGER_TRAITS_HPP + +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +template +inline constexpr bool is_multiprecision_v = BOOST_MATH_NAMESPACE::tools::detail::has_backend_type::value; + +template +inline constexpr bool is_integer_like_v = std::is_integral::value || (std::numeric_limits::is_specialized && std::numeric_limits::is_integer); + +// Common type of two bounds: the usual promotion for builtins, otherwise the class type. +template +using common_integer_t = std::conditional_t::value && std::is_integral::value, + std::common_type_t, + std::conditional_t::value, Upper, Lower>>; + +// True when the non-negative value x fits in 64 bits. +template +inline bool fits_u64(const Integer& x) +{ + if constexpr (std::is_integral::value) + { + (void)x; + return true; + } + else + { + return x <= Integer((std::numeric_limits::max)()); + } +} + +template +inline std::uint64_t to_u64(const Integer& x) +{ + return static_cast(x); +} + +template +inline Integer from_u64(std::uint64_t x) +{ + return static_cast(x); +} + +// Clamps negative inputs of signed types to zero. +template +inline Integer clamp_non_negative(const Integer& x) +{ + if constexpr (std::is_integral::value && std::is_unsigned::value) + { + return x; + } + else + { + return x < Integer(0) ? Integer(0) : x; + } +} +template +inline Integer to_common(const Bound& x) +{ + return Integer(clamp_non_negative(x)); +} + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_INTEGER_TRAITS_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/layout.hpp b/include/boost/math/special_functions/detail/prime_sieve/layout.hpp new file mode 100644 index 0000000000..f5fa930315 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/layout.hpp @@ -0,0 +1,364 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Bit layout of the sieve array and the wheel tables shared by every backend. +// +// One byte represents 30 consecutive integers: bit k of byte i is the integer +// segment_low + 30 * i + wheel_offsets[k] with wheel_offsets = {7, 11, 13, 17, 19, 23, 29, 31}. +// segment_low is always a multiple of 30 and the first byte of a range starting at s is the +// one holding s, i.e. segment_low = 30 * ((s - 7) / 30). Multiples of 2, 3 and 5 have no bit. +// +// A sieving prime p = 30 * p30 + r advances through its multiples p * q where q runs over the +// residues coprime to the wheel modulus. The wheel tables give, per (residue class of p, +// residue class of q), the bit to clear, the distance to the next q, and the byte correction. +// +// The tables are host objects; the CUDA backend copies what it needs into a kernel argument. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_LAYOUT_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_LAYOUT_HPP + +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +// Prime extraction with AVX-512 byte compression (Ice Lake and later, or Zen 4), selected at +// compile time; define BOOST_MATH_PRIME_SIEVE_NO_SIMD to force the portable loop. +#if defined(__AVX512F__) && defined(__AVX512VBMI__) && defined(__AVX512VBMI2__) && !defined(__CUDACC__) && !defined(BOOST_MATH_PRIME_SIEVE_NO_SIMD) +# define BOOST_MATH_PRIME_SIEVE_AVX512_EXTRACT +# ifndef BOOST_MATH_BUILD_MODULE +# include +# endif +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +inline constexpr std::uint8_t wheel_offsets[8] = {7, 11, 13, 17, 19, 23, 29, 31}; +inline constexpr std::uint8_t unset_bit[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; + +// Bit index of a residue modulo 30 that is coprime to 30, or 0xff otherwise. +// The same mapping orders the residue classes of the sieving primes. +BOOST_MATH_GPU_ENABLED constexpr std::uint8_t bit_of_residue(unsigned r) noexcept +{ + return r == 7 ? 0 : r == 11 ? 1 : r == 13 ? 2 : r == 17 ? 3 : r == 19 ? 4 : r == 23 ? 5 : r == 29 ? 6 : r == 1 ? 7 : 0xff; +} + +// Residue modulo 30 of the sieving primes in class c. +BOOST_MATH_GPU_ENABLED constexpr unsigned class_residue(unsigned c) noexcept +{ + return c == 7 ? 1u : wheel_offsets[c]; +} + +namespace layout_detail { + +constexpr std::array make_bit_values() noexcept +{ + std::array a {}; + for (std::size_t b {0}; b < 64; ++b) + { + a[b] = static_cast(30 * (b / 8) + wheel_offsets[b % 8]); + } + a[64] = 0; + return a; +} + +// keep_low[d]: bits of the first byte whose offset is >= d (d = start - segment_low in [7, 36]) +constexpr std::array make_keep_low() noexcept +{ + std::array a {}; + for (unsigned d {0}; d < 37; ++d) + { + std::uint8_t m {0}; + for (unsigned k {0}; k < 8; ++k) + { + if (wheel_offsets[k] >= d) + { + m = static_cast(m | (1u << k)); + } + } + a[d] = m; + } + return a; +} + +// keep_high[e]: bits of the last byte whose offset is <= e (e = stop - byte_base in [0, 36]) +constexpr std::array make_keep_high() noexcept +{ + std::array a {}; + for (unsigned e {0}; e < 37; ++e) + { + std::uint8_t m {0}; + for (unsigned k {0}; k < 8; ++k) + { + if (wheel_offsets[k] <= e) + { + m = static_cast(m | (1u << k)); + } + } + a[e] = m; + } + return a; +} + +constexpr unsigned gcd_u(unsigned a, unsigned b) noexcept +{ + while (b != 0) + { + const unsigned t {a % b}; + a = b; + b = t; + } + return a; +} + +} // namespace layout_detail + +// Offset within a 64-bit word (240 integers) of each bit; entry 64 absorbs countr_zero(0). +inline constexpr std::array bit_values = layout_detail::make_bit_values(); +inline constexpr std::array keep_low = layout_detail::make_keep_low(); +inline constexpr std::array keep_high = layout_detail::make_keep_high(); + +// Wheel tables for a modulus with Size residues coprime to it (30/8 or 210/48). +template +struct wheel_tables +{ + struct init_entry + { + std::uint8_t next_multiple_factor; // distance from q to the next coprime multiplier + std::uint8_t wheel_index; // phase of that multiplier + }; + + struct element + { + std::uint8_t unset_bit; // mask clearing the bit of p * q + std::uint8_t next_multiple_factor; // multiplier increment to the next coprime q + std::uint8_t correct; // byte correction beyond factor * (p / 30) + std::uint16_t next; // following state + }; + + static constexpr unsigned modulo {Modulo}; + static constexpr unsigned size {Size}; + static constexpr unsigned states {8 * Size}; + + std::array residues {}; + std::array init {}; + std::array wheel {}; +}; + +template +constexpr wheel_tables make_wheel_tables() noexcept +{ + wheel_tables t {}; + + unsigned n {0}; + for (unsigned r {0}; r < Modulo; ++r) + { + if (layout_detail::gcd_u(r, Modulo) == 1) + { + t.residues[n++] = static_cast(r); + } + } + + for (unsigned x {0}; x < Modulo; ++x) + { + unsigned y {x}; + unsigned distance {0}; + while (layout_detail::gcd_u(y % Modulo, Modulo) != 1) + { + ++y; + ++distance; + } + unsigned phase {0}; + while (t.residues[phase] != y % Modulo) + { + ++phase; + } + t.init[x].next_multiple_factor = static_cast(distance); + t.init[x].wheel_index = static_cast(phase); + } + + for (unsigned c {0}; c < 8; ++c) + { + const unsigned rp {class_residue(c)}; + for (unsigned i {0}; i < Size; ++i) + { + const unsigned rq {t.residues[i]}; + const unsigned product {(rp * rq) % 30}; + const unsigned bit {bit_of_residue(product)}; + const unsigned i_next {(i + 1) % Size}; + const unsigned factor {(t.residues[i_next] + Modulo - t.residues[i]) % Modulo}; + const unsigned correct {(wheel_offsets[bit] - 6u + factor * rp) / 30u}; + + auto& e = t.wheel[c * Size + i]; + e.unset_bit = unset_bit[bit]; + e.next_multiple_factor = static_cast(factor); + e.correct = static_cast(correct); + e.next = static_cast(c * Size + i_next); + } + } + return t; +} + +using wheel30_t = wheel_tables<30, 8>; +using wheel210_t = wheel_tables<210, 48>; + +inline constexpr wheel30_t wheel30 = make_wheel_tables<30, 8>(); +inline constexpr wheel210_t wheel210 = make_wheel_tables<210, 48>(); + +// Packed sieving prime: 23 bits of byte index, 9 bits of wheel state, and p / 30. +struct sieving_prime +{ + static constexpr std::uint32_t max_multiple_index {(1u << 23) - 1}; + + std::uint32_t indexes; + std::uint32_t prime30; + + constexpr std::size_t multiple_index() const noexcept + { + return indexes & max_multiple_index; + } + + constexpr unsigned wheel_index() const noexcept + { + return indexes >> 23; + } + + constexpr void set(std::size_t multiple_index, unsigned wheel_index) noexcept + { + indexes = static_cast(multiple_index) | (static_cast(wheel_index) << 23); + } +}; + +// Computes the byte index (relative to segment_low) and wheel state of the first multiple of +// prime that is at least max(prime * prime, segment_low + 7) and coprime to the wheel modulus. +// Returns false when no such multiple is <= stop; the outputs are then meaningless. +// Host only: device code uses its own copy of the tables (see cuda.hpp). +template +inline bool first_multiple(const Tables& t, std::uint64_t prime, std::uint64_t segment_low, + std::uint64_t stop, std::uint64_t& multiple_index, unsigned& wheel_index) noexcept +{ + // Offsets 7..31 shifted by 6 divide cleanly into bytes 0.. + // Written without early returns: for short windows at large magnitudes about half of the + // primes have no multiple in range and a data-dependent branch here would mispredict. + const std::uint64_t low6 {segment_low + 6}; + std::uint64_t q {low6 / prime + 1}; + q = q < prime ? prime : q; + // prime * q lies in (low6, low6 + prime] or equals prime * prime (< 2^64), so a wrapped + // product is below low6: one comparison replaces a second 64-bit division + const std::uint64_t multiple {prime * q}; + const bool in_range {static_cast(static_cast(multiple >= low6) & static_cast(multiple <= stop))}; + const auto e = t.init[q % Tables::modulo]; + const std::uint64_t advance {prime * e.next_multiple_factor}; + const bool fits {static_cast(static_cast(in_range) & static_cast(advance <= stop - multiple))}; + multiple_index = (multiple + advance - low6) / 30; + wheel_index = bit_of_residue(static_cast(prime % 30)) * Tables::size + e.wheel_index; + return fits; +} + +#ifdef BOOST_MATH_PRIME_SIEVE_AVX512_EXTRACT + +// Writes the integers whose bits are set in word (base value low) to out and returns how many. +// The 64 byte offsets are compressed by the bit mask so the set bits' offsets become the first +// count bytes; each group of eight is then spread into 64-bit lanes and added to the base. +// Writes whole groups of eight, so out needs 7 slots of slack beyond the count. +inline std::size_t extract_word(std::uint64_t word, std::uint64_t low, std::uint64_t* out) noexcept +{ + const std::size_t count {static_cast(BOOST_MATH_NAMESPACE::tools::popcount(word))}; + if (count == 0) + { + return 0; + } + const __m512i offsets {_mm512_loadu_si512(bit_values.data())}; + const __m512i compressed {_mm512_maskz_compress_epi8(static_cast<__mmask64>(word), offsets)}; + const __m512i base {_mm512_set1_epi64(static_cast(low))}; + __m512i index {_mm512_set_epi64(7, 6, 5, 4, 3, 2, 1, 0)}; + const __m512i eight {_mm512_set1_epi64(8)}; + for (std::size_t j {0}; j < count; j += 8) + { + // byte 0 of each 64-bit lane receives compressed[8 * group + lane] + const __m512i values {_mm512_maskz_permutexvar_epi8(static_cast<__mmask64>(0x0101010101010101ULL), index, compressed)}; + _mm512_storeu_si512(out + j, _mm512_add_epi64(values, base)); + index = _mm512_add_epi64(index, eight); + } + return count; +} + +// Same for 32-bit outputs: sixteen values per group, so 15 slots of slack are needed. +inline std::size_t extract_word_u32(std::uint64_t word, std::uint64_t low, std::uint32_t* out) noexcept +{ + const std::size_t count {static_cast(BOOST_MATH_NAMESPACE::tools::popcount(word))}; + if (count == 0) + { + return 0; + } + const __m512i offsets {_mm512_loadu_si512(bit_values.data())}; + const __m512i compressed {_mm512_maskz_compress_epi8(static_cast<__mmask64>(word), offsets)}; + const __m512i base {_mm512_set1_epi32(static_cast(static_cast(low)))}; + __m512i index {_mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)}; + const __m512i sixteen {_mm512_set1_epi32(16)}; + for (std::size_t j {0}; j < count; j += 16) + { + const __m512i values {_mm512_maskz_permutexvar_epi8(static_cast<__mmask64>(0x1111111111111111ULL), index, compressed)}; + _mm512_storeu_si512(out + j, _mm512_add_epi32(values, base)); + index = _mm512_add_epi32(index, sixteen); + } + return count; +} + +#else + +// Writes the integers whose bits are set in word (base value low) to out and returns how many. +// Writes four values per iteration unconditionally, so out needs 3 slots of slack beyond +// the count (64 bits at most, so 67 slots always suffice). +inline std::size_t extract_word(std::uint64_t word, std::uint64_t low, std::uint64_t* out) noexcept +{ + const std::size_t count {static_cast(BOOST_MATH_NAMESPACE::tools::popcount(word))}; + std::size_t j {0}; + while (j < count) + { + out[j] = low + bit_values[BOOST_MATH_NAMESPACE::tools::countr_zero(word)]; + word &= word - 1; + out[j + 1] = low + bit_values[BOOST_MATH_NAMESPACE::tools::countr_zero(word)]; + word &= word - 1; + out[j + 2] = low + bit_values[BOOST_MATH_NAMESPACE::tools::countr_zero(word)]; + word &= word - 1; + out[j + 3] = low + bit_values[BOOST_MATH_NAMESPACE::tools::countr_zero(word)]; + word &= word - 1; + j += 4; + } + return count; +} + +// Same as extract_word for values known to fit 32 bits (sieving primes). +inline std::size_t extract_word_u32(std::uint64_t word, std::uint64_t low, std::uint32_t* out) noexcept +{ + const std::size_t count {static_cast(BOOST_MATH_NAMESPACE::tools::popcount(word))}; + const std::uint32_t base {static_cast(low)}; + std::size_t j {0}; + while (j < count) + { + out[j] = base + bit_values[BOOST_MATH_NAMESPACE::tools::countr_zero(word)]; + word &= word - 1; + out[j + 1] = base + bit_values[BOOST_MATH_NAMESPACE::tools::countr_zero(word)]; + word &= word - 1; + out[j + 2] = base + bit_values[BOOST_MATH_NAMESPACE::tools::countr_zero(word)]; + word &= word - 1; + out[j + 3] = base + bit_values[BOOST_MATH_NAMESPACE::tools::countr_zero(word)]; + word &= word - 1; + j += 4; + } + return count; +} + +#endif // BOOST_MATH_PRIME_SIEVE_AVX512_EXTRACT + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_LAYOUT_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/options.hpp b/include/boost/math/special_functions/detail/prime_sieve/options.hpp new file mode 100644 index 0000000000..240bb016a4 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/options.hpp @@ -0,0 +1,137 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// User-facing tuning options and the derived segment geometry. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_OPTIONS_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_OPTIONS_HPP + +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN + +// Strategy for ranges that fit in 64 bits: sieve to sqrt(upper) or test survivors of a +// shallow sieve individually (better for short intervals at large magnitudes). +BOOST_MATH_EXPORT enum class prime_range_strategy +{ + automatic, + full_sieve, + test_survivors +}; + +BOOST_MATH_EXPORT struct prime_sieve_options +{ + std::size_t l1d_bytes {0}; // 0 = detect + std::size_t l2_bytes {0}; // 0 = detect (per core) + std::size_t sieve_bytes {0}; // 0 = derive from sqrt(upper) and the caches; clamped to [16 KiB, 8 MiB] + unsigned max_threads {0}; // 0 = std::thread::hardware_concurrency() + std::size_t chunk_primes {1u << 19}; // target primes per parallel chunk when storing output + prime_range_strategy range_strategy {prime_range_strategy::automatic}; + bool probable_prime_only {false}; // beyond 2^64: skip the deterministic pseudosquares test +}; + +namespace detail::prime_sieve { + +inline constexpr std::size_t min_sieve_bytes {16u * 1024u}; +inline constexpr std::size_t max_sieve_bytes {8u * 1024u * 1024u}; // 23-bit multiple index +inline constexpr double factor_small {0.2}; +inline constexpr double factor_medium {3.0}; +inline constexpr double factor_sieve_size {2.0}; + +struct sieve_geometry +{ + std::uint64_t start {7}; // >= 7 + std::uint64_t stop {7}; // inclusive + std::uint64_t sqrt_stop {2}; + std::size_t sieve_bytes {min_sieve_bytes}; // multiple of 8, power of two when big primes exist + std::size_t l1_bytes {32768}; // erat_small chunk + std::uint64_t max_small {0}; // primes <= max_small go to erat_small + std::uint64_t max_medium {0}; // primes <= max_medium go to erat_medium, larger to erat_big + bool has_big {false}; +}; + +inline std::size_t round_down_multiple(std::size_t value, std::size_t unit) noexcept +{ + return unit == 0 ? value : (value / unit) * unit; +} + +inline sieve_geometry make_geometry(std::uint64_t start, std::uint64_t stop, const prime_sieve_options& options) noexcept +{ + sieve_geometry g {}; + g.start = start < 7 ? 7 : start; + g.stop = stop; + g.sqrt_stop = BOOST_MATH_NAMESPACE::tools::isqrt(stop); + + const cache_info& cache {cached_cache_info()}; + const std::size_t l1 {options.l1d_bytes != 0 ? options.l1d_bytes : cache.l1d_bytes}; + const std::size_t l2 {options.l2_bytes != 0 ? options.l2_bytes : cache.l2_bytes}; + + std::size_t sieve_bytes {}; + if (options.sieve_bytes != 0) + { + sieve_bytes = options.sieve_bytes; + } + else + { + // Scale with sqrt(stop) so that medium primes have several multiples per segment + const double wanted {factor_sieve_size * static_cast(g.sqrt_stop)}; + sieve_bytes = wanted > static_cast(max_sieve_bytes) ? max_sieve_bytes : static_cast(wanted); + if (sieve_bytes > l1) + { + sieve_bytes = round_down_multiple(sieve_bytes, l1); + } + // Keep the segment inside the per-core L2 and within 16 L1 sizes + std::size_t cap {static_cast(BOOST_MATH_NAMESPACE::tools::floor_pow2(l2))}; + cap = (std::min)(cap, 16 * l1); + cap = (std::max)(cap, l1); + sieve_bytes = (std::max)(sieve_bytes, l1); + sieve_bytes = (std::min)(sieve_bytes, cap); + } + sieve_bytes = (std::max)(sieve_bytes, min_sieve_bytes); + sieve_bytes = (std::min)(sieve_bytes, max_sieve_bytes); + + // A range that fits in one segment does not need more memory than that, but the segment + // must stay large enough that no prime falls into the big class if it can be avoided + if (stop - g.start < 30u * static_cast(sieve_bytes)) + { + std::size_t shrunk {static_cast((stop - g.start) / 30 + 2)}; + const std::size_t no_big {static_cast(static_cast(g.sqrt_stop) / factor_medium) + 1}; + shrunk = (std::max)(shrunk, no_big); + sieve_bytes = (std::min)(sieve_bytes, shrunk); + sieve_bytes = (std::max)(sieve_bytes, std::size_t(8)); + } + sieve_bytes = (sieve_bytes + 7) / 8 * 8; + + // Big primes need a power-of-two segment for cheap bucket indexing. The bucket sieve + // is not cache bound, and the largest segment measured fastest, so use the maximum + // unless the caller fixed the size. + if (static_cast(g.sqrt_stop) > factor_medium * static_cast(sieve_bytes)) + { + sieve_bytes = options.sieve_bytes != 0 ? static_cast(BOOST_MATH_NAMESPACE::tools::floor_pow2(sieve_bytes)) : max_sieve_bytes; + sieve_bytes = (std::max)(sieve_bytes, min_sieve_bytes); + } + + g.sieve_bytes = sieve_bytes; + g.l1_bytes = (std::min)(l1, sieve_bytes); + g.max_small = static_cast(factor_small * static_cast(g.l1_bytes)); + g.max_medium = static_cast(factor_medium * static_cast(sieve_bytes)); + g.max_small = (std::min)(g.max_small, g.sqrt_stop); + g.max_medium = (std::min)(g.max_medium, g.sqrt_stop); + g.has_big = g.sqrt_stop > g.max_medium; + return g; +} + +} // namespace detail::prime_sieve +BOOST_MATH_NAMESPACE_END + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_OPTIONS_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/parallel.hpp b/include/boost/math/special_functions/detail/prime_sieve/parallel.hpp new file mode 100644 index 0000000000..a4176c4dfa --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/parallel.hpp @@ -0,0 +1,409 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Multithreaded driver: the range is cut into chunks of about 200 * sqrt(stop) that are +// handed out dynamically through an atomic counter; each worker owns a segment_sieve and +// shares the read-only sieving primes. Output chunks are committed in order through a +// bounded queue so the caller sees ascending primes without padding. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_PARALLEL_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_PARALLEL_HPP + +#include +#include + +#ifdef BOOST_MATH_PRIME_SIEVE_HAS_THREADS + +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +inline constexpr std::uint64_t min_chunk_width {10000000}; + +inline std::vector sieving_primes_upto_parallel(std::uint64_t n, const prime_sieve_options& options); + +struct chunk_plan +{ + std::uint64_t start {0}; + std::uint64_t stop {0}; + std::uint64_t chunk {0}; // width in integers, multiple of 30 + std::uint64_t iters {1}; + unsigned threads {1}; +}; + +inline unsigned worker_count(const prime_sieve_options& options) noexcept +{ + if (options.max_threads != 0) + { + return options.max_threads; + } + const unsigned hw {std::thread::hardware_concurrency()}; + return hw == 0 ? 2u : hw; +} + +// primesieve's balancing: chunks of at most 200 * sqrt(stop) so the O(pi(sqrt stop)) setup +// per chunk stays below one percent, an iteration count that is a multiple of the thread +// count, and a floor of 1e7 integers per chunk. +inline chunk_plan plan_chunks(std::uint64_t start, std::uint64_t stop, const prime_sieve_options& options, bool extracting) noexcept +{ + chunk_plan plan {}; + plan.start = start; + plan.stop = stop; + const std::uint64_t dist {stop - start + 1}; + const unsigned hw {worker_count(options)}; + const std::uint64_t root {BOOST_MATH_NAMESPACE::tools::isqrt(stop)}; + const std::uint64_t threshold {(std::max)(root / 5, min_chunk_width)}; + std::uint64_t threads {dist / threshold}; + threads = (std::max)(threads, std::uint64_t(1)); + threads = (std::min)(threads, static_cast(hw)); + if (threads <= 1) + { + plan.chunk = dist; + plan.iters = 1; + plan.threads = 1; + return plan; + } + + std::uint64_t chunk {(std::min)(200 * root, dist / threads)}; + if (extracting) + { + // Keep one chunk's worth of primes near chunk_primes entries + const double per_chunk {static_cast(options.chunk_primes) * std::log(static_cast(stop))}; + if (per_chunk < static_cast(chunk)) + { + chunk = static_cast(per_chunk); + } + } + chunk = (std::max)(chunk, min_chunk_width); + std::uint64_t iters {dist / chunk}; + iters = (iters / threads) * threads; + iters = (std::max)(iters, threads); + chunk = (dist - 1) / iters + 1; + chunk = (std::max)(chunk, min_chunk_width); + chunk += 30 - chunk % 30; + iters = (dist - 1) / chunk + 1; + + plan.chunk = chunk; + plan.iters = iters; + plan.threads = static_cast((std::min)(threads, iters)); + return plan; +} + +// Bounds of chunk i, inclusive. +inline void chunk_bounds(const chunk_plan& plan, std::uint64_t i, std::uint64_t& lo, std::uint64_t& hi) noexcept +{ + lo = plan.start + i * plan.chunk; + const std::uint64_t remaining {plan.stop - lo}; + hi = remaining < plan.chunk ? plan.stop : lo + plan.chunk - 1; +} + +// Counts the primes in [start, stop] (start >= 7) on several threads. +inline std::uint64_t parallel_count(std::uint64_t start, std::uint64_t stop, const prime_sieve_options& options) +{ + if (stop < start) + { + return 0; + } + const chunk_plan plan {plan_chunks(start, stop, options, false)}; + const sieve_geometry g {make_geometry(start, stop, options)}; + const std::vector primes {sieving_primes_upto_parallel(g.sqrt_stop, options)}; + if (plan.threads <= 1) + { + // Too narrow to split, but the sieving primes above were still generated in parallel + segment_sieve engine {g, primes}; + count_sink sink {}; + engine.run(sink); + return sink.count; + } + + alignas(64) std::atomic next {0}; + + auto worker = [&]() -> std::uint64_t + { + segment_sieve engine {g, primes}; + count_sink sink {}; + std::uint64_t i {}; + while ((i = next.fetch_add(1, std::memory_order_relaxed)) < plan.iters) + { + std::uint64_t lo {}; + std::uint64_t hi {}; + chunk_bounds(plan, i, lo, hi); + engine.reset_range(lo, hi); + engine.run(sink); + } + return sink.count; + }; + + std::vector> futures; + futures.reserve(plan.threads); + for (unsigned t {0}; t < plan.threads; ++t) + { +#ifndef BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS + try +#endif + { + futures.push_back(std::async(std::launch::async, worker)); + } +#ifndef BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS + catch (const std::system_error&) + { + break; + } +#endif + } + // Any chunks left over (thread creation failed) are processed here + std::uint64_t total {worker()}; + for (auto& f : futures) + { + total += f.get(); + } + return total; +} + +// In-order hand-off of per-chunk prime buffers from workers to the consuming thread. +class ordered_chunk_queue +{ +public: + explicit ordered_chunk_queue(std::size_t capacity) : slots_(capacity), ready_(capacity, false) + { + } + + // Returns the empty buffer for chunk i once the chunk that previously used the slot is drained. + std::vector& acquire(std::uint64_t i) + { + std::unique_lock lock {mutex_}; + free_.wait(lock, [&] { return failed_ || i < next_ + slots_.size(); }); + return slots_[static_cast(i % slots_.size())]; + } + + void publish(std::uint64_t i) + { + { + std::lock_guard lock {mutex_}; + ready_[static_cast(i % slots_.size())] = true; + } + ready_cv_.notify_all(); + } + + void fail(std::exception_ptr e) + { + { + std::lock_guard lock {mutex_}; + if (!failed_) + { + failed_ = true; + error_ = e; + } + } + ready_cv_.notify_all(); + free_.notify_all(); + } + + bool failed() const + { + std::lock_guard lock {mutex_}; + return failed_; + } + + // Blocks until chunk i is published; returns nullptr when a worker failed. + std::vector* wait_ready(std::uint64_t i) + { + std::unique_lock lock {mutex_}; + ready_cv_.wait(lock, [&] { return failed_ || ready_[static_cast(i % slots_.size())]; }); + if (failed_) + { + return nullptr; + } + return &slots_[static_cast(i % slots_.size())]; + } + + void release(std::uint64_t i) + { + { + std::lock_guard lock {mutex_}; + const std::size_t s {static_cast(i % slots_.size())}; + ready_[s] = false; + slots_[s].clear(); + next_ = i + 1; + } + free_.notify_all(); + } + + void rethrow() + { + std::exception_ptr e {}; + { + std::lock_guard lock {mutex_}; + e = error_; + } + if (e) + { + std::rethrow_exception(e); + } + } + +private: + mutable std::mutex mutex_; + std::condition_variable ready_cv_; + std::condition_variable free_; + std::vector> slots_; + std::vector ready_; + std::uint64_t next_ {0}; + bool failed_ {false}; + std::exception_ptr error_ {}; +}; + +// Sieves [start, stop] (start >= 7) on several threads and passes the primes in ascending +// order to consume(const std::uint64_t*, std::size_t) on the calling thread. +template +void parallel_range(std::uint64_t start, std::uint64_t stop, const prime_sieve_options& options, Consumer& consume) +{ + if (stop < start) + { + return; + } + const chunk_plan plan {plan_chunks(start, stop, options, true)}; + const sieve_geometry g {make_geometry(start, stop, options)}; + const std::vector primes {sieving_primes_upto_parallel(g.sqrt_stop, options)}; + if (plan.threads <= 1) + { + segment_sieve engine {g, primes}; + extract_sink sink {consume}; + engine.run(sink); + return; + } + + alignas(64) std::atomic next {0}; + ordered_chunk_queue queue {2 * static_cast(plan.threads)}; + + auto worker = [&]() + { +#ifndef BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS + try +#endif + { + segment_sieve engine {g, primes}; + std::uint64_t i {}; + while ((i = next.fetch_add(1, std::memory_order_relaxed)) < plan.iters) + { + std::uint64_t lo {}; + std::uint64_t hi {}; + chunk_bounds(plan, i, lo, hi); + std::vector& buffer {queue.acquire(i)}; + if (queue.failed()) + { + return; + } + buffer.reserve(static_cast(prime_count_upper_bound(lo, hi))); + append_u64 appender {buffer}; + extract_sink sink {appender}; + engine.reset_range(lo, hi); + engine.run(sink); + queue.publish(i); + } + } +#ifndef BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS + catch (...) + { + queue.fail(std::current_exception()); + } +#endif + }; + + std::vector> futures; + futures.reserve(plan.threads); + for (unsigned t {0}; t < plan.threads; ++t) + { +#ifndef BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS + try +#endif + { + futures.push_back(std::async(std::launch::async, worker)); + } +#ifndef BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS + catch (const std::system_error&) + { + break; + } +#endif + } + if (futures.empty()) + { + // No worker could be started: fall back to the sequential path + extract_sink sink {consume}; + run_u64(start, stop, options, sink); + return; + } + +#ifndef BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS + try +#endif + { + for (std::uint64_t i {0}; i < plan.iters; ++i) + { + std::vector* buffer {queue.wait_ready(i)}; + if (buffer == nullptr) + { + break; + } + consume(buffer->data(), buffer->size()); + queue.release(i); + } + } +#ifndef BOOST_MATH_PRIME_SIEVE_NO_EXCEPTIONS + catch (...) + { + // The consumer threw: release the workers blocked on the full queue before waiting + // on the futures, whose destructors would otherwise block forever. + queue.fail(std::current_exception()); + for (auto& f : futures) + { + f.wait(); + } + throw; + } +#endif + for (auto& f : futures) + { + f.wait(); + } + queue.rethrow(); +} + +// Sieving primes in [167, n] generated on several threads when there are many of them. +inline std::vector sieving_primes_upto_parallel(std::uint64_t n, const prime_sieve_options& options) +{ + if (n < 100000000) + { + return sieving_primes_upto(n); + } + std::vector out; + out.reserve(static_cast(prime_count_upper_bound(n))); + append_u32 appender {out}; + parallel_range(167, n, options, appender); + return out; +} + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_PRIME_SIEVE_HAS_THREADS +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_PARALLEL_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/presieve.hpp b/include/boost/math/special_functions/detail/prime_sieve/presieve.hpp new file mode 100644 index 0000000000..218db76a6d --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/presieve.hpp @@ -0,0 +1,268 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Pre-sieving: multiples of the primes 7..163 are removed by ANDing periodic byte patterns +// into each segment instead of crossing them off one by one. The 16 patterns (products of +// two or three primes, 6 to 10 KB each) are generated on first use. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_PRESIEVE_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_PRESIEVE_HPP + +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +inline constexpr unsigned presieve_max_prime {163}; +inline constexpr std::size_t presieve_table_count {16}; + +// The 35 primes handled by pre-sieving, 7..163. +inline constexpr std::uint8_t presieve_primes[35] = +{ + 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163 +}; + +// Groups whose products give tables of 6 to 10 KB each. +inline constexpr std::uint8_t presieve_groups[presieve_table_count][3] = +{ + {7, 23, 37}, {11, 19, 31}, {13, 17, 29}, {41, 163, 0}, {43, 157, 0}, {47, 151, 0}, {53, 149, 0}, {59, 139, 0}, + {61, 137, 0}, {67, 131, 0}, {71, 127, 0}, {73, 113, 0}, {79, 109, 0}, {83, 107, 0}, {89, 103, 0}, {97, 101, 0} +}; + +// Crosses the multiples of p off a pattern of period bytes covering the integers +// [0, 30 * period + 1]. Usable at compile time. +constexpr void presieve_mark(std::uint8_t* pattern, std::size_t period, std::uint64_t p) noexcept +{ + constexpr std::uint8_t residues[8] = {1, 7, 11, 13, 17, 19, 23, 29}; + const std::uint64_t limit {30 * static_cast(period) + 1}; + for (std::uint64_t base {0}; ; base += 30) + { + for (unsigned k {0}; k < 8; ++k) + { + const std::uint64_t n {p * (base + residues[k])}; + if (n > limit) + { + return; + } + pattern[static_cast((n - 7) / 30)] = static_cast(pattern[(n - 7) / 30] & unset_bit[bit_of_residue(static_cast(n % 30))]); + } + } +} + +template +struct presieve_pattern +{ + std::uint8_t bytes[Period]; +}; + +// The pattern for one group of primes; the third prime may be 1 (absent). +template +constexpr presieve_pattern make_presieve_pattern() noexcept +{ + presieve_pattern t {}; + for (std::size_t i {0}; i < A * B * C; ++i) + { + t.bytes[i] = 0xff; + } + presieve_mark(t.bytes, A * B * C, A); + presieve_mark(t.bytes, A * B * C, B); + if (C != 1) + { + presieve_mark(t.bytes, A * B * C, C); + } + return t; +} + +// View of the 16 patterns used by presieve_segment. +struct presieve_tables +{ + const std::uint8_t* table[presieve_table_count]; + std::size_t period[presieve_table_count]; +}; + +// The patterns are constant expressions on compilers whose constexpr step limits allow it. +// MSVC (100000 steps by default) and the nvcc front end fall back to generation at first use. +#if !defined(BOOST_MATH_PRIME_SIEVE_RUNTIME_PRESIEVE) && !defined(_MSC_VER) && !defined(__CUDACC__) +# define BOOST_MATH_PRIME_SIEVE_CONSTEXPR_PRESIEVE +#endif + +#ifdef BOOST_MATH_PRIME_SIEVE_CONSTEXPR_PRESIEVE + +namespace presieve_detail { + +inline constexpr auto pattern_0 = make_presieve_pattern<7, 23, 37>(); +inline constexpr auto pattern_1 = make_presieve_pattern<11, 19, 31>(); +inline constexpr auto pattern_2 = make_presieve_pattern<13, 17, 29>(); +inline constexpr auto pattern_3 = make_presieve_pattern<41, 163, 1>(); +inline constexpr auto pattern_4 = make_presieve_pattern<43, 157, 1>(); +inline constexpr auto pattern_5 = make_presieve_pattern<47, 151, 1>(); +inline constexpr auto pattern_6 = make_presieve_pattern<53, 149, 1>(); +inline constexpr auto pattern_7 = make_presieve_pattern<59, 139, 1>(); +inline constexpr auto pattern_8 = make_presieve_pattern<61, 137, 1>(); +inline constexpr auto pattern_9 = make_presieve_pattern<67, 131, 1>(); +inline constexpr auto pattern_10 = make_presieve_pattern<71, 127, 1>(); +inline constexpr auto pattern_11 = make_presieve_pattern<73, 113, 1>(); +inline constexpr auto pattern_12 = make_presieve_pattern<79, 109, 1>(); +inline constexpr auto pattern_13 = make_presieve_pattern<83, 107, 1>(); +inline constexpr auto pattern_14 = make_presieve_pattern<89, 103, 1>(); +inline constexpr auto pattern_15 = make_presieve_pattern<97, 101, 1>(); + +inline constexpr presieve_tables tables +{ + { + pattern_0.bytes, pattern_1.bytes, pattern_2.bytes, pattern_3.bytes, pattern_4.bytes, pattern_5.bytes, pattern_6.bytes, pattern_7.bytes, + pattern_8.bytes, pattern_9.bytes, pattern_10.bytes, pattern_11.bytes, pattern_12.bytes, pattern_13.bytes, pattern_14.bytes, pattern_15.bytes + }, + { + sizeof(pattern_0.bytes), sizeof(pattern_1.bytes), sizeof(pattern_2.bytes), sizeof(pattern_3.bytes), sizeof(pattern_4.bytes), sizeof(pattern_5.bytes), sizeof(pattern_6.bytes), sizeof(pattern_7.bytes), + sizeof(pattern_8.bytes), sizeof(pattern_9.bytes), sizeof(pattern_10.bytes), sizeof(pattern_11.bytes), sizeof(pattern_12.bytes), sizeof(pattern_13.bytes), sizeof(pattern_14.bytes), sizeof(pattern_15.bytes) + } +}; + +} // namespace presieve_detail + +inline const presieve_tables& get_presieve_tables() noexcept +{ + return presieve_detail::tables; +} + +#else + +namespace presieve_detail { + +struct runtime_tables +{ + std::vector storage[presieve_table_count]; + presieve_tables view {}; + + runtime_tables() + { + for (std::size_t k {0}; k < presieve_table_count; ++k) + { + std::size_t period {1}; + for (const std::uint8_t p : presieve_groups[k]) + { + if (p != 0) + { + period *= p; + } + } + storage[k].assign(period, 0xff); + for (const std::uint8_t p : presieve_groups[k]) + { + if (p != 0) + { + presieve_mark(storage[k].data(), period, p); + } + } + view.table[k] = storage[k].data(); + view.period[k] = period; + } + } +}; + +} // namespace presieve_detail + +inline const presieve_tables& get_presieve_tables() +{ + static const presieve_detail::runtime_tables tables {}; + return tables.view; +} + +#endif + +// Applies four tables to sieve[0, bytes) starting at segment_low; the first pass assigns, +// later passes AND. Runs are cut at table wrap points so the inner loops auto-vectorize. +template +inline void presieve_pass(std::uint8_t* sieve, std::size_t bytes, std::uint64_t segment_low, + const presieve_tables& t, std::size_t first_table) +{ + const std::uint8_t* tab[4] {}; + std::size_t pos[4] {}; + std::size_t per[4] {}; + for (std::size_t k {0}; k < 4; ++k) + { + tab[k] = t.table[first_table + k]; + per[k] = t.period[first_table + k]; + pos[k] = static_cast((segment_low / 30) % per[k]); + } + + std::size_t i {0}; + while (i < bytes) + { + std::size_t run {bytes - i}; + for (std::size_t k {0}; k < 4; ++k) + { + run = (std::min)(run, per[k] - pos[k]); + } + const std::uint8_t* t0 {tab[0] + pos[0]}; + const std::uint8_t* t1 {tab[1] + pos[1]}; + const std::uint8_t* t2 {tab[2] + pos[2]}; + const std::uint8_t* t3 {tab[3] + pos[3]}; + std::uint8_t* s {sieve + i}; + if (Assign) + { + for (std::size_t j {0}; j < run; ++j) + { + s[j] = static_cast(t0[j] & t1[j] & t2[j] & t3[j]); + } + } + else + { + for (std::size_t j {0}; j < run; ++j) + { + s[j] = static_cast(s[j] & t0[j] & t1[j] & t2[j] & t3[j]); + } + } + i += run; + for (std::size_t k {0}; k < 4; ++k) + { + pos[k] += run; + if (pos[k] == per[k]) + { + pos[k] = 0; + } + } + } +} + +// Initializes sieve[0, bytes) for the segment at segment_low with multiples of 7..163 removed, +// then restores the bits of those primes themselves when the segment contains them. +inline void presieve_segment(std::uint8_t* sieve, std::size_t bytes, std::uint64_t segment_low) +{ + const presieve_tables& t {get_presieve_tables()}; + presieve_pass(sieve, bytes, segment_low, t, 0); + presieve_pass(sieve, bytes, segment_low, t, 4); + presieve_pass(sieve, bytes, segment_low, t, 8); + presieve_pass(sieve, bytes, segment_low, t, 12); + + if (segment_low <= presieve_max_prime) + { + for (const std::uint8_t p : presieve_primes) + { + if (p >= segment_low + 7) + { + const std::size_t byte {static_cast((p - segment_low - 7) / 30)}; + if (byte < bytes) + { + sieve[byte] = static_cast(sieve[byte] | (1u << bit_of_residue(p % 30))); + } + } + } + } +} + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_PRESIEVE_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/primality.hpp b/include/boost/math/special_functions/detail/prime_sieve/primality.hpp new file mode 100644 index 0000000000..379427ef64 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/primality.hpp @@ -0,0 +1,826 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Primality tests used by the prime sieve: +// * deterministic Miller-Rabin for 64-bit integers +// * generic modular arithmetic, Jacobi symbol, integer roots +// * Baillie-PSW probable prime test +// * the Lukes-Patterson-Williams pseudosquares test (deterministic, table bounded) +// The generic templates require an Integer type that can hold m * m for the modulus m +// in use (Boost.Multiprecision integers qualify). Builtin 64-bit values use the +// dedicated *_u64 functions. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_PRIMALITY_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_PRIMALITY_HPP + +#include + +#ifndef BOOST_MATH_HAS_NVRTC + +#include +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_X64) +# include +#endif +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +// The 71 primes not exceeding 353: bases for the pseudosquares test and trial division. +inline constexpr std::uint16_t small_primes_to_353[71] = +{ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, + 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353 +}; + +// (a + b) mod m for a, b < m without overflow. +inline std::uint64_t addmod_u64(std::uint64_t a, std::uint64_t b, std::uint64_t m) noexcept +{ + return a >= m - b ? a - (m - b) : a + b; +} + +// (a * b) mod m for any 64-bit operands. +inline std::uint64_t mulmod_u64(std::uint64_t a, std::uint64_t b, std::uint64_t m) noexcept +{ +// clang-cl has __int128 but the MSVC runtime lacks __umodti3, which the remainder below needs: +#if defined(BOOST_MATH_HAS_INT128) && !(defined(_MSC_VER) && defined(__clang__)) + return static_cast((static_cast(a) * b) % m); +#elif defined(_MSC_VER) && !defined(__clang__) && defined(_M_X64) + std::uint64_t high {}; + const std::uint64_t low {_umul128(a, b, &high)}; + if (high >= m) + { + high %= m; + } + std::uint64_t remainder {}; + _udiv128(high, low, m, &remainder); + return remainder; +#else + a %= m; + b %= m; + std::uint64_t result {0}; + while (b != 0) + { + if (b & 1u) + { + result = addmod_u64(result, a, m); + } + a = addmod_u64(a, a, m); + b >>= 1; + } + return result; +#endif +} + +// base^exp mod m. +inline std::uint64_t powm_u64(std::uint64_t base, std::uint64_t exp, std::uint64_t m) noexcept +{ + std::uint64_t result {1 % m}; + base %= m; + while (exp != 0) + { + if (exp & 1u) + { + result = mulmod_u64(result, base, m); + } + base = mulmod_u64(base, base, m); + exp >>= 1; + } + return result; +} + +// Deterministic Miller-Rabin for all 64-bit values with the seven bases of Sinclair. +// Slower than is_prime_u64; kept as an independent oracle for testing. +inline bool is_prime_u64_miller_rabin(std::uint64_t n) noexcept +{ + if (n < 2) + { + return false; + } + for (std::size_t i {0}; i < 12; ++i) + { + const std::uint64_t p {small_primes_to_353[i]}; + if (n % p == 0) + { + return n == p; + } + } + if (n < 41u * 41u) + { + return true; + } + + constexpr std::uint64_t bases[7] = {2u, 325u, 9375u, 28178u, 450775u, 9780504u, 1795265022u}; + const int r {BOOST_MATH_NAMESPACE::tools::countr_zero(n - 1)}; + const std::uint64_t d {(n - 1) >> r}; + + for (const std::uint64_t base : bases) + { + const std::uint64_t a {base % n}; + if (a == 0) + { + continue; + } + std::uint64_t x {powm_u64(a, d, n)}; + if (x == 1 || x == n - 1) + { + continue; + } + bool composite {true}; + for (int i {1}; i < r; ++i) + { + x = mulmod_u64(x, x, n); + if (x == n - 1) + { + composite = false; + break; + } + } + if (composite) + { + return false; + } + } + return true; +} + +// Jacobi symbol (a / n) for odd n > 0. +inline int jacobi_u64(std::uint64_t a, std::uint64_t n) noexcept +{ + a %= n; + int result {1}; + while (a != 0) + { + const int twos {BOOST_MATH_NAMESPACE::tools::countr_zero(a)}; + a >>= twos; + if ((twos & 1) != 0) + { + const std::uint64_t r {n % 8}; + if (r == 3 || r == 5) + { + result = -result; + } + } + const std::uint64_t t {a}; + a = n; + n = t; + if (a % 4 == 3 && n % 4 == 3) + { + result = -result; + } + a %= n; + } + return n == 1 ? result : 0; +} + +// Montgomery arithmetic modulo an odd 64-bit n. Where no 128-bit product is available +// the "Montgomery" form degenerates to plain residues with a slow multiply. +class montgomery_u64 +{ +public: + explicit montgomery_u64(std::uint64_t n) noexcept : n_(n) + { +#if defined(BOOST_MATH_HAS_INT128) || (defined(_MSC_VER) && !defined(__clang__) && defined(_M_X64)) + // Newton iteration for n^-1 mod 2^64: n is odd so n * n == 1 (mod 8) seeds 3 bits + std::uint64_t inv {n}; + for (int i {0}; i < 5; ++i) + { + inv *= 2u - n * inv; + } + n_inv_neg_ = 0u - inv; + one_ = (0u - n) % n; // 2^64 mod n + r2_ = mulmod_u64(one_, one_, n); // 2^128 mod n +#else + one_ = 1; + r2_ = 1; +#endif + } + + std::uint64_t modulus() const noexcept + { + return n_; + } + + std::uint64_t one() const noexcept + { + return one_; + } + + std::uint64_t to_form(std::uint64_t a) const noexcept + { + return mul(a % n_, r2_); + } + + std::uint64_t add(std::uint64_t a, std::uint64_t b) const noexcept + { + return addmod_u64(a, b, n_); + } + + std::uint64_t sub(std::uint64_t a, std::uint64_t b) const noexcept + { + return a >= b ? a - b : a + (n_ - b); + } + + // a / 2 modulo n (n odd) + std::uint64_t half(std::uint64_t a) const noexcept + { + return (a & 1u) ? (a >> 1) + (n_ >> 1) + 1 : a >> 1; + } + + std::uint64_t mul(std::uint64_t a, std::uint64_t b) const noexcept + { +#if defined(BOOST_MATH_HAS_INT128) + const unsigned __int128 t {static_cast(a) * b}; + const std::uint64_t m {static_cast(t) * n_inv_neg_}; + const unsigned __int128 mn {static_cast(m) * n_}; + const std::uint64_t t_hi {static_cast(t >> 64)}; + const std::uint64_t mn_hi {static_cast(mn >> 64)}; + return reduce(t_hi, mn_hi, static_cast(t) != 0); +#elif defined(_MSC_VER) && !defined(__clang__) && defined(_M_X64) + std::uint64_t t_hi {}; + const std::uint64_t t_lo {_umul128(a, b, &t_hi)}; + const std::uint64_t m {t_lo * n_inv_neg_}; + std::uint64_t mn_hi {}; + _umul128(m, n_, &mn_hi); + return reduce(t_hi, mn_hi, t_lo != 0); +#else + return mulmod_u64(a, b, n_); +#endif + } + + std::uint64_t pow(std::uint64_t base, std::uint64_t exp) const noexcept + { + std::uint64_t result {one_}; + while (exp != 0) + { + if (exp & 1u) + { + result = mul(result, base); + } + base = mul(base, base); + exp >>= 1; + } + return result; + } + +private: + // The low halves of t and m * n sum to a multiple of 2^64, so only the carry matters. + std::uint64_t reduce(std::uint64_t t_hi, std::uint64_t mn_hi, bool carry) const noexcept + { + const std::uint64_t r {t_hi + mn_hi + (carry ? 1u : 0u)}; + if (r < t_hi || r >= n_) + { + return r - n_; + } + return r; + } + + std::uint64_t n_; + std::uint64_t n_inv_neg_ {0}; + std::uint64_t one_; + std::uint64_t r2_; +}; + +// Deterministic primality for all 64-bit values: trial division, then Baillie-PSW (a strong +// base-2 test and a strong Lucas test with Selfridge's parameters), which has been verified +// to have no counterexample below 2^64. +inline bool is_prime_u64(std::uint64_t n) noexcept +{ + if (n < 2) + { + return false; + } + for (std::size_t i {0}; i < 16; ++i) + { + const std::uint64_t p {small_primes_to_353[i]}; + if (n % p == 0) + { + return n == p; + } + } + if (n < 59u * 59u) + { + return true; + } + + const montgomery_u64 mont {n}; + const std::uint64_t one {mont.one()}; + const std::uint64_t minus_one {n - one}; + + // strong Fermat test to base 2 + const int r {BOOST_MATH_NAMESPACE::tools::countr_zero(n - 1)}; + const std::uint64_t d {(n - 1) >> r}; + std::uint64_t x {mont.pow(mont.to_form(2), d)}; + if (x != one && x != minus_one) + { + bool witness {true}; + for (int i {1}; i < r; ++i) + { + x = mont.mul(x, x); + if (x == minus_one) + { + witness = false; + break; + } + } + if (witness) + { + return false; + } + } + + // perfect squares would make the search for D below loop forever + const std::uint64_t root {BOOST_MATH_NAMESPACE::tools::isqrt(n)}; + if (root * root == n) + { + return false; + } + + // Selfridge method A: D = 5, -7, 9, -11, ... with (D / n) == -1; P = 1, Q = (1 - D) / 4 + long d_small {5}; + while (true) + { + const std::uint64_t magnitude {static_cast(d_small < 0 ? -d_small : d_small)}; + int j {jacobi_u64(magnitude % n, n)}; + if (d_small < 0 && n % 4 == 3) + { + j = -j; + } + if (j == -1) + { + break; + } + if (j == 0 && magnitude % n != 0) + { + return false; + } + d_small = d_small > 0 ? -(d_small + 2) : -(d_small - 2); + } + const long q_small {(1 - d_small) / 4}; + const std::uint64_t d_res {d_small < 0 ? n - (static_cast(-d_small) % n) : static_cast(d_small) % n}; + const std::uint64_t q_res {q_small < 0 ? n - (static_cast(-q_small) % n) : static_cast(q_small) % n}; + const std::uint64_t big_d {mont.to_form(d_res)}; + const std::uint64_t big_q {mont.to_form(q_res)}; + + const int s {BOOST_MATH_NAMESPACE::tools::countr_zero(n + 1)}; + const std::uint64_t k {(n + 1) >> s}; + std::uint64_t u {one}; + std::uint64_t v {one}; + std::uint64_t qk {big_q}; + for (int i {63 - BOOST_MATH_NAMESPACE::tools::countl_zero(k)}; i-- > 0;) + { + u = mont.mul(u, v); + v = mont.sub(mont.mul(v, v), mont.add(qk, qk)); + qk = mont.mul(qk, qk); + if (((k >> i) & 1u) != 0) + { + const std::uint64_t u_next {mont.half(mont.add(u, v))}; + const std::uint64_t v_next {mont.half(mont.add(mont.mul(big_d, u), v))}; + u = u_next; + v = v_next; + qk = mont.mul(qk, big_q); + } + } + if (u == 0 || v == 0) + { + return true; + } + for (int i {1}; i < s; ++i) + { + v = mont.sub(mont.mul(v, v), mont.add(qk, qk)); + if (v == 0) + { + return true; + } + qk = mont.mul(qk, qk); + } + return false; +} + +// Reduces x into [0, m) for signed Integer types. +template +inline Integer mod_positive(Integer x, const Integer& m) +{ + x %= m; + if (x < 0) + { + x += m; + } + return x; +} + +// base^exp mod m by square and multiply. +template +Integer powm(Integer base, Integer exp, const Integer& m) +{ + Integer result {1}; + base = mod_positive(base, m); + while (exp > 0) + { + if (exp % 2 == 1) + { + result = (result * base) % m; + } + exp /= 2; + if (exp > 0) + { + base = (base * base) % m; + } + } + return result; +} + +// Jacobi symbol (a / n) for a >= 0 and odd n > 0. +template +int jacobi(Integer a, Integer n) +{ + a %= n; + int result {1}; + while (a != 0) + { + while (a % 2 == 0) + { + a /= 2; + const Integer r {n % 8}; + if (r == 3 || r == 5) + { + result = -result; + } + } + std::swap(a, n); + if (a % 4 == 3 && n % 4 == 3) + { + result = -result; + } + a %= n; + } + return n == 1 ? result : 0; +} + +// Jacobi symbol for a small signed numerator. +template +int jacobi_signed(long a, const Integer& n) +{ + if (a < 0) + { + const int sign {n % 4 == 3 ? -1 : 1}; + return sign * jacobi(Integer(-a), n); + } + return jacobi(Integer(a), n); +} + +// Number of significant bits in n >= 0. +template +unsigned bit_length(Integer n) +{ + unsigned bits {0}; + while (n > 0) + { + n /= 2; + ++bits; + } + return bits; +} + +// Largest r with r * r <= n. +template +Integer isqrt(const Integer& n) +{ + if (n < 2) + { + return n; + } + Integer x {1}; + x <<= (bit_length(n) + 1) / 2; + while (true) + { + const Integer y {(x + n / x) / 2}; + if (y >= x) + { + return x; + } + x = y; + } +} + +// Largest r with r^k <= n, for k >= 2. +template +Integer iroot(const Integer& n, unsigned k) +{ + if (k == 2) + { + return isqrt(n); + } + Integer low {1}; + Integer high {1}; + high <<= (bit_length(n) / k + 1); + while (low < high) + { + const Integer mid {(low + high + 1) / 2}; + Integer power {1}; + bool too_big {false}; + for (unsigned i {0}; i < k; ++i) + { + power *= mid; + if (power > n) + { + too_big = true; + break; + } + } + if (too_big) + { + high = mid - 1; + } + else + { + low = mid; + } + } + return low; +} + +// True when n == r^k for some r and some prime k <= max_k. +template +bool is_perfect_power(const Integer& n, unsigned max_k) +{ + for (std::size_t i {0}; i < 71 && small_primes_to_353[i] <= max_k; ++i) + { + const unsigned k {small_primes_to_353[i]}; + const Integer r {iroot(n, k)}; + Integer power {1}; + for (unsigned j {0}; j < k; ++j) + { + power *= r; + } + if (power == n) + { + return true; + } + } + return false; +} + +// Strong Fermat probable prime test to base 2 for odd n > 2. +template +bool strong_fermat_base2(const Integer& n) +{ + Integer d {n - 1}; + unsigned r {0}; + while (d % 2 == 0) + { + d /= 2; + ++r; + } + Integer x {powm(Integer(2), d, n)}; + if (x == 1 || x == n - 1) + { + return true; + } + for (unsigned i {1}; i < r; ++i) + { + x = (x * x) % n; + if (x == n - 1) + { + return true; + } + } + return false; +} + +// Strong Lucas probable prime test with Selfridge's method A parameters for odd n > 2. +// n must not be a perfect square (the D search would not terminate). +template +bool strong_lucas_selfridge(const Integer& n) +{ + // Find D = 5, -7, 9, -11, ... with (D / n) == -1 + long d_small {5}; + while (true) + { + const int j {jacobi_signed(d_small, n)}; + if (j == -1) + { + break; + } + if (j == 0) + { + // gcd(|D|, n) > 1: composite unless n is |D| itself + return n == Integer(d_small < 0 ? -d_small : d_small); + } + d_small = d_small > 0 ? -(d_small + 2) : -(d_small - 2); + } + + const Integer big_d {static_cast(d_small)}; + const Integer big_q {mod_positive(Integer((1 - d_small) / 4), n)}; + + Integer d {n + 1}; + unsigned s {0}; + while (d % 2 == 0) + { + d /= 2; + ++s; + } + + // Binary ladder for U_d, V_d and Q^d with P == 1 + Integer u {1}; + Integer v {1}; + Integer qk {big_q}; + const unsigned bits {bit_length(d)}; + for (unsigned i {bits - 1}; i-- > 0;) + { + // k -> 2k + u = (u * v) % n; + v = mod_positive(Integer(v * v - 2 * qk), n); + qk = (qk * qk) % n; + if (((d >> i) & 1) == 1) + { + // k -> k + 1 + Integer u_next {u + v}; + if (u_next % 2 != 0) + { + u_next += n; + } + u_next /= 2; + Integer v_next {big_d * u + v}; + v_next = mod_positive(v_next, n); + if (v_next % 2 != 0) + { + v_next += n; + } + v_next /= 2; + u = u_next % n; + v = v_next % n; + qk = (qk * big_q) % n; + } + } + + if (u == 0 || v == 0) + { + return true; + } + for (unsigned i {1}; i < s; ++i) + { + v = mod_positive(Integer(v * v - 2 * qk), n); + if (v == 0) + { + return true; + } + qk = (qk * qk) % n; + } + return false; +} + +// Baillie-PSW probable prime test: no counterexample is known, deterministic below 2^64. +template +bool is_probable_prime_bpsw(const Integer& n) +{ + if (n < 2) + { + return false; + } + for (std::size_t i {0}; i < 71; ++i) + { + const Integer p {small_primes_to_353[i]}; + if (n % p == 0) + { + return n == p; + } + } + if (n < Integer(359u * 359u)) + { + return true; + } + if (!strong_fermat_base2(n)) + { + return false; + } + const Integer r {isqrt(n)}; + if (r * r == n) + { + return false; + } + return strong_lucas_selfridge(n); +} + +// Pseudosquares L_p: the least non-square m == 1 (mod 8) that is a quadratic residue modulo +// every odd prime q <= p. Each row stores the smallest prime attaining a distinct value, so +// choosing the first row with L_p > n / s uses the fewest bases. Values from Hugh Williams, +// "Edouard Lucas and Primality Testing", table 16.3.1, extended by Wooding (2003). +struct pseudosquare_entry +{ + std::uint16_t p; + std::uint64_t high; + std::uint64_t low; +}; + +inline constexpr pseudosquare_entry pseudosquares[49] = +{ + { 3, 0, 73ULL }, { 5, 0, 241ULL }, { 7, 0, 1009ULL }, + { 11, 0, 2641ULL }, { 13, 0, 8089ULL }, { 17, 0, 18001ULL }, + { 19, 0, 53881ULL }, { 23, 0, 87481ULL }, { 29, 0, 117049ULL }, + { 31, 0, 515761ULL }, { 37, 0, 1083289ULL }, { 41, 0, 3206641ULL }, + { 43, 0, 3818929ULL }, { 47, 0, 9257329ULL }, { 53, 0, 22000801ULL }, + { 59, 0, 48473881ULL }, { 67, 0, 175244281ULL }, { 71, 0, 427733329ULL }, + { 79, 0, 898716289ULL }, { 83, 0, 2805544681ULL }, { 101, 0, 10310263441ULL }, + { 103, 0, 23616331489ULL }, { 107, 0, 85157610409ULL }, { 113, 0, 196265095009ULL }, + { 131, 0, 2871842842801ULL }, { 149, 0, 26250887023729ULL }, { 157, 0, 112434732901969ULL }, + { 173, 0, 178936222537081ULL }, { 181, 0, 696161110209049ULL }, { 193, 0, 2854909648103881ULL }, + { 197, 0, 6450045516630769ULL }, { 211, 0, 11641399247947921ULL }, { 227, 0, 190621428905186449ULL }, + { 229, 0, 196640148121928601ULL }, { 233, 0, 712624335095093521ULL }, { 239, 0, 1773855791877850321ULL }, + { 241, 0, 2327687064124474441ULL }, { 251, 0, 6384991873059836689ULL }, { 257, 0, 8019204661305419761ULL }, + { 263, 0, 10198100582046287689ULL }, + { 277, 0x3ULL, 0xc956f827e0524359ULL }, // 69848288320900186969 + { 281, 0xbULL, 0x539315b3b1268d59ULL }, // 208936365799044975961 + { 283, 0x1cULL, 0xec87d86ca60b50a1ULL }, // 533552663339828203681 + { 293, 0x32ULL, 0xc6d3496f20db3d81ULL }, // 936664079266714697089 + { 311, 0x74ULL, 0x210967a12ba94be1ULL }, // 2142202860370269916129 + { 331, 0x2e3ULL, 0xec11ddc09fd65c51ULL }, // 13649154491558298803281 + { 337, 0x753ULL, 0x641c14b397c27bf1ULL }, // 34594858801670127778801 + { 347, 0x1511ULL, 0x85fdf38d1fc9ce21ULL }, // 99492945930479213334049 + { 353, 0x3e8bULL, 0xaba417e222ca5091ULL } // 295363187400900310880401 +}; + +// Builds the pseudosquare value of a table row in the Integer type. +template +Integer pseudosquare_value(std::size_t index) +{ + Integer value {pseudosquares[index].high}; + value <<= 32; + value <<= 32; + value += Integer(pseudosquares[index].low); + return value; +} + +// Smallest table index whose pseudosquare exceeds n_over_s, or 49 when the table is exhausted. +template +std::size_t pseudosquare_index_for(const Integer& n_over_s) +{ + for (std::size_t i {0}; i < 49; ++i) + { + if (pseudosquare_value(i) > n_over_s) + { + return i; + } + } + return 49; +} + +// Lukes-Patterson-Williams test. Preconditions: n odd, n has no prime factor <= s, +// s >= 2, and pseudosquares[index] satisfies L_p > n / s. Returns true iff n is prime. +// Conditions (Sorenson, "The pseudosquares prime sieve", theorem 2.1): +// (1) q^((n-1)/2) == +-1 (mod n) for every prime q <= p +// (2) 2^((n-1)/2) == -1 (mod n) when n == 5 (mod 8) +// (3) some q gives -1 when n == 1 (mod 8) +// which prove n is a prime or a prime power; the perfect power check removes the latter. +template +bool pseudosquares_prime_test(const Integer& n, std::size_t index, std::uint64_t s) +{ + const unsigned p {pseudosquares[index].p}; + const Integer exponent {(n - 1) / 2}; + const Integer n_mod_8 {n % 8}; + bool saw_minus_one {false}; + + for (std::size_t i {0}; i < 71 && small_primes_to_353[i] <= p; ++i) + { + const Integer q {small_primes_to_353[i]}; + const Integer e {powm(q, exponent, n)}; + if (e == n - 1) + { + saw_minus_one = true; + } + else if (e != 1) + { + return false; + } + else if (i == 0 && n_mod_8 == 5) + { + return false; + } + } + if (n_mod_8 == 1 && !saw_minus_one) + { + return false; + } + + // Any prime power q^k with q > s has k <= log(n) / log(s) + const unsigned log2_s {s < 2 ? 1u : static_cast(63 - BOOST_MATH_NAMESPACE::tools::countl_zero(s))}; + const unsigned max_k {bit_length(n) / log2_s}; + if (max_k >= 2 && is_perfect_power(n, max_k)) + { + return false; + } + return true; +} + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_HAS_NVRTC +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_PRIMALITY_HPP diff --git a/include/boost/math/special_functions/detail/prime_sieve/sinks.hpp b/include/boost/math/special_functions/detail/prime_sieve/sinks.hpp new file mode 100644 index 0000000000..bdf4803113 --- /dev/null +++ b/include/boost/math/special_functions/detail/prime_sieve/sinks.hpp @@ -0,0 +1,219 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Sinks consume finished segments: count set bits, or extract the primes into a +// 64-bit buffer that a consumer converts to the user's integer type. + +#ifndef BOOST_MATH_SF_DETAIL_PRIME_SIEVE_SINKS_HPP +#define BOOST_MATH_SF_DETAIL_PRIME_SIEVE_SINKS_HPP + +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail::prime_sieve { + +// Sink contract: segment(words, n_words, low) receives the final bits of one segment whose +// first byte represents low + {7, ..., 31}; bits outside the requested range are already clear. +struct count_sink +{ + std::uint64_t count {0}; + + void segment(const std::uint64_t* words, std::size_t n_words, std::uint64_t) noexcept + { + count += count_bits(words, n_words); + } + + // Without a hardware popcount instruction the compiler expands popcount into a library + // call or a long bit trick per word; a Harley-Seal carry-save adder over 8 words needs + // about a third of the operations (Hacker's Delight, 2nd edition, chapter 5). + static std::uint64_t count_bits(const std::uint64_t* words, std::size_t n) noexcept + { +#if defined(__x86_64__) && !defined(__POPCNT__) + std::uint64_t total {0}; + std::uint64_t ones {0}; + std::uint64_t twos {0}; + std::uint64_t fours {0}; + std::size_t i {0}; + for (; i + 8 <= n; i += 8) + { + std::uint64_t twos_a {}; + std::uint64_t twos_b {}; + std::uint64_t fours_a {}; + std::uint64_t fours_b {}; + csa(ones, twos_a, ones, words[i], words[i + 1]); + csa(ones, twos_b, ones, words[i + 2], words[i + 3]); + csa(twos, fours_a, twos, twos_a, twos_b); + csa(ones, twos_a, ones, words[i + 4], words[i + 5]); + csa(ones, twos_b, ones, words[i + 6], words[i + 7]); + csa(twos, fours_b, twos, twos_a, twos_b); + std::uint64_t eights {}; + csa(fours, eights, fours, fours_a, fours_b); + total += static_cast(swar_popcount(eights)); + } + total = 8 * total + 4 * swar_popcount(fours) + 2 * swar_popcount(twos) + swar_popcount(ones); + for (; i < n; ++i) + { + total += static_cast(swar_popcount(words[i])); + } + return total; +#else + std::uint64_t c {0}; + for (std::size_t i {0}; i < n; ++i) + { + c += static_cast(BOOST_MATH_NAMESPACE::tools::popcount(words[i])); + } + return c; +#endif + } + + static void csa(std::uint64_t& sum, std::uint64_t& carry, std::uint64_t a, std::uint64_t b, std::uint64_t c) noexcept + { + const std::uint64_t u {a ^ b}; + sum = u ^ c; + carry = (a & b) | (u & c); + } + + static std::uint64_t swar_popcount(std::uint64_t x) noexcept + { + x = x - ((x >> 1) & 0x5555555555555555ULL); + x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL); + x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fULL; + return (x * 0x0101010101010101ULL) >> 56; + } + + void flush() noexcept + { + } +}; + +// Extracts primes into a buffer of batch entries and hands full batches to Consumer, +// which is called as consume(const std::uint64_t* primes, std::size_t n). +template +class extract_sink +{ +public: + static constexpr std::size_t slack {68}; + + explicit extract_sink(Consumer& consume, std::size_t batch = 65536) : consume_(consume), batch_(batch) + { + buffer_.resize(batch + slack); + } + + void segment(const std::uint64_t* words, std::size_t n_words, std::uint64_t low) + { + const unsigned char* bytes {reinterpret_cast(words)}; + for (std::size_t w {0}; w < n_words; ++w) + { + if (size_ >= batch_) + { + flush(); + } + const std::uint64_t word {BOOST_MATH_NAMESPACE::tools::load_le64(bytes + 8 * w)}; + size_ += extract_word(word, low + 240u * w, buffer_.data() + size_); + } + } + + void flush() + { + if (size_ != 0) + { + consume_(buffer_.data(), size_); + size_ = 0; + } + } + +private: + Consumer& consume_; + std::vector buffer_; + std::size_t size_ {0}; + std::size_t batch_; +}; + +// Consumer that converts to Integer and writes through an output iterator. +template +struct output_converter +{ + OutputIterator out; + + void operator()(const std::uint64_t* primes, std::size_t n) + { + for (std::size_t i {0}; i < n; ++i) + { + *out = static_cast(primes[i]); + ++out; + } + } +}; + +// Writes 32-bit primes straight into a pre-sized vector (sieving prime generation), avoiding +// the 64-bit batch buffer and the conversion pass. +class extract_sink_u32 +{ +public: + // capacity must be an upper bound on the number of primes plus 68 slots of slack + extract_sink_u32(std::vector& out, std::size_t capacity) : out_(out) + { + out_.resize(capacity); + } + + void segment(const std::uint64_t* words, std::size_t n_words, std::uint64_t low) noexcept + { + const unsigned char* bytes {reinterpret_cast(words)}; + std::uint32_t* dst {out_.data()}; + for (std::size_t w {0}; w < n_words; ++w) + { + const std::uint64_t word {BOOST_MATH_NAMESPACE::tools::load_le64(bytes + 8 * w)}; + size_ += extract_word_u32(word, low + 240u * w, dst + size_); + } + } + + void flush() + { + out_.resize(size_); + } + +private: + std::vector& out_; + std::size_t size_ {0}; +}; + +// Consumer that appends 32-bit values to a vector (sieving primes). +struct append_u32 +{ + std::vector& out; + + void operator()(const std::uint64_t* primes, std::size_t n) + { + const std::size_t old_size {out.size()}; + out.resize(old_size + n); + std::uint32_t* dst {out.data() + old_size}; + for (std::size_t i {0}; i < n; ++i) + { + dst[i] = static_cast(primes[i]); + } + } +}; + +// Consumer that appends 64-bit values to a vector. +struct append_u64 +{ + std::vector& out; + + void operator()(const std::uint64_t* primes, std::size_t n) + { + out.insert(out.end(), primes, primes + n); + } +}; + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::detail::prime_sieve + +#endif // BOOST_MATH_SF_DETAIL_PRIME_SIEVE_SINKS_HPP diff --git a/include/boost/math/special_functions/detail/round_fwd.hpp b/include/boost/math/special_functions/detail/round_fwd.hpp index 7d69f8b9c5..8041178fdb 100644 --- a/include/boost/math/special_functions/detail/round_fwd.hpp +++ b/include/boost/math/special_functions/detail/round_fwd.hpp @@ -16,71 +16,67 @@ #pragma once #endif -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type trunc(const T& v, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type trunc(const T& v); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int itrunc(const T& v, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int itrunc(const T& v); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long ltrunc(const T& v, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long ltrunc(const T& v); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long long lltrunc(const T& v, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long long lltrunc(const T& v); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type round(const T& v, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type round(const T& v); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int iround(const T& v, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int iround(const T& v); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long lround(const T& v, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long lround(const T& v); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long long llround(const T& v, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long long llround(const T& v); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T modf(const T& v, T* ipart, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T modf(const T& v, T* ipart); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T modf(const T& v, int* ipart, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T modf(const T& v, int* ipart); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T modf(const T& v, long* ipart, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T modf(const T& v, long* ipart); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T modf(const T& v, long long* ipart, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T modf(const T& v, long long* ipart); - } -} + BOOST_MATH_NAMESPACE_END #undef BOOST_MATH_STD_USING #define BOOST_MATH_STD_USING BOOST_MATH_STD_USING_CORE\ - using boost::math::round;\ - using boost::math::iround;\ - using boost::math::lround;\ - using boost::math::trunc;\ - using boost::math::itrunc;\ - using boost::math::ltrunc;\ - using boost::math::modf; + using BOOST_MATH_NAMESPACE::round;\ + using BOOST_MATH_NAMESPACE::iround;\ + using BOOST_MATH_NAMESPACE::lround;\ + using BOOST_MATH_NAMESPACE::trunc;\ + using BOOST_MATH_NAMESPACE::itrunc;\ + using BOOST_MATH_NAMESPACE::ltrunc;\ + using BOOST_MATH_NAMESPACE::modf; #endif // BOOST_MATH_SPECIAL_ROUND_FWD_HPP diff --git a/include/boost/math/special_functions/detail/t_distribution_inv.hpp b/include/boost/math/special_functions/detail/t_distribution_inv.hpp index 4b55b4fe21..93b6e3713e 100644 --- a/include/boost/math/special_functions/detail/t_distribution_inv.hpp +++ b/include/boost/math/special_functions/detail/t_distribution_inv.hpp @@ -18,7 +18,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // // The main method used is due to Hill: @@ -35,7 +35,7 @@ BOOST_MATH_GPU_ENABLED T inverse_students_t_hill(T ndf, T u, const Policy& pol) T a, b, c, d, q, x, y; if (ndf > 1e20f) - return -boost::math::erfc_inv(2 * u, pol) * constants::root_two(); + return -BOOST_MATH_NAMESPACE::erfc_inv(2 * u, pol) * constants::root_two(); a = 1 / (ndf - 0.5f); b = 48 / (a * a); @@ -48,14 +48,14 @@ BOOST_MATH_GPU_ENABLED T inverse_students_t_hill(T ndf, T u, const Policy& pol) // // Asymptotic inverse expansion about normal: // - x = -boost::math::erfc_inv(2 * u, pol) * constants::root_two(); + x = -BOOST_MATH_NAMESPACE::erfc_inv(2 * u, pol) * constants::root_two(); y = x * x; if (ndf < 5) c += 0.3f * (ndf - 4.5f) * (x + 0.6f); c += (((0.05f * d * x - 5) * x - 7) * x - 2) * x + b; y = (((((0.4f * y + 6.3f) * y + 36) * y + 94.5f) / c - y - 3) / b + 1) * x; - y = boost::math::expm1(a * y * y, pol); + y = BOOST_MATH_NAMESPACE::expm1(a * y * y, pol); } else { @@ -82,7 +82,7 @@ BOOST_MATH_GPU_ENABLED T inverse_students_t_tail_series(T df, T v, const Policy& BOOST_MATH_STD_USING // Tail series expansion, see section 6 of Shaw's paper. // w is calculated using Eq 60: - T w = boost::math::tgamma_delta_ratio(df / 2, constants::half(), pol) + T w = BOOST_MATH_NAMESPACE::tgamma_delta_ratio(df / 2, constants::half(), pol) * sqrt(df * constants::pi()) * v; // define some variables: T np2 = df + 2; @@ -136,7 +136,7 @@ BOOST_MATH_GPU_ENABLED T inverse_students_t_body_series(T df, T u, const Policy& // // Start with Eq 56 of Shaw: // - T v = boost::math::tgamma_delta_ratio(df / 2, constants::half(), pol) + T v = BOOST_MATH_NAMESPACE::tgamma_delta_ratio(df / 2, constants::half(), pol) * sqrt(df * constants::pi()) * (u - constants::half()); // // Workspace for the polynomial coefficients: @@ -287,7 +287,7 @@ BOOST_MATH_GPU_ENABLED T inverse_students_t(T df, T u, T v, const Policy& pol, b // supplement: // T a = 4 * (u - u * u);//1 - 4 * (u - 0.5f) * (u - 0.5f); - T b = boost::math::cbrt(a, pol); + T b = BOOST_MATH_NAMESPACE::cbrt(a, pol); static const T c = static_cast(0.85498797333834849467655443627193); T p = 6 * (1 + c * (1 / b - 1)); T p0; @@ -377,7 +377,7 @@ BOOST_MATH_GPU_ENABLED T inverse_students_t(T df, T u, T v, const Policy& pol, b calculate_real: if(df > 0x10000000) { - result = -boost::math::erfc_inv(2 * u, pol) * constants::root_two(); + result = -BOOST_MATH_NAMESPACE::erfc_inv(2 * u, pol) * constants::root_two(); if((pexact) && (df >= 1e20)) *pexact = true; } @@ -390,11 +390,11 @@ BOOST_MATH_GPU_ENABLED T inverse_students_t(T df, T u, T v, const Policy& pol, b T crossover = 0.2742f - df * 0.0242143f; if(u > crossover) { - result = boost::math::detail::inverse_students_t_body_series(df, u, pol); + result = BOOST_MATH_NAMESPACE::detail::inverse_students_t_body_series(df, u, pol); } else { - result = boost::math::detail::inverse_students_t_tail_series(df, u, pol); + result = BOOST_MATH_NAMESPACE::detail::inverse_students_t_tail_series(df, u, pol); } } else @@ -409,11 +409,11 @@ BOOST_MATH_GPU_ENABLED T inverse_students_t(T df, T u, T v, const Policy& pol, b // The following is equivalent to: u > 2^df/-0.654 if(m_exp > 0 && u_exp < df / 0.654f) { - result = boost::math::detail::inverse_students_t_hill(df, u, pol); + result = BOOST_MATH_NAMESPACE::detail::inverse_students_t_hill(df, u, pol); } else { - result = boost::math::detail::inverse_students_t_tail_series(df, u, pol); + result = BOOST_MATH_NAMESPACE::detail::inverse_students_t_tail_series(df, u, pol); } } } @@ -426,7 +426,7 @@ BOOST_MATH_GPU_ENABLED inline T find_ibeta_inv_from_t_dist(T a, T p, T /*q*/, T* T u = p / 2; T v = 1 - u; T df = a * 2; - T t = boost::math::detail::inverse_students_t(df, u, v, pol); + T t = BOOST_MATH_NAMESPACE::detail::inverse_students_t(df, u, v, pol); *py = t * t / (df + t * t); return df / (df + t * t); } @@ -445,7 +445,7 @@ namespace detail { #endif template -BOOST_MATH_GPU_ENABLED inline T fast_students_t_quantile_imp(T df, T p, const Policy& pol, const boost::math::false_type*) +BOOST_MATH_GPU_ENABLED inline T fast_students_t_quantile_imp(T df, T p, const Policy& pol, const BOOST_MATH_NAMESPACE::false_type*) { BOOST_MATH_STD_USING // @@ -468,12 +468,12 @@ BOOST_MATH_GPU_ENABLED inline T fast_students_t_quantile_imp(T df, T p, const Po } template -BOOST_MATH_GPU_ENABLED T fast_students_t_quantile_imp(T df, T p, const Policy& pol, const boost::math::true_type*) +BOOST_MATH_GPU_ENABLED T fast_students_t_quantile_imp(T df, T p, const Policy& pol, const BOOST_MATH_NAMESPACE::true_type*) { BOOST_MATH_STD_USING bool invert = false; if((df < 2) && (floor(df) != df)) - return boost::math::detail::fast_students_t_quantile_imp(df, p, pol, static_cast(nullptr)); + return BOOST_MATH_NAMESPACE::detail::fast_students_t_quantile_imp(df, p, pol, static_cast(nullptr)); if(p > 0.5) { p = 1 - p; @@ -489,53 +489,70 @@ BOOST_MATH_GPU_ENABLED T fast_students_t_quantile_imp(T df, T p, const Policy& p // // Change variables to inverse incomplete beta: // - T t2 = t * t; - T xb = df / (df + t2); - T y = t2 / (df + t2); - T a = df / 2; - // - // t can be so large that x underflows, - // just return our estimate in that case: - // - if(xb == 0) - return t; - // - // Get incomplete beta and it's derivative: - // - T f1; - T f0 = xb < y ? ibeta_imp(a, constants::half(), xb, pol, false, true, &f1) - : ibeta_imp(constants::half(), a, y, pol, true, true, &f1); + for (int i = 0; i < 3; ++i) + { + T t2 = t * t; + T xb = df / (df + t2); + T y = t2 / (df + t2); + T a = df / 2; + // + // t can be so large that x underflows, + // just return our estimate in that case: + // + if(xb == 0) + return invert ? -t : t; + // + // Get incomplete beta and it's derivative: + // + T f1; + T f0 = xb < y ? ibeta_imp(a, constants::half(), xb, pol, false, true, &f1) + : ibeta_imp(constants::half(), a, y, pol, true, true, &f1); - // Get cdf from incomplete beta result: - T p0 = f0 / 2 - p; - // Get pdf from derivative: - T p1 = f1 * sqrt(y * xb * xb * xb / df); - // - // Second derivative divided by p1: - // - // yacas gives: - // - // In> PrettyForm(Simplify(D(t) (1 + t^2/v) ^ (-(v+1)/2))) - // - // | | v + 1 | | - // | -| ----- + 1 | | - // | | 2 | | - // -| | 2 | | - // | | t | | - // | | -- + 1 | | - // | ( v + 1 ) * | v | * t | - // --------------------------------------------- - // v - // - // Which after some manipulation is: - // - // -p1 * t * (df + 1) / (t^2 + df) - // - T p2 = t * (df + 1) / (t * t + df); - // Halley step: - t = fabs(t); - t += p0 / (p1 + p0 * p2 / 2); - return !invert ? -t : t; + // Get cdf from incomplete beta result: + T p0 = f0 / 2 - p; + // Get pdf from derivative: + T rxb = sqrt(xb); + T p1 = f1 * sqrt(y / df); + p1 *= rxb; + p1 *= rxb; + p1 *= rxb; + // If p1 has underflowed, all subsequent calculations will fail: + if (p1 < tools::min_value()) + return invert ? -t : t; + // + // Second derivative divided by p1: + // + // yacas gives: + // + // In> PrettyForm(Simplify(D(t) (1 + t^2/v) ^ (-(v+1)/2))) + // + // | | v + 1 | | + // | -| ----- + 1 | | + // | | 2 | | + // -| | 2 | | + // | | t | | + // | | -- + 1 | | + // | ( v + 1 ) * | v | * t | + // --------------------------------------------- + // v + // + // Which after some manipulation is: + // + // -p1 * t * (df + 1) / (t^2 + df) + // + T p2 = t * (df + 1) / (t * t + df); + // Halley step: + T step = p0 / (p1 + p0 * p2 / 2); + t -= step; + // + // The series estimates used for non-integer df between 2 and 3 are + // only good to about 1e-5, which a single Halley step can't fix, + // so repeat if the step was large: + // + if (fabs(step) < 1e-7f * fabs(t)) + break; + } + return invert ? -t : t; } template @@ -549,17 +566,17 @@ BOOST_MATH_GPU_ENABLED inline T fast_students_t_quantile(T df, T p, const Policy policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; - typedef boost::math::integral_constant::digits <= 53) + typedef BOOST_MATH_NAMESPACE::integral_constant::digits <= 53) && - (boost::math::numeric_limits::is_specialized) + (BOOST_MATH_NAMESPACE::numeric_limits::is_specialized) && - (boost::math::numeric_limits::radix == 2) + (BOOST_MATH_NAMESPACE::numeric_limits::radix == 2) > tag_type; return policies::checked_narrowing_cast(fast_students_t_quantile_imp(static_cast(df), static_cast(p), pol, static_cast(nullptr)), "boost::math::students_t_quantile<%1%>(%1%,%1%,%1%)"); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SF_DETAIL_INV_T_HPP diff --git a/include/boost/math/special_functions/detail/unchecked_bernoulli.hpp b/include/boost/math/special_functions/detail/unchecked_bernoulli.hpp index 676332983a..1cae06e003 100644 --- a/include/boost/math/special_functions/detail/unchecked_bernoulli.hpp +++ b/include/boost/math/special_functions/detail/unchecked_bernoulli.hpp @@ -11,16 +11,18 @@ #ifndef BOOST_MATH_UNCHECKED_BERNOULLI_HPP #define BOOST_MATH_UNCHECKED_BERNOULLI_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include +#endif #include #include #include -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -78,7 +80,7 @@ struct bernoulli_imp_variant } // namespace detail -template +BOOST_MATH_EXPORT template struct max_bernoulli_b2n : public detail::max_bernoulli_index::value>{}; namespace detail { @@ -1292,7 +1294,7 @@ inline T unchecked_bernoulli_imp(std::size_t n, const std::integral_constant +BOOST_MATH_EXPORT template inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_b2n(const std::size_t n) { typedef std::integral_constant::value> tag_type; @@ -1300,6 +1302,6 @@ inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_b2n(const std:: return detail::unchecked_bernoulli_imp(n, tag_type()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_UNCHECKED_BERNOULLI_HPP diff --git a/include/boost/math/special_functions/detail/unchecked_factorial.hpp b/include/boost/math/special_functions/detail/unchecked_factorial.hpp index 12487eae05..d910c71275 100644 --- a/include/boost/math/special_functions/detail/unchecked_factorial.hpp +++ b/include/boost/math/special_functions/detail/unchecked_factorial.hpp @@ -38,10 +38,9 @@ #pragma GCC system_header #endif -namespace boost { namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN // Forward declarations: -template +BOOST_MATH_EXPORT template struct max_factorial; // // see https://github.com/boostorg/math/issues/923 @@ -53,7 +52,7 @@ struct unchecked_factorial_data; #ifdef BOOST_MATH_HAS_NVRTC // Need fwd decl -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T unchecked_factorial(unsigned i); #endif @@ -64,7 +63,7 @@ template struct unchecked_factorial_data { #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES - static constexpr boost::math::array factorials = { { + static constexpr BOOST_MATH_NAMESPACE::array factorials = { { 1.0F, 1.0F, 2.0F, @@ -102,15 +101,15 @@ struct unchecked_factorial_data 0.29523279903960414084761860964352e39F, }}; #else - static const boost::math::array factorials; + static const BOOST_MATH_NAMESPACE::array factorials; #endif }; template #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES - constexpr boost::math::array unchecked_factorial_data::factorials; + constexpr BOOST_MATH_NAMESPACE::array unchecked_factorial_data::factorials; #else - const boost::math::array unchecked_factorial_data::factorials = {{ + const BOOST_MATH_NAMESPACE::array unchecked_factorial_data::factorials = {{ 1.0F, 1.0F, 2.0F, @@ -216,7 +215,7 @@ template struct unchecked_factorial_data { #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES - static constexpr boost::math::array factorials = { { + static constexpr BOOST_MATH_NAMESPACE::array factorials = { { 1.0, 1.0, 2.0, @@ -390,15 +389,15 @@ struct unchecked_factorial_data 0.7257415615307998967396728211129263114717e307, }}; #else - static const boost::math::array factorials; + static const BOOST_MATH_NAMESPACE::array factorials; #endif }; template #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES - constexpr boost::math::array unchecked_factorial_data::factorials; + constexpr BOOST_MATH_NAMESPACE::array unchecked_factorial_data::factorials; #else - const boost::math::array unchecked_factorial_data::factorials = {{ + const BOOST_MATH_NAMESPACE::array unchecked_factorial_data::factorials = {{ 1.0, 1.0, 2.0, @@ -645,7 +644,7 @@ template struct unchecked_factorial_data { #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES - static constexpr boost::math::array factorials = { { + static constexpr BOOST_MATH_NAMESPACE::array factorials = { { 1L, 1L, 2L, @@ -819,15 +818,15 @@ struct unchecked_factorial_data 0.7257415615307998967396728211129263114717e307L, }}; #else - static const boost::math::array factorials; + static const BOOST_MATH_NAMESPACE::array factorials; #endif }; template #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES - constexpr boost::math::array unchecked_factorial_data::factorials; + constexpr BOOST_MATH_NAMESPACE::array unchecked_factorial_data::factorials; #else - const boost::math::array unchecked_factorial_data::factorials = {{ + const BOOST_MATH_NAMESPACE::array unchecked_factorial_data::factorials = {{ 1L, 1L, 2L, @@ -1020,7 +1019,7 @@ template struct unchecked_factorial_data { #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES - static constexpr boost::math::array factorials = { { + static constexpr BOOST_MATH_NAMESPACE::array factorials = { { 1, 1, 2, @@ -1194,15 +1193,15 @@ struct unchecked_factorial_data 0.7257415615307998967396728211129263114717e307Q, } }; #else - static const boost::math::array factorials; + static const BOOST_MATH_NAMESPACE::array factorials; #endif }; template #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES -constexpr boost::math::array unchecked_factorial_data::factorials; +constexpr BOOST_MATH_NAMESPACE::array unchecked_factorial_data::factorials; #else -const boost::math::array unchecked_factorial_data::factorials = { { +const BOOST_MATH_NAMESPACE::array unchecked_factorial_data::factorials = { { 1, 1, 2, @@ -1392,7 +1391,7 @@ struct max_factorial #endif template -inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constant&) +inline T unchecked_factorial_imp(unsigned i, const BOOST_MATH_NAMESPACE::integral_constant&) { // // If you're foolish enough to instantiate factorial @@ -1406,118 +1405,118 @@ inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constan // unsigned int nfac = static_cast(factorial(n)); // See factorial documentation for more detail. // - static_assert(!boost::math::is_integral::value && !boost::math::numeric_limits::is_integer, "Type T must not be an integral type"); + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value && !BOOST_MATH_NAMESPACE::numeric_limits::is_integer, "Type T must not be an integral type"); // We rely on C++11 thread safe initialization here: - static const boost::math::array factorials = {{ - T(boost::math::tools::convert_from_string("1")), - T(boost::math::tools::convert_from_string("1")), - T(boost::math::tools::convert_from_string("2")), - T(boost::math::tools::convert_from_string("6")), - T(boost::math::tools::convert_from_string("24")), - T(boost::math::tools::convert_from_string("120")), - T(boost::math::tools::convert_from_string("720")), - T(boost::math::tools::convert_from_string("5040")), - T(boost::math::tools::convert_from_string("40320")), - T(boost::math::tools::convert_from_string("362880")), - T(boost::math::tools::convert_from_string("3628800")), - T(boost::math::tools::convert_from_string("39916800")), - T(boost::math::tools::convert_from_string("479001600")), - T(boost::math::tools::convert_from_string("6227020800")), - T(boost::math::tools::convert_from_string("87178291200")), - T(boost::math::tools::convert_from_string("1307674368000")), - T(boost::math::tools::convert_from_string("20922789888000")), - T(boost::math::tools::convert_from_string("355687428096000")), - T(boost::math::tools::convert_from_string("6402373705728000")), - T(boost::math::tools::convert_from_string("121645100408832000")), - T(boost::math::tools::convert_from_string("2432902008176640000")), - T(boost::math::tools::convert_from_string("51090942171709440000")), - T(boost::math::tools::convert_from_string("1124000727777607680000")), - T(boost::math::tools::convert_from_string("25852016738884976640000")), - T(boost::math::tools::convert_from_string("620448401733239439360000")), - T(boost::math::tools::convert_from_string("15511210043330985984000000")), - T(boost::math::tools::convert_from_string("403291461126605635584000000")), - T(boost::math::tools::convert_from_string("10888869450418352160768000000")), - T(boost::math::tools::convert_from_string("304888344611713860501504000000")), - T(boost::math::tools::convert_from_string("8841761993739701954543616000000")), - T(boost::math::tools::convert_from_string("265252859812191058636308480000000")), - T(boost::math::tools::convert_from_string("8222838654177922817725562880000000")), - T(boost::math::tools::convert_from_string("263130836933693530167218012160000000")), - T(boost::math::tools::convert_from_string("8683317618811886495518194401280000000")), - T(boost::math::tools::convert_from_string("295232799039604140847618609643520000000")), - T(boost::math::tools::convert_from_string("10333147966386144929666651337523200000000")), - T(boost::math::tools::convert_from_string("371993326789901217467999448150835200000000")), - T(boost::math::tools::convert_from_string("13763753091226345046315979581580902400000000")), - T(boost::math::tools::convert_from_string("523022617466601111760007224100074291200000000")), - T(boost::math::tools::convert_from_string("20397882081197443358640281739902897356800000000")), - T(boost::math::tools::convert_from_string("815915283247897734345611269596115894272000000000")), - T(boost::math::tools::convert_from_string("33452526613163807108170062053440751665152000000000")), - T(boost::math::tools::convert_from_string("1405006117752879898543142606244511569936384000000000")), - T(boost::math::tools::convert_from_string("60415263063373835637355132068513997507264512000000000")), - T(boost::math::tools::convert_from_string("2658271574788448768043625811014615890319638528000000000")), - T(boost::math::tools::convert_from_string("119622220865480194561963161495657715064383733760000000000")), - T(boost::math::tools::convert_from_string("5502622159812088949850305428800254892961651752960000000000")), - T(boost::math::tools::convert_from_string("258623241511168180642964355153611979969197632389120000000000")), - T(boost::math::tools::convert_from_string("12413915592536072670862289047373375038521486354677760000000000")), - T(boost::math::tools::convert_from_string("608281864034267560872252163321295376887552831379210240000000000")), - T(boost::math::tools::convert_from_string("30414093201713378043612608166064768844377641568960512000000000000")), - T(boost::math::tools::convert_from_string("1551118753287382280224243016469303211063259720016986112000000000000")), - T(boost::math::tools::convert_from_string("80658175170943878571660636856403766975289505440883277824000000000000")), - T(boost::math::tools::convert_from_string("4274883284060025564298013753389399649690343788366813724672000000000000")), - T(boost::math::tools::convert_from_string("230843697339241380472092742683027581083278564571807941132288000000000000")), - T(boost::math::tools::convert_from_string("12696403353658275925965100847566516959580321051449436762275840000000000000")), - T(boost::math::tools::convert_from_string("710998587804863451854045647463724949736497978881168458687447040000000000000")), - T(boost::math::tools::convert_from_string("40526919504877216755680601905432322134980384796226602145184481280000000000000")), - T(boost::math::tools::convert_from_string("2350561331282878571829474910515074683828862318181142924420699914240000000000000")), - T(boost::math::tools::convert_from_string("138683118545689835737939019720389406345902876772687432540821294940160000000000000")), - T(boost::math::tools::convert_from_string("8320987112741390144276341183223364380754172606361245952449277696409600000000000000")), - T(boost::math::tools::convert_from_string("507580213877224798800856812176625227226004528988036003099405939480985600000000000000")), - T(boost::math::tools::convert_from_string("31469973260387937525653122354950764088012280797258232192163168247821107200000000000000")), - T(boost::math::tools::convert_from_string("1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000")), - T(boost::math::tools::convert_from_string("126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000")), - T(boost::math::tools::convert_from_string("8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000")), - T(boost::math::tools::convert_from_string("544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000")), - T(boost::math::tools::convert_from_string("36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000")), - T(boost::math::tools::convert_from_string("2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000")), - T(boost::math::tools::convert_from_string("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000")), - T(boost::math::tools::convert_from_string("11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000")), - T(boost::math::tools::convert_from_string("850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000")), - T(boost::math::tools::convert_from_string("61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000")), - T(boost::math::tools::convert_from_string("4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000")), - T(boost::math::tools::convert_from_string("330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000")), - T(boost::math::tools::convert_from_string("24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000")), - T(boost::math::tools::convert_from_string("1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000")), - T(boost::math::tools::convert_from_string("145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000")), - T(boost::math::tools::convert_from_string("11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000")), - T(boost::math::tools::convert_from_string("894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000")), - T(boost::math::tools::convert_from_string("71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000")), - T(boost::math::tools::convert_from_string("5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000")), - T(boost::math::tools::convert_from_string("475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000")), - T(boost::math::tools::convert_from_string("39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000")), - T(boost::math::tools::convert_from_string("3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000")), - T(boost::math::tools::convert_from_string("281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000")), - T(boost::math::tools::convert_from_string("24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000")), - T(boost::math::tools::convert_from_string("2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000")), - T(boost::math::tools::convert_from_string("185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000")), - T(boost::math::tools::convert_from_string("16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000")), - T(boost::math::tools::convert_from_string("1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000")), - T(boost::math::tools::convert_from_string("135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000")), - T(boost::math::tools::convert_from_string("12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000")), - T(boost::math::tools::convert_from_string("1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000")), - T(boost::math::tools::convert_from_string("108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000")), - T(boost::math::tools::convert_from_string("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000")), - T(boost::math::tools::convert_from_string("991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000")), - T(boost::math::tools::convert_from_string("96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000")), - T(boost::math::tools::convert_from_string("9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000")), - T(boost::math::tools::convert_from_string("933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000")), - T(boost::math::tools::convert_from_string("93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000")), + static const BOOST_MATH_NAMESPACE::array factorials = {{ + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("2")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("6")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("24")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("120")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("720")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("5040")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("40320")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("362880")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("3628800")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("39916800")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("479001600")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("6227020800")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("87178291200")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1307674368000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("20922789888000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("355687428096000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("6402373705728000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("121645100408832000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("2432902008176640000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("51090942171709440000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1124000727777607680000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("25852016738884976640000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("620448401733239439360000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("15511210043330985984000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("403291461126605635584000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("10888869450418352160768000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("304888344611713860501504000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("8841761993739701954543616000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("265252859812191058636308480000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("8222838654177922817725562880000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("263130836933693530167218012160000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("8683317618811886495518194401280000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("295232799039604140847618609643520000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("10333147966386144929666651337523200000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("371993326789901217467999448150835200000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("13763753091226345046315979581580902400000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("523022617466601111760007224100074291200000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("20397882081197443358640281739902897356800000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("815915283247897734345611269596115894272000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("33452526613163807108170062053440751665152000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1405006117752879898543142606244511569936384000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("60415263063373835637355132068513997507264512000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("2658271574788448768043625811014615890319638528000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("119622220865480194561963161495657715064383733760000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("5502622159812088949850305428800254892961651752960000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("258623241511168180642964355153611979969197632389120000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("12413915592536072670862289047373375038521486354677760000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("608281864034267560872252163321295376887552831379210240000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("30414093201713378043612608166064768844377641568960512000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1551118753287382280224243016469303211063259720016986112000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("80658175170943878571660636856403766975289505440883277824000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("4274883284060025564298013753389399649690343788366813724672000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("230843697339241380472092742683027581083278564571807941132288000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("12696403353658275925965100847566516959580321051449436762275840000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("710998587804863451854045647463724949736497978881168458687447040000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("40526919504877216755680601905432322134980384796226602145184481280000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("2350561331282878571829474910515074683828862318181142924420699914240000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("138683118545689835737939019720389406345902876772687432540821294940160000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("8320987112741390144276341183223364380754172606361245952449277696409600000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("507580213877224798800856812176625227226004528988036003099405939480985600000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("31469973260387937525653122354950764088012280797258232192163168247821107200000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000")), + T(BOOST_MATH_NAMESPACE::tools::convert_from_string("93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000")), }}; return factorials[i]; } template -inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constant&) +inline T unchecked_factorial_imp(unsigned i, const BOOST_MATH_NAMESPACE::integral_constant&) { // // If you're foolish enough to instantiate factorial @@ -1531,7 +1530,7 @@ inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constan // unsigned int nfac = static_cast(factorial(n)); // See factorial documentation for more detail. // - static_assert(!boost::math::is_integral::value && !boost::math::numeric_limits::is_integer, "Type T must not be an integral type"); + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value && !BOOST_MATH_NAMESPACE::numeric_limits::is_integer, "Type T must not be an integral type"); static const char* const factorial_strings[] = { "1", @@ -1642,13 +1641,13 @@ inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constan static BOOST_MATH_THREAD_LOCAL T factorials[sizeof(factorial_strings) / sizeof(factorial_strings[0])]; static BOOST_MATH_THREAD_LOCAL int digits = 0; - int current_digits = boost::math::tools::digits(); + int current_digits = BOOST_MATH_NAMESPACE::tools::digits(); if(digits != current_digits) { digits = current_digits; for(unsigned k = 0; k < sizeof(factorials) / sizeof(factorials[0]); ++k) - factorials[k] = static_cast(boost::math::tools::convert_from_string(factorial_strings[k])); + factorials[k] = static_cast(BOOST_MATH_NAMESPACE::tools::convert_from_string(factorial_strings[k])); } return factorials[i]; @@ -1657,13 +1656,13 @@ inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constan #endif // BOOST_MATH_HAS_GPU_SUPPORT template -BOOST_MATH_GPU_ENABLED inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constant::digits>&) +BOOST_MATH_GPU_ENABLED inline T unchecked_factorial_imp(unsigned i, const BOOST_MATH_NAMESPACE::integral_constant::digits>&) { return unchecked_factorial(i); } template -BOOST_MATH_GPU_ENABLED inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constant::digits>&) +BOOST_MATH_GPU_ENABLED inline T unchecked_factorial_imp(unsigned i, const BOOST_MATH_NAMESPACE::integral_constant::digits>&) { return unchecked_factorial(i); } @@ -1672,14 +1671,14 @@ BOOST_MATH_GPU_ENABLED inline T unchecked_factorial_imp(unsigned i, const boost: #if DBL_MANT_DIG != LDBL_MANT_DIG template -inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constant&) +inline T unchecked_factorial_imp(unsigned i, const BOOST_MATH_NAMESPACE::integral_constant&) { return unchecked_factorial(i); } #endif #ifdef BOOST_MATH_USE_FLOAT128 template -inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constant&) +inline T unchecked_factorial_imp(unsigned i, const BOOST_MATH_NAMESPACE::integral_constant&) { return unchecked_factorial(i); } @@ -1687,27 +1686,27 @@ inline T unchecked_factorial_imp(unsigned i, const boost::math::integral_constan #endif // BOOST_MATH_HAS_GPU_SUPPORT -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T unchecked_factorial(unsigned i) { - typedef typename boost::math::policies::precision >::type tag_type; + typedef typename BOOST_MATH_NAMESPACE::policies::precision >::type tag_type; return unchecked_factorial_imp(i, tag_type()); } #ifdef BOOST_MATH_USE_FLOAT128 -#define BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL : boost::math::numeric_limits::digits == 113 ? max_factorial::value +#define BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL : BOOST_MATH_NAMESPACE::numeric_limits::digits == 113 ? max_factorial::value #else #define BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL #endif -template +BOOST_MATH_EXPORT template struct max_factorial { static constexpr unsigned value = - boost::math::numeric_limits::digits == boost::math::numeric_limits::digits ? max_factorial::value - : boost::math::numeric_limits::digits == boost::math::numeric_limits::digits ? max_factorial::value + BOOST_MATH_NAMESPACE::numeric_limits::digits == BOOST_MATH_NAMESPACE::numeric_limits::digits ? max_factorial::value + : BOOST_MATH_NAMESPACE::numeric_limits::digits == BOOST_MATH_NAMESPACE::numeric_limits::digits ? max_factorial::value #ifndef BOOST_MATH_GPU_ENABLED - : boost::math::numeric_limits::digits == boost::math::numeric_limits::digits ? max_factorial::value + : BOOST_MATH_NAMESPACE::numeric_limits::digits == BOOST_MATH_NAMESPACE::numeric_limits::digits ? max_factorial::value BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL #endif : 100; @@ -1720,8 +1719,7 @@ template constexpr unsigned max_factorial::value; #endif -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SP_UC_FACTORIALS_HPP diff --git a/include/boost/math/special_functions/digamma.hpp b/include/boost/math/special_functions/digamma.hpp index 718bd45529..04c5b8e098 100644 --- a/include/boost/math/special_functions/digamma.hpp +++ b/include/boost/math/special_functions/digamma.hpp @@ -23,6 +23,7 @@ #ifndef BOOST_MATH_HAS_NVRTC #include +#include #include #include #include @@ -39,16 +40,15 @@ #pragma GCC system_header #endif -namespace boost{ -namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // // Begin by defining the smallest value for which it is safe to // use the asymptotic expansion for digamma: // -BOOST_MATH_GPU_ENABLED inline unsigned digamma_large_lim(const boost::math::integral_constant*) +BOOST_MATH_GPU_ENABLED inline unsigned digamma_large_lim(const BOOST_MATH_NAMESPACE::integral_constant*) { return 20; } -BOOST_MATH_GPU_ENABLED inline unsigned digamma_large_lim(const boost::math::integral_constant*) +BOOST_MATH_GPU_ENABLED inline unsigned digamma_large_lim(const BOOST_MATH_NAMESPACE::integral_constant*) { return 20; } BOOST_MATH_GPU_ENABLED inline unsigned digamma_large_lim(const void*) { return 10; } @@ -65,7 +65,7 @@ BOOST_MATH_GPU_ENABLED inline unsigned digamma_large_lim(const void*) #ifndef BOOST_MATH_HAS_NVRTC template -inline T digamma_imp_large(T x, const boost::math::integral_constant*) +inline T digamma_imp_large(T x, const BOOST_MATH_NAMESPACE::integral_constant*) { BOOST_MATH_STD_USING // ADL of std functions. static const T P[] = { @@ -98,7 +98,7 @@ inline T digamma_imp_large(T x, const boost::math::integral_constant*) // 19-digit precision for x >= 10: // template -inline T digamma_imp_large(T x, const boost::math::integral_constant*) +inline T digamma_imp_large(T x, const BOOST_MATH_NAMESPACE::integral_constant*) { BOOST_MATH_STD_USING // ADL of std functions. static const T P[] = { @@ -126,7 +126,7 @@ inline T digamma_imp_large(T x, const boost::math::integral_constant*) // 17-digit precision for x >= 10: // template -BOOST_MATH_GPU_ENABLED inline T digamma_imp_large(T x, const boost::math::integral_constant*) +BOOST_MATH_GPU_ENABLED inline T digamma_imp_large(T x, const BOOST_MATH_NAMESPACE::integral_constant*) { BOOST_MATH_STD_USING // ADL of std functions. BOOST_MATH_STATIC const T P[] = { @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline T digamma_imp_large(T x, const boost::math::integr // 9-digit precision for x >= 10: // template -BOOST_MATH_GPU_ENABLED inline T digamma_imp_large(T x, const boost::math::integral_constant*) +BOOST_MATH_GPU_ENABLED inline T digamma_imp_large(T x, const BOOST_MATH_NAMESPACE::integral_constant*) { BOOST_MATH_STD_USING // ADL of std functions. BOOST_MATH_STATIC const T P[] = { @@ -183,7 +183,7 @@ struct digamma_series_func digamma_series_func(T x) : k(1), xx(x * x), term(1 / (x * x)) {} T operator()() { - T result = term * boost::math::bernoulli_b2n(k) / (2 * k); + T result = term * BOOST_MATH_NAMESPACE::bernoulli_b2n(k) / (2 * k); term /= xx; ++k; return result; @@ -192,13 +192,13 @@ struct digamma_series_func }; template -inline T digamma_imp_large(T x, const Policy& pol, const boost::math::integral_constant*) +inline T digamma_imp_large(T x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant*) { BOOST_MATH_STD_USING digamma_series_func s(x); T result = log(x) - 1 / (2 * x); std::uintmax_t max_iter = policies::get_max_series_iterations(); - result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter, -result); + result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter, -result); result = -result; policies::check_series_iterations("boost::math::digamma<%1%>(%1%)", max_iter, pol); return result; @@ -210,7 +210,7 @@ inline T digamma_imp_large(T x, const Policy& pol, const boost::math::integral_c // 35-digit precision: // template -T digamma_imp_1_2(T x, const boost::math::integral_constant*) +T digamma_imp_1_2(T x, const BOOST_MATH_NAMESPACE::integral_constant*) { // // Now the approximation, we use the form: @@ -274,7 +274,7 @@ T digamma_imp_1_2(T x, const boost::math::integral_constant*) // 19-digit precision: // template -T digamma_imp_1_2(T x, const boost::math::integral_constant*) +T digamma_imp_1_2(T x, const BOOST_MATH_NAMESPACE::integral_constant*) { // // Now the approximation, we use the form: @@ -328,7 +328,7 @@ T digamma_imp_1_2(T x, const boost::math::integral_constant*) // 18-digit precision: // template -BOOST_MATH_GPU_ENABLED T digamma_imp_1_2(T x, const boost::math::integral_constant*) +BOOST_MATH_GPU_ENABLED T digamma_imp_1_2(T x, const BOOST_MATH_NAMESPACE::integral_constant*) { // // Now the approximation, we use the form: @@ -379,7 +379,7 @@ BOOST_MATH_GPU_ENABLED T digamma_imp_1_2(T x, const boost::math::integral_consta // 9-digit precision: // template -BOOST_MATH_GPU_ENABLED inline T digamma_imp_1_2(T x, const boost::math::integral_constant*) +BOOST_MATH_GPU_ENABLED inline T digamma_imp_1_2(T x, const BOOST_MATH_NAMESPACE::integral_constant*) { // // Now the approximation, we use the form: @@ -490,7 +490,7 @@ BOOST_MATH_GPU_ENABLED T digamma_imp(T x, const Tag* t, const Policy& pol) // LCOV_EXCL_START template -T digamma_imp(T x, const boost::math::integral_constant* t, const Policy& pol) +T digamma_imp(T x, const BOOST_MATH_NAMESPACE::integral_constant* t, const Policy& pol) { // // This handles reflection of negative arguments, and all our @@ -590,14 +590,14 @@ T digamma_imp(T x, const boost::math::integral_constant* t, const Policy } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type digamma(T x, const Policy&) { typedef typename tools::promote_args::type result_type; typedef typename policies::evaluation::type value_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant 113) ? 0 : precision_type::value <= 24 ? 24 : precision_type::value <= 53 ? 53 : @@ -613,15 +613,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::digamma_imp(static_cast(x), static_cast(nullptr), forwarding_policy()), "boost::math::digamma<%1%>(%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type digamma(T x) { return digamma(x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/ellint_1.hpp b/include/boost/math/special_functions/ellint_1.hpp index 96c7c9e9b9..2425d29356 100644 --- a/include/boost/math/special_functions/ellint_1.hpp +++ b/include/boost/math/special_functions/ellint_1.hpp @@ -31,19 +31,19 @@ // Elliptic integrals (complete and incomplete) of the first kind // Carlson, Numerische Mathematik, vol 33, 1 (1979) -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T1 k, T2 phi, const Policy& pol); namespace detail{ template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant const&); +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, BOOST_MATH_NAMESPACE::integral_constant const&); template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant const&); +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, BOOST_MATH_NAMESPACE::integral_constant const&); template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant const&); +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, BOOST_MATH_NAMESPACE::integral_constant const&); template BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, T one_minus_k2); @@ -52,8 +52,8 @@ template BOOST_MATH_GPU_ENABLED T ellint_f_imp(T phi, T k, const Policy& pol, T one_minus_k2) { BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; constexpr auto function = "boost::math::ellint_f<%1%>(%1%,%1%)"; BOOST_MATH_INSTRUMENT_VARIABLE(phi); @@ -93,12 +93,12 @@ BOOST_MATH_GPU_ENABLED T ellint_f_imp(T phi, T k, const Policy& pol, T one_minus // so rewritten to use fmod instead: // BOOST_MATH_INSTRUMENT_CODE("pi/2 = " << constants::pi() / 2); - T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi())); + T rphi = BOOST_MATH_NAMESPACE::tools::fmod_workaround(phi, T(constants::half_pi())); BOOST_MATH_INSTRUMENT_VARIABLE(rphi); - T m = boost::math::round((phi - rphi) / constants::half_pi()); + T m = BOOST_MATH_NAMESPACE::round((phi - rphi) / constants::half_pi()); BOOST_MATH_INSTRUMENT_VARIABLE(m); int s = 1; - if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5)) + if(BOOST_MATH_NAMESPACE::tools::fmod_workaround(m, T(2)) > T(0.5)) { m += 1; s = -1; @@ -162,7 +162,7 @@ template BOOST_MATH_GPU_ENABLED T ellint_k_imp(T k, const Policy& pol, T one_minus_k2) { BOOST_MATH_STD_USING - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; constexpr auto function = "boost::math::ellint_k<%1%>(%1%)"; @@ -182,7 +182,7 @@ BOOST_MATH_GPU_ENABLED T ellint_k_imp(T k, const Policy& pol, T one_minus_k2) return value; } template -BOOST_MATH_GPU_ENABLED inline T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant const&) +BOOST_MATH_GPU_ENABLED inline T ellint_k_imp(T k, const Policy& pol, BOOST_MATH_NAMESPACE::integral_constant const&) { return ellint_k_imp(k, pol, T(1 - k * k)); } @@ -204,10 +204,10 @@ BOOST_MATH_GPU_ENABLED inline T ellint_k_imp(T k, const Policy& pol, boost::math // archived in the code below), but was found to have slightly higher error rates. // template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant const&) +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, BOOST_MATH_NAMESPACE::integral_constant const&) { BOOST_MATH_STD_USING - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; T m = k * k; @@ -232,7 +232,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(0.081541118718303215), static_cast(0.078199656811256481910) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.05)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.05)); } case 2: case 3: @@ -253,7 +253,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(0.248557682972264071), static_cast(0.266363809892617521) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.15)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.15)); } case 4: case 5: @@ -274,7 +274,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(0.871013847709812357), static_cast(1.057652872753547036) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.25)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.25)); } case 6: case 7: @@ -296,7 +296,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(5.115867135558865806), static_cast(7.224080007363877411) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.35)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.35)); } case 8: case 9: @@ -319,7 +319,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(53.73749198700554656), static_cast(90.27388602940998849) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.45)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.45)); } case 10: case 11: @@ -343,7 +343,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(1228.420013075863451), static_cast(2536.529755382764488) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.55)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.55)); } case 12: case 13: @@ -369,7 +369,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(228672.1890493117096), static_cast(612757.2711915852774) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.65)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.65)); } case 14: case 15: @@ -398,7 +398,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(1901975729.538660119), static_cast(7208915015.330103756) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.75)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.75)); } case 16: //else if (m < static_cast(0.85)) @@ -422,7 +422,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(1408862325.028702687), static_cast(7515687935.373774627) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.825)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.825)); } case 17: //else if (m < static_cast(0.90)) @@ -450,20 +450,20 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& static_cast(499488053713388.7989), static_cast(37859743397240299.20) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.875)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.875)); } default: // // This handles all cases where m > 0.9, // including all error handling: // - return ellint_k_imp(k, pol, boost::math::integral_constant()); + return ellint_k_imp(k, pol, BOOST_MATH_NAMESPACE::integral_constant()); #if 0 else { T lambda_prime = (1 - sqrt(k)) / (2 * (1 + sqrt(k))); T k_prime = ellint_k(sqrt((1 - k) * (1 + k))); // K(m') - T lambda_prime_4th = boost::math::pow<4>(lambda_prime); + T lambda_prime_4th = BOOST_MATH_NAMESPACE::pow<4>(lambda_prime); T q_prime = ((((((20910 * lambda_prime_4th) + 1707) * lambda_prime_4th + 150) * lambda_prime_4th + 15) * lambda_prime_4th + 2) * lambda_prime_4th + 1) * lambda_prime; /*T q_prime_2 = lambda_prime + 2 * boost::math::pow<5>(lambda_prime) @@ -471,16 +471,16 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& + 150 * boost::math::pow<13>(lambda_prime) + 1707 * boost::math::pow<17>(lambda_prime) + 20910 * boost::math::pow<21>(lambda_prime);*/ - return -log(q_prime) * k_prime / boost::math::constants::pi(); + return -log(q_prime) * k_prime / BOOST_MATH_NAMESPACE::constants::pi(); } #endif } } template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant const&) +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, BOOST_MATH_NAMESPACE::integral_constant const&) { BOOST_MATH_STD_USING - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; T m = k * k; switch (static_cast(m * 20)) @@ -505,7 +505,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 0.075592617535422415648L, 0.073562939365441925050L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.05L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.05L); } case 2: case 3: @@ -528,7 +528,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 0.31290024539780334906L, 0.34223105446381299902L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.15L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.15L); } case 4: case 5: @@ -552,7 +552,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 1.9772844873556364793L, 2.4628890581910021287L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.25L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.25L); } case 6: case 7: @@ -577,7 +577,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 21.104114212004582734L, 30.460132808575799413L, }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.35L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.35L); } case 8: case 9: @@ -603,7 +603,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 441.78537518096201946L, 756.39903981567380952L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.45L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.45L); } case 10: case 11: @@ -630,7 +630,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 22958.388550988306870L, 48203.103373625406989L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.55L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.55L); } case 12: case 13: @@ -659,7 +659,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 1.2046317340783185238e7L, 3.2705187507963254185e7L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.65L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.65L); } case 14: case 15: @@ -692,7 +692,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 1.5254661585564745591e12L, 5.8483259088850315936e12 }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.75L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.75L); } case 16: { @@ -719,7 +719,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 1.1692489201929996116e12L, 6.3306543358985679881e12 }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.825L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.825L); } case 17: { @@ -751,43 +751,43 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& 1.2814410112866546052e19L, 9.8249807041031260167e19 }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.875L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.875L); } default: // // All cases where m > 0.9 // including all error handling: // - return ellint_k_imp(k, pol, boost::math::integral_constant()); + return ellint_k_imp(k, pol, BOOST_MATH_NAMESPACE::integral_constant()); } } template -BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T k, const Policy& pol, const boost::math::true_type&) +BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T k, const Policy& pol, const BOOST_MATH_NAMESPACE::true_type&) { typedef typename tools::promote_args::type result_type; typedef typename policies::evaluation::type value_type; - typedef boost::math::integral_constant::value && boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 54) ? 0 : - boost::math::is_floating_point::value && boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 64) ? 1 : 2 + BOOST_MATH_NAMESPACE::is_floating_point::value && BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 54) ? 0 : + BOOST_MATH_NAMESPACE::is_floating_point::value && BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 64) ? 1 : 2 #endif > precision_tag_type; return policies::checked_narrowing_cast(detail::ellint_k_imp(static_cast(k), pol, precision_tag_type()), "boost::math::ellint_1<%1%>(%1%)"); } template -BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T1 k, T2 phi, const boost::math::false_type&) +BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T1 k, T2 phi, const BOOST_MATH_NAMESPACE::false_type&) { - return boost::math::ellint_1(k, phi, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ellint_1(k, phi, policies::policy<>()); } } // namespace detail // Elliptic integral (Legendre form) of the first kind -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T1 k, T2 phi, const Policy& pol) // LCOV_EXCL_LINE gcc misses this but sees the function body, strange! { typedef typename tools::promote_args::type result_type; @@ -795,7 +795,7 @@ BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T1 k, return policies::checked_narrowing_cast(detail::ellint_f_imp(static_cast(phi), static_cast(k), pol), "boost::math::ellint_1<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T1 k, T2 phi) { typedef typename policies::is_policy::type tag_type; @@ -803,13 +803,13 @@ BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T1 k, } // Complete elliptic integral (Legendre form) of the first kind -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_1(T k) { return ellint_1(k, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_1_HPP diff --git a/include/boost/math/special_functions/ellint_2.hpp b/include/boost/math/special_functions/ellint_2.hpp index 501d36b66b..70439045db 100644 --- a/include/boost/math/special_functions/ellint_2.hpp +++ b/include/boost/math/special_functions/ellint_2.hpp @@ -34,27 +34,27 @@ // Elliptic integrals (complete and incomplete) of the second kind // Carlson, Numerische Mathematik, vol 33, 1 (1979) -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_2(T1 k, T2 phi, const Policy& pol); namespace detail{ template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, const boost::math::integral_constant&); +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&); template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, const boost::math::integral_constant&); +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&); template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, const boost::math::integral_constant&); +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&); // Elliptic integral (Legendre form) of the second kind template BOOST_MATH_GPU_ENABLED T ellint_e_imp(T phi, T k, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; bool invert = false; if (phi == 0) @@ -75,9 +75,9 @@ BOOST_MATH_GPU_ENABLED T ellint_e_imp(T phi, T k, const Policy& pol) } else if(phi > 1 / tools::epsilon()) { - typedef boost::math::integral_constant::value&& boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 54) ? 0 : - boost::math::is_floating_point::value && boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 64) ? 1 : 2 + typedef BOOST_MATH_NAMESPACE::integral_constant::value&& BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 54) ? 0 : + BOOST_MATH_NAMESPACE::is_floating_point::value && BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 64) ? 1 : 2 > precision_tag_type; // Phi is so large that phi%pi is necessarily zero (or garbage), // just return the second part of the duplication formula: @@ -96,8 +96,8 @@ BOOST_MATH_GPU_ENABLED T ellint_e_imp(T phi, T k, const Policy& pol) // // 2n + sin(phi - n * pi) ; |phi - n * pi| <= pi / 2 // - T m = boost::math::round(phi / boost::math::constants::pi()); - T remains = phi - m * boost::math::constants::pi(); + T m = BOOST_MATH_NAMESPACE::round(phi / BOOST_MATH_NAMESPACE::constants::pi()); + T remains = phi - m * BOOST_MATH_NAMESPACE::constants::pi(); T value = 2 * m + sin(remains); // negative arc length for negative phi @@ -112,17 +112,17 @@ BOOST_MATH_GPU_ENABLED T ellint_e_imp(T phi, T k, const Policy& pol) // but that fails if T has more digits than a long long, // so rewritten to use fmod instead: // - T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi())); - T m = boost::math::round((phi - rphi) / constants::half_pi()); + T rphi = BOOST_MATH_NAMESPACE::tools::fmod_workaround(phi, T(constants::half_pi())); + T m = BOOST_MATH_NAMESPACE::round((phi - rphi) / constants::half_pi()); int s = 1; - if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5)) + if(BOOST_MATH_NAMESPACE::tools::fmod_workaround(m, T(2)) > T(0.5)) { m += 1; s = -1; rphi = constants::half_pi() - rphi; } T k2 = k * k; - if(boost::math::pow<3>(rphi) * k2 / 6 <= tools::epsilon() * fabs(rphi)) + if(BOOST_MATH_NAMESPACE::pow<3>(rphi) * k2 / 6 <= tools::epsilon() * fabs(rphi)) { // See http://functions.wolfram.com/EllipticIntegrals/EllipticE2/06/01/03/0001/ result = s * rphi; @@ -138,13 +138,19 @@ BOOST_MATH_GPU_ENABLED T ellint_e_imp(T phi, T k, const Policy& pol) T cosp = cos(rphi); T c = 1 / (sinp * sinp); T cm1 = cosp * cosp / (sinp * sinp); // c - 1 - result = s * ((1 - k2) * ellint_rf_imp(cm1, T(c - k2), c, pol) + k2 * (1 - k2) * ellint_rd(cm1, c, T(c - k2), pol) / 3 + k2 * sqrt(cm1 / (c * (c - k2)))); + // + // 1 - k^2 and c - k^2 = (c - 1) + (1 - k^2) are calculated without cancellation + // as both are small when k is near 1 and phi near pi/2: + // + T k2m1 = (1 - fabs(k)) * (1 + fabs(k)); + T cmk2 = cm1 + k2m1; + result = s * (k2m1 * ellint_rf_imp(cm1, cmk2, c, pol) + k2 * k2m1 * ellint_rd(cm1, c, cmk2, pol) / 3 + k2 * sqrt(cm1 / (c * cmk2))); } if (m != 0) { - typedef boost::math::integral_constant::value&& boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 54) ? 0 : - boost::math::is_floating_point::value && boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 64) ? 1 : 2 + typedef BOOST_MATH_NAMESPACE::integral_constant::value&& BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 54) ? 0 : + BOOST_MATH_NAMESPACE::is_floating_point::value && BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 64) ? 1 : 2 > precision_tag_type; result += m * ellint_e_imp(k, pol, precision_tag_type()); } @@ -154,10 +160,10 @@ BOOST_MATH_GPU_ENABLED T ellint_e_imp(T phi, T k, const Policy& pol) // Complete elliptic integral (Legendre form) of the second kind template -BOOST_MATH_GPU_ENABLED T ellint_e_imp(T k, const Policy& pol, boost::math::integral_constant const&) +BOOST_MATH_GPU_ENABLED T ellint_e_imp(T k, const Policy& pol, BOOST_MATH_NAMESPACE::integral_constant const&) { BOOST_MATH_STD_USING - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; if (abs(k) > 1) { @@ -192,10 +198,10 @@ BOOST_MATH_GPU_ENABLED T ellint_e_imp(T k, const Policy& pol, boost::math::integ // existing routines. // template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, boost::math::integral_constant const&) +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, BOOST_MATH_NAMESPACE::integral_constant const&) { BOOST_MATH_STD_USING - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; T m = k * k; switch (static_cast(20 * m)) @@ -218,7 +224,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(0.004809187786009338), -static_cast(0.004086399233255150) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.05)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.05)); } case 2: case 3: @@ -238,7 +244,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(0.011799303775587354), -static_cast(0.011197445703074968) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.15)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.15)); } case 4: case 5: @@ -258,7 +264,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(0.032371395314758122), -static_cast(0.034789960386404158) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.25)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.25)); } case 6: case 7: @@ -279,7 +285,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(0.127053585157696036), -static_cast(0.160791120691274606) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.35)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.35)); } case 8: case 9: @@ -301,7 +307,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(0.860523235727239756), -static_cast(1.308833205758540162) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.45)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.45)); } case 10: case 11: @@ -323,7 +329,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(6.446753640156048150), -static_cast(11.97703130208884026) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.55)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.55)); } case 12: case 13: @@ -347,7 +353,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(463.5938853480342030), -static_cast(1137.380822169360061) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.65)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.65)); } case 14: case 15: @@ -373,7 +379,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(315126.0406449163424), -static_cast(1104011.344311591159) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.75)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.75)); } case 16: //else if (m < 0.85) @@ -395,7 +401,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(396650.4505013548170), -static_cast(1920033.413682634405) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.825)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.825)); } case 17: //else if (m < 0.90) @@ -420,21 +426,21 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -static_cast(5198725846.725541393), -static_cast(36409256888.12139973) }; - return boost::math::tools::evaluate_polynomial(coef, m - static_cast(0.875)); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - static_cast(0.875)); } default: // // All cases where m > 0.9 // including all error handling: // - return ellint_e_imp(k, pol, boost::math::integral_constant()); + return ellint_e_imp(k, pol, BOOST_MATH_NAMESPACE::integral_constant()); } } template -BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, boost::math::integral_constant const&) +BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& pol, BOOST_MATH_NAMESPACE::integral_constant const&) { BOOST_MATH_STD_USING - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; T m = k * k; switch (static_cast(20 * m)) @@ -459,7 +465,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -0.0035450302604139562644L, -0.0031283511188028336315L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.05L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.05L); } case 2: case 3: @@ -481,7 +487,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -0.010850368064799902735L, -0.010696133481060989818L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.15L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.15L); } case 4: case 5: @@ -504,7 +510,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -0.042636187648900252525L, -0.048302272505241634467 }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.25L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.25L); } case 6: case 7: @@ -527,7 +533,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -0.20705400012405941376L, -0.27053164884730888948L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.35L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.35L); } case 8: case 9: @@ -551,7 +557,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -2.0200280559452241745L, -3.1566019548237606451L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.45L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.45L); } case 10: case 11: @@ -576,7 +582,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -43.109479829481450573L, -83.186290908288807424L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.55L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.55L); } case 12: case 13: @@ -604,7 +610,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -17821.809331816437058L, -45307.849987201897801L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.65L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.65L); } case 14: case 15: @@ -635,7 +641,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -1.7900668836197342979e8L, -6.4817399873722371964e8L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.75L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.75L); } case 16: //else if (m < 0.85L) @@ -663,7 +669,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -5.9850851892915740401e9L, -3.0614702984618644983e10L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.825L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.825L); } case 17: //else if (m < 0.90L) @@ -693,47 +699,47 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_e_imp(T k, const Policy& -9.4325465851415135118e13L, -6.8291980829471896669e14L }; - return boost::math::tools::evaluate_polynomial(coef, m - 0.875L); + return BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(coef, m - 0.875L); } default: // // All cases where m > 0.9 // including all error handling: // - return ellint_e_imp(k, pol, boost::math::integral_constant()); + return ellint_e_imp(k, pol, BOOST_MATH_NAMESPACE::integral_constant()); } } template -BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_2(T k, const Policy& pol, const boost::math::true_type&) +BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_2(T k, const Policy& pol, const BOOST_MATH_NAMESPACE::true_type&) { typedef typename tools::promote_args::type result_type; typedef typename policies::evaluation::type value_type; - typedef boost::math::integral_constant::value&& boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 54) ? 0 : - boost::math::is_floating_point::value && boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 64) ? 1 : 2 + typedef BOOST_MATH_NAMESPACE::integral_constant::value&& BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 54) ? 0 : + BOOST_MATH_NAMESPACE::is_floating_point::value && BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 64) ? 1 : 2 > precision_tag_type; return policies::checked_narrowing_cast(detail::ellint_e_imp(static_cast(k), pol, precision_tag_type()), "boost::math::ellint_2<%1%>(%1%)"); } // Elliptic integral (Legendre form) of the second kind template -BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_2(T1 k, T2 phi, const boost::math::false_type&) +BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_2(T1 k, T2 phi, const BOOST_MATH_NAMESPACE::false_type&) { - return boost::math::ellint_2(k, phi, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ellint_2(k, phi, policies::policy<>()); } } // detail // Elliptic integral (Legendre form) of the second kind -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_2(T1 k, T2 phi) { typedef typename policies::is_policy::type tag_type; return detail::ellint_2(k, phi, tag_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_2(T1 k, T2 phi, const Policy& pol) // LCOV_EXCL_LINE gcc misses this but sees the function body, strange! { typedef typename tools::promote_args::type result_type; @@ -743,14 +749,14 @@ BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_2(T1 k, // Complete elliptic integral (Legendre form) of the second kind -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_2(T k) { return ellint_2(k, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_2_HPP diff --git a/include/boost/math/special_functions/ellint_3.hpp b/include/boost/math/special_functions/ellint_3.hpp index b8df7e2645..60734a50de 100644 --- a/include/boost/math/special_functions/ellint_3.hpp +++ b/include/boost/math/special_functions/ellint_3.hpp @@ -35,7 +35,7 @@ // Elliptic integrals (complete and incomplete) of the third kind // Carlson, Numerische Mathematik, vol 33, 1 (1979) -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -117,14 +117,14 @@ BOOST_MATH_CUDA_ENABLED T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol } else { - T rphi = boost::math::tools::fmod_workaround(T(fabs(phi)), T(constants::half_pi())); - T m = boost::math::round((fabs(phi) - rphi) / constants::half_pi()); + T rphi = BOOST_MATH_NAMESPACE::tools::fmod_workaround(T(fabs(phi)), T(constants::half_pi())); + T m = BOOST_MATH_NAMESPACE::round((fabs(phi) - rphi) / constants::half_pi()); int sign = 1; if((m != 0) && (k >= 1)) { return policies::raise_domain_error(function, "Got k=1 and phi=%1% but the result is complex in that domain", phi, pol); } - if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5)) + if(BOOST_MATH_NAMESPACE::tools::fmod_workaround(m, T(2)) > T(0.5)) { m += 1; sign = -1; @@ -149,7 +149,7 @@ BOOST_MATH_CUDA_ENABLED T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol // v > 1: T vcr = sqrt(-vc); T arg = vcr * tan(phi); - return (boost::math::log1p(arg, pol) - boost::math::log1p(-arg, pol)) / (2 * vcr); + return (BOOST_MATH_NAMESPACE::log1p(arg, pol) - BOOST_MATH_NAMESPACE::log1p(-arg, pol)) / (2 * vcr); } } if((v < 0) && fabs(k) <= 1) @@ -276,7 +276,7 @@ BOOST_MATH_CUDA_ENABLED T ellint_pi_imp(T v, T k, T vc, const Policy& pol) { // Note arg vc = 1-v, possibly without cancellation errors BOOST_MATH_STD_USING - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; constexpr auto function = "boost::math::ellint_pi<%1%>(%1%,%1%)"; @@ -292,7 +292,7 @@ BOOST_MATH_CUDA_ENABLED T ellint_pi_imp(T v, T k, T vc, const Policy& pol) if(v == 0) { - return (k == 0) ? boost::math::constants::pi() / 2 : boost::math::ellint_1(k, pol); + return (k == 0) ? BOOST_MATH_NAMESPACE::constants::pi() / 2 : BOOST_MATH_NAMESPACE::ellint_1(k, pol); } if(v < 0) @@ -302,11 +302,11 @@ BOOST_MATH_CUDA_ENABLED T ellint_pi_imp(T v, T k, T vc, const Policy& pol) T N = (k2 - v) / (1 - v); T Nm1 = (1 - k2) / (1 - v); T result = 0; - result = boost::math::detail::ellint_pi_imp(N, k, Nm1, pol); + result = BOOST_MATH_NAMESPACE::detail::ellint_pi_imp(N, k, Nm1, pol); // This next part is split in two to avoid spurious over/underflow: result *= -v / (1 - v); result *= (1 - k2) / (k2 - v); - result += boost::math::ellint_1(k, pol) * k2 / (k2 - v); + result += BOOST_MATH_NAMESPACE::ellint_1(k, pol) * k2 / (k2 - v); return result; } @@ -320,13 +320,13 @@ BOOST_MATH_CUDA_ENABLED T ellint_pi_imp(T v, T k, T vc, const Policy& pol) } template -BOOST_MATH_CUDA_ENABLED inline typename tools::promote_args::type ellint_3(T1 k, T2 v, T3 phi, const boost::math::false_type&) +BOOST_MATH_CUDA_ENABLED inline typename tools::promote_args::type ellint_3(T1 k, T2 v, T3 phi, const BOOST_MATH_NAMESPACE::false_type&) { - return boost::math::ellint_3(k, v, phi, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ellint_3(k, v, phi, policies::policy<>()); } template -BOOST_MATH_CUDA_ENABLED inline typename tools::promote_args::type ellint_3(T1 k, T2 v, const Policy& pol, const boost::math::true_type&) +BOOST_MATH_CUDA_ENABLED inline typename tools::promote_args::type ellint_3(T1 k, T2 v, const Policy& pol, const BOOST_MATH_NAMESPACE::true_type&) { typedef typename tools::promote_args::type result_type; typedef typename policies::evaluation::type value_type; @@ -340,7 +340,7 @@ BOOST_MATH_CUDA_ENABLED inline typename tools::promote_args::type ellint } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline typename tools::promote_args::type ellint_3(T1 k, T2 v, T3 phi, const Policy&) { typedef typename tools::promote_args::type result_type; @@ -355,20 +355,20 @@ BOOST_MATH_CUDA_ENABLED inline typename tools::promote_args::type el forwarding_policy()), "boost::math::ellint_3<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED typename detail::ellint_3_result::type ellint_3(T1 k, T2 v, T3 phi) { typedef typename policies::is_policy::type tag_type; return detail::ellint_3(k, v, phi, tag_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_CUDA_ENABLED inline typename tools::promote_args::type ellint_3(T1 k, T2 v) { return ellint_3(k, v, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_3_HPP diff --git a/include/boost/math/special_functions/ellint_d.hpp b/include/boost/math/special_functions/ellint_d.hpp index f5a8491f5a..c2fb35897e 100644 --- a/include/boost/math/special_functions/ellint_d.hpp +++ b/include/boost/math/special_functions/ellint_d.hpp @@ -33,9 +33,9 @@ // Elliptic integrals (complete and incomplete) of the second kind // Carlson, Numerische Mathematik, vol 33, 1 (1979) -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args::type ellint_d(T1 k, T2 phi, const Policy& pol); namespace detail{ @@ -48,8 +48,8 @@ template BOOST_MATH_GPU_ENABLED T ellint_d_imp(T phi, T k, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; bool invert = false; if(phi < 0) @@ -76,10 +76,10 @@ BOOST_MATH_GPU_ENABLED T ellint_d_imp(T phi, T k, const Policy& pol) // Carlson's algorithm works only for |phi| <= pi/2, // use the integrand's periodicity to normalize phi // - T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi())); - T m = boost::math::round((phi - rphi) / constants::half_pi()); + T rphi = BOOST_MATH_NAMESPACE::tools::fmod_workaround(phi, T(constants::half_pi())); + T m = BOOST_MATH_NAMESPACE::round((phi - rphi) / constants::half_pi()); int s = 1; - if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5)) + if(BOOST_MATH_NAMESPACE::tools::fmod_workaround(m, T(2)) > T(0.5)) { m += 1; s = -1; @@ -119,7 +119,7 @@ template BOOST_MATH_GPU_ENABLED T ellint_d_imp(T k, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math::tools; + using namespace BOOST_MATH_NAMESPACE::tools; if (abs(k) >= 1) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED T ellint_d_imp(T k, const Policy& pol) } template -BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_d(T k, const Policy& pol, const boost::math::true_type&) +BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_d(T k, const Policy& pol, const BOOST_MATH_NAMESPACE::true_type&) { typedef typename tools::promote_args::type result_type; typedef typename policies::evaluation::type value_type; @@ -147,29 +147,29 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_d(T k // Elliptic integral (Legendre form) of the second kind template -BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_d(T1 k, T2 phi, const boost::math::false_type&) +BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_d(T1 k, T2 phi, const BOOST_MATH_NAMESPACE::false_type&) { - return boost::math::ellint_d(k, phi, policies::policy<>()); + return BOOST_MATH_NAMESPACE::ellint_d(k, phi, policies::policy<>()); } } // detail // Complete elliptic integral (Legendre form) of the second kind -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_d(T k) { return ellint_d(k, policies::policy<>()); } // Elliptic integral (Legendre form) of the second kind -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_d(T1 k, T2 phi) { typedef typename policies::is_policy::type tag_type; return detail::ellint_d(k, phi, tag_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_d(T1 k, T2 phi, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -177,7 +177,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_ return policies::checked_narrowing_cast(detail::ellint_d_imp(static_cast(phi), static_cast(k), pol), "boost::math::ellint_2<%1%>(%1%,%1%)"); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_D_HPP diff --git a/include/boost/math/special_functions/ellint_rc.hpp b/include/boost/math/special_functions/ellint_rc.hpp index ae3c6375e5..f43d067b02 100644 --- a/include/boost/math/special_functions/ellint_rc.hpp +++ b/include/boost/math/special_functions/ellint_rc.hpp @@ -29,7 +29,7 @@ // R_C(x, y) = R_F(x, y, y) = 0.5 * \int_{0}^{\infty} (t+x)^{-1/2} (t+y)^{-1} dt // Carlson, Numerische Mathematik, vol 33, 1 (1979) -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T ellint_rc_imp(T x, T y, const Policy& pol) @@ -75,7 +75,7 @@ BOOST_MATH_GPU_ENABLED T ellint_rc_imp(T x, T y, const Policy& pol) if(y / x > T(0.5)) { T arg = sqrt((x - y) / x); - result = (boost::math::log1p(arg, pol) - boost::math::log1p(-arg, pol)) / (2 * sqrt(x - y)); + result = (BOOST_MATH_NAMESPACE::log1p(arg, pol) - BOOST_MATH_NAMESPACE::log1p(-arg, pol)) / (2 * sqrt(x - y)); } else { @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED T ellint_rc_imp(T x, T y, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rc(T1 x, T2 y, const Policy& pol) { @@ -99,14 +99,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type static_cast(y), pol), "boost::math::ellint_rc<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rc(T1 x, T2 y) { return ellint_rc(x, y, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_RC_HPP diff --git a/include/boost/math/special_functions/ellint_rd.hpp b/include/boost/math/special_functions/ellint_rd.hpp index f2a33adc46..cc78b878df 100644 --- a/include/boost/math/special_functions/ellint_rd.hpp +++ b/include/boost/math/special_functions/ellint_rd.hpp @@ -27,7 +27,7 @@ // R_D(x, y, z) = R_J(x, y, z, z) = 1.5 * \int_{0}^{\infty} [(t+x)(t+y)]^{-1/2} (t+z)^{-3/2} dt // Carlson, Numerische Mathematik, vol 33, 1 (1979) -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T ellint_rd_imp(T x, T y, T z, const Policy& pol) @@ -181,7 +181,7 @@ BOOST_MATH_GPU_ENABLED T ellint_rd_imp(T x, T y, T z, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rd(T1 x, T2 y, T3 z, const Policy& pol) { @@ -194,14 +194,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type static_cast(z), pol), "boost::math::ellint_rd<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rd(T1 x, T2 y, T3 z) { return ellint_rd(x, y, z, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_RD_HPP diff --git a/include/boost/math/special_functions/ellint_rf.hpp b/include/boost/math/special_functions/ellint_rf.hpp index eb1c2b6e71..d43e0e140e 100644 --- a/include/boost/math/special_functions/ellint_rf.hpp +++ b/include/boost/math/special_functions/ellint_rf.hpp @@ -29,23 +29,23 @@ // R_F(x, y, z) = 0.5 * \int_{0}^{\infty} [(t+x)(t+y)(t+z)]^{-1/2} dt // Carlson, Numerische Mathematik, vol 33, 1 (1979) -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T ellint_rf_imp(T x, T y, T z, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math; + using namespace BOOST_MATH_NAMESPACE; constexpr auto function = "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)"; if(x < 0 || y < 0 || z < 0) { - return policies::raise_domain_error(function, "domain error, all arguments must be non-negative, only sensible result is %1%.", boost::math::numeric_limits::quiet_NaN(), pol); + return policies::raise_domain_error(function, "domain error, all arguments must be non-negative, only sensible result is %1%.", BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), pol); } if(x + y == 0 || y + z == 0 || z + x == 0) { - return policies::raise_domain_error(function, "domain error, at most one argument can be zero, only sensible result is %1%.", boost::math::numeric_limits::quiet_NaN(), pol); + return policies::raise_domain_error(function, "domain error, at most one argument can be zero, only sensible result is %1%.", BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), pol); } // // Special cases from http://dlmf.nist.gov/19.20#i @@ -106,13 +106,13 @@ namespace boost { namespace math { namespace detail{ T zn = z; T An = (x + y + z) / 3; T A0 = An; - T Q = pow(3 * boost::math::tools::epsilon(), T(-1) / 8) * BOOST_MATH_GPU_SAFE_MAX(BOOST_MATH_GPU_SAFE_MAX(fabs(An - xn), fabs(An - yn)), fabs(An - zn)); + T Q = pow(3 * BOOST_MATH_NAMESPACE::tools::epsilon(), T(-1) / 8) * BOOST_MATH_GPU_SAFE_MAX(BOOST_MATH_GPU_SAFE_MAX(fabs(An - xn), fabs(An - yn)), fabs(An - zn)); T fn = 1; // duplication unsigned k = 1; - for(; k < boost::math::policies::get_max_series_iterations(); ++k) + for(; k < BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); ++k) { T root_x = sqrt(xn); T root_y = sqrt(yn); @@ -143,7 +143,7 @@ namespace boost { namespace math { namespace detail{ } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rf(T1 x, T2 y, T3 z, const Policy& pol) { @@ -156,14 +156,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type static_cast(z), pol), "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rf(T1 x, T2 y, T3 z) { return ellint_rf(x, y, z, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_RF_HPP diff --git a/include/boost/math/special_functions/ellint_rg.hpp b/include/boost/math/special_functions/ellint_rg.hpp index 8a7f706ac0..e44cc87ef1 100644 --- a/include/boost/math/special_functions/ellint_rg.hpp +++ b/include/boost/math/special_functions/ellint_rg.hpp @@ -18,7 +18,7 @@ #include #include -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T ellint_rg_imp(T x, T y, T z, const Policy& pol) @@ -28,7 +28,7 @@ namespace boost { namespace math { namespace detail{ if(x < 0 || y < 0 || z < 0) { - return policies::raise_domain_error(function, "domain error, all arguments must be non-negative, only sensible result is %1%.", boost::math::numeric_limits::quiet_NaN(), pol); + return policies::raise_domain_error(function, "domain error, all arguments must be non-negative, only sensible result is %1%.", BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), pol); } // // Function is symmetric in x, y and z, but we require @@ -92,10 +92,10 @@ namespace boost { namespace math { namespace detail{ xn = (xn + yn) / 2; yn = t; sum_pow *= 2; - sum += sum_pow * boost::math::pow<2>(xn - yn); + sum += sum_pow * BOOST_MATH_NAMESPACE::pow<2>(xn - yn); } T RF = constants::pi() / (xn + yn); - return ((boost::math::pow<2>((x0 + y0) / 2) - sum) * RF) / 2; + return ((BOOST_MATH_NAMESPACE::pow<2>((x0 + y0) / 2) - sum) * RF) / 2; } return (z * ellint_rf_imp(x, y, z, pol) - (x - z) * (y - z) * ellint_rd_imp(x, y, z, pol) / 3 @@ -104,7 +104,7 @@ namespace boost { namespace math { namespace detail{ } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rg(T1 x, T2 y, T3 z, const Policy& pol) { @@ -117,14 +117,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type static_cast(z), pol), "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rg(T1 x, T2 y, T3 z) { return ellint_rg(x, y, z, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_RG_HPP diff --git a/include/boost/math/special_functions/ellint_rj.hpp b/include/boost/math/special_functions/ellint_rj.hpp index 8c1f93788f..71e8f6b04a 100644 --- a/include/boost/math/special_functions/ellint_rj.hpp +++ b/include/boost/math/special_functions/ellint_rj.hpp @@ -31,12 +31,12 @@ // R_J(x, y, z, p) = 1.5 * \int_{0}^{\infty} (t+p)^{-1} [(t+x)(t+y)(t+z)]^{-1/2} dt // Carlson, Numerische Mathematik, vol 33, 1 (1979) -namespace boost { namespace math { namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T ellint_rc1p_imp(T y, const Policy& pol) { - using namespace boost::math; + using namespace BOOST_MATH_NAMESPACE; // Calculate RC(1, 1 + x) BOOST_MATH_STD_USING @@ -61,7 +61,7 @@ BOOST_MATH_GPU_ENABLED T ellint_rc1p_imp(T y, const Policy& pol) if(y > T(-0.5)) { T arg = sqrt(-y); - result = (boost::math::log1p(arg, pol) - boost::math::log1p(-arg, pol)) / (2 * sqrt(-y)); + result = (BOOST_MATH_NAMESPACE::log1p(arg, pol) - BOOST_MATH_NAMESPACE::log1p(-arg, pol)) / (2 * sqrt(-y)); } else { @@ -71,6 +71,50 @@ BOOST_MATH_GPU_ENABLED T ellint_rc1p_imp(T y, const Policy& pol) return result; } +// +// RC(1, 1+e) = 1 - e/3 + e^2/5 - ..., summed until the terms are negligible, for small |e|. +// +template +BOOST_MATH_GPU_ENABLED T ellint_rc1p_series(T e) +{ + BOOST_MATH_STD_USING + T sum = 1; + T term = 1; + for(unsigned k = 1; k < 10000; ++k) + { + term *= -e; + T t = term / (2 * k + 1); + sum += t; + if(fabs(t) < tools::epsilon()) + break; + } + return sum; +} +// +// The series in the final step of the RJ algorithm, through order B: +// sum_N (3/2)_N / (5/2)_N T_N with N T_N = -sum_{r=2}^{5} (-1)^r (N - r/2) E_r T_{N-r}, +// Carlson, J. Res. Natl. Inst. Stand. Technol. 107 (2002) 413-418, Eq. (3.9). +// +template +BOOST_MATH_GPU_ENABLED T ellint_rj_series(T E2, T E3, T E4, T E5, unsigned B) +{ + T tm1 = 1, tm2 = 0, tm3 = 0, tm4 = 0, tm5 = 0; // T_{N-1}, ..., T_{N-5} + T sum = 1; + T c = 1; + for(unsigned N = 1; N <= B; ++N) + { + T tn = -((T(N) - 1) * E2 * tm2 - (T(N) - T(1.5)) * E3 * tm3 + (T(N) - 2) * E4 * tm4 - (T(N) - T(2.5)) * E5 * tm5) / N; + c *= T(2 * N + 1) / (2 * N + 3); + sum += c * tn; + tm5 = tm4; + tm4 = tm3; + tm3 = tm2; + tm2 = tm1; + tm1 = tn; + } + return sum; +} + template BOOST_MATH_GPU_ENABLED T ellint_rj_imp_final(T x, T y, T z, T p, const Policy& pol) { @@ -135,7 +179,15 @@ BOOST_MATH_GPU_ENABLED T ellint_rj_imp_final(T x, T y, T z, T p, const Policy& p T An = (x + y + z + 2 * p) / 5; T A0 = An; T delta = (p - x) * (p - y) * (p - z); - T Q = pow(tools::epsilon() / 5, -T(1) / 8) * BOOST_MATH_GPU_SAFE_MAX(BOOST_MATH_GPU_SAFE_MAX(fabs(An - x), fabs(An - y)), BOOST_MATH_GPU_SAFE_MAX(fabs(An - z), fabs(An - p))); + // + // Beyond long double precision, fewer duplications with a longer final series pay off, with order + // ~2 p^0.4 for p bits (Johansson, arXiv:1806.06725), and so does summing the series for RC(1, 1+E_n) + // whenever |E_n| <= 1/8, rather than calling atan or log. + // + const bool high_precision = tools::digits() > 64; + const unsigned order = high_precision ? static_cast(2 * pow(static_cast(tools::digits()), 0.4) + 0.5) : 7u; + const T rc_series_limit = high_precision ? T(0.125) : T(0); + T Q = (high_precision ? T(pow(tools::epsilon() / 5, -T(1) / (order + 1))) : T(sqrt(sqrt(sqrt(5 / tools::epsilon()))))) * BOOST_MATH_GPU_SAFE_MAX(BOOST_MATH_GPU_SAFE_MAX(fabs(An - x), fabs(An - y)), BOOST_MATH_GPU_SAFE_MAX(fabs(An - z), fabs(An - p))); unsigned n; T lambda; @@ -144,6 +196,10 @@ BOOST_MATH_GPU_ENABLED T ellint_rj_imp_final(T x, T y, T z, T p, const Policy& p T rx, ry, rz, rp; T fmn = 1; // 4^-n T RC_sum = 0; + // After the first iteration or two E_n is tiny, and RC(1, 1+E_n) is cheaper from its + // series 1 - E/3 + E^2/5 - ... (as Johansson also suggests, arXiv:1806.06725): + // below this limit the first omitted term is under epsilon / 13. + const T series_limit = sqrt(tools::cbrt_epsilon()); for(n = 0; n < policies::get_max_series_iterations(); ++n) { @@ -154,7 +210,15 @@ BOOST_MATH_GPU_ENABLED T ellint_rj_imp_final(T x, T y, T z, T p, const Policy& p Dn = (rp + rx) * (rp + ry) * (rp + rz); En = delta / Dn; En /= Dn; - if((En < T(-0.5)) && (En > T(-1.5))) + if(fabs(En) < series_limit) + { + RC_sum += fmn / Dn * (1 + En * (T(-1) / 3 + En * (T(1) / 5 + En * (T(-1) / 7 + En * (T(1) / 9 + En * (T(-1) / 11)))))); + } + else if(fabs(En) <= rc_series_limit) + { + RC_sum += fmn / Dn * ellint_rc1p_series(En); + } + else if((En < T(-0.5)) && (En > T(-1.5))) { // // Occasionally En ~ -1, we then have no means of calculating @@ -200,7 +264,9 @@ BOOST_MATH_GPU_ENABLED T ellint_rj_imp_final(T x, T y, T z, T p, const Policy& p T E3 = X * Y * Z + 2 * E2 * P + 4 * P * P * P; T E4 = (2 * X * Y * Z + E2 * P + 3 * P * P * P) * P; T E5 = X * Y * Z * P * P; - T result = fmn * pow(An, T(-3) / 2) * + if(high_precision) + return fmn / (An * sqrt(An)) * ellint_rj_series(E2, E3, E4, E5, order) + 6 * RC_sum; + T result = fmn / (An * sqrt(An)) * (1 - 3 * E2 / 14 + E3 / 6 + 9 * E2 * E2 / 88 - 3 * E4 / 22 - 9 * E2 * E3 / 52 + 3 * E5 / 26 - E2 * E2 * E2 / 16 + 3 * E3 * E3 / 40 + 3 * E2 * E4 / 20 + 45 * E2 * E2 * E3 / 272 - 9 * (E3 * E4 + E2 * E5) / 68); @@ -233,7 +299,7 @@ BOOST_MATH_GPU_ENABLED T ellint_rj_imp(T x, T y, T z, T p, const Policy& pol) } if(x + y == 0 || y + z == 0 || z + x == 0) { - return policies::raise_domain_error(function, "At most one argument can be zero, only possible result is %1%.", boost::math::numeric_limits::quiet_NaN(), pol); + return policies::raise_domain_error(function, "At most one argument can be zero, only possible result is %1%.", BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(), pol); } // for p < 0, the integral is singular, return Cauchy principal value @@ -271,7 +337,7 @@ BOOST_MATH_GPU_ENABLED T ellint_rj_imp(T x, T y, T z, T p, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rj(T1 x, T2 y, T3 z, T4 p, const Policy& pol) { @@ -286,14 +352,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type pol), "boost::math::ellint_rj<%1%>(%1%,%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type ellint_rj(T1 x, T2 y, T3 z, T4 p) { return ellint_rj(x, y, z, p, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_RJ_HPP diff --git a/include/boost/math/special_functions/erf.hpp b/include/boost/math/special_functions/erf.hpp index dffb0c59cc..67656aec2b 100644 --- a/include/boost/math/special_functions/erf.hpp +++ b/include/boost/math/special_functions/erf.hpp @@ -31,7 +31,7 @@ #pragma GCC system_header #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -46,7 +46,7 @@ struct erf_asympt_series_t BOOST_MATH_GPU_ENABLED erf_asympt_series_t(T z) : xx(2 * -z * z), tk(1) { BOOST_MATH_STD_USING - result = -exp(-z * z) / sqrt(boost::math::constants::pi()); + result = -exp(-z * z) / sqrt(BOOST_MATH_NAMESPACE::constants::pi()); result /= z; } @@ -150,7 +150,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const Tag& t) BOOST_MATH_INSTRUMENT_CODE("Generic erf_imp called"); - if ((boost::math::isnan)(z)) + if ((BOOST_MATH_NAMESPACE::isnan)(z)) return policies::raise_domain_error("boost::math::erf<%1%>(%1%)", "Expected a finite argument but got %1%", z, pol); if (fabs(z) < tools::root_epsilon()) @@ -163,7 +163,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const Tag& t) return invert ? 1 - term2 : term2; } - const bool signbit_result = ((boost::math::signbit)(z) != 0); + const bool signbit_result = ((BOOST_MATH_NAMESPACE::signbit)(z) != 0); if (signbit_result) { @@ -179,7 +179,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const Tag& t) { detail::erf_asympt_series_t s(z); std::uintmax_t max_iter = policies::get_max_series_iterations(); - result = boost::math::tools::sum_series(s, policies::get_epsilon(), max_iter, 1); + result = BOOST_MATH_NAMESPACE::tools::sum_series(s, policies::get_epsilon(), max_iter, 1); policies::check_series_iterations("boost::math::erf<%1%>(%1%, %1%)", max_iter, pol); } else @@ -204,7 +204,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const Tag& t) // Compute Q: invert = !invert; result = z * exp(-z_sq); - result /= boost::math::constants::root_pi(); + result /= BOOST_MATH_NAMESPACE::constants::root_pi(); result *= upper_gamma_fraction(T(0.5f), z_sq, policies::get_epsilon()); } } @@ -220,7 +220,7 @@ BOOST_MATH_GPU_ENABLED T erf_imp(T z, bool invert, const Policy& pol, const std: BOOST_MATH_INSTRUMENT_CODE("53-bit precision erf_imp called"); - if ((boost::math::isnan)(z)) + if ((BOOST_MATH_NAMESPACE::isnan)(z)) return policies::raise_domain_error("boost::math::erf<%1%>(%1%)", "Expected a finite argument but got %1%", z, pol); int prefix_multiplier = 1; @@ -476,7 +476,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const std::integral_constant(%1%)", "Expected a finite argument but got %1%", z, pol); if(z < 0) @@ -724,7 +724,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const std::integral_constant(%1%)", "Expected a finite argument but got %1%", z, pol); if(z < 0) @@ -1190,7 +1190,7 @@ T erf_imp(T z, bool invert, const Policy& pol, const std::integral_constant +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type erf(T z, const Policy& /* pol */) { typedef typename tools::promote_args::type result_type; @@ -1223,7 +1223,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type erf(T z, con tag_type()), "boost::math::erf<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type erfc(T z, const Policy& /* pol */) { typedef typename tools::promote_args::type result_type; @@ -1256,27 +1256,25 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type erfc(T z, co tag_type()), "boost::math::erfc<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type erf(T z) { - return boost::math::erf(z, policies::policy<>()); + return BOOST_MATH_NAMESPACE::erf(z, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type erfc(T z) { - return boost::math::erfc(z, policies::policy<>()); + return BOOST_MATH_NAMESPACE::erfc(z, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else // Special handling for NVRTC platform -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto erf(T x) { return ::erf(x); @@ -1288,19 +1286,19 @@ BOOST_MATH_GPU_ENABLED auto erf(float x) return ::erff(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto erf(T x, const Policy&) { return ::erf(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto erf(float x, const Policy&) { return ::erff(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto erfc(T x) { return ::erfc(x); @@ -1312,20 +1310,19 @@ BOOST_MATH_GPU_ENABLED auto erfc(float x) return ::erfcf(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto erfc(T x, const Policy&) { return ::erfc(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto erfc(float x, const Policy&) { return ::erfcf(x); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC diff --git a/include/boost/math/special_functions/expint.hpp b/include/boost/math/special_functions/expint.hpp index eeec63199e..7ee23b7dec 100644 --- a/include/boost/math/special_functions/expint.hpp +++ b/include/boost/math/special_functions/expint.hpp @@ -36,16 +36,16 @@ #pragma GCC system_header #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type expint(unsigned n, T z, const Policy& /*pol*/); namespace detail{ template -BOOST_MATH_GPU_ENABLED inline T expint_1_rational(const T& z, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline T expint_1_rational(const T& z, const BOOST_MATH_NAMESPACE::integral_constant&) { // this function is never actually called BOOST_MATH_ASSERT(0); @@ -53,7 +53,7 @@ BOOST_MATH_GPU_ENABLED inline T expint_1_rational(const T& z, const boost::math: } template -BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING T result; @@ -85,7 +85,7 @@ BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const boost::math::integr / tools::evaluate_polynomial(Q, z); result += z - log(z) - Y; } - else if(z < -boost::math::tools::log_min_value()) + else if(z < -BOOST_MATH_NAMESPACE::tools::log_min_value()) { // Maximum Deviation Found (interpolated): 1.444e-17 // Max error found at double precision: 3.119e-17 @@ -131,7 +131,7 @@ BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const boost::math::integr } template -BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING T result; @@ -164,7 +164,7 @@ BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const boost::math::integr / tools::evaluate_polynomial(Q, z); result += z - log(z) - Y; } - else if(z < -boost::math::tools::log_min_value()) + else if(z < -BOOST_MATH_NAMESPACE::tools::log_min_value()) { // Maximum Deviation Found (interpolated): 2.220e-20 // Max error found at long double precision: 1.346e-19 @@ -215,7 +215,7 @@ BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const boost::math::integr } template -BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING T result; @@ -304,7 +304,7 @@ BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const boost::math::integr / tools::evaluate_polynomial(Q, recip); result *= exp(-z) * recip; } - else if(z < -boost::math::tools::log_min_value()) + else if(z < -BOOST_MATH_NAMESPACE::tools::log_min_value()) { // Max error in interpolated form: 4.413e-35 // Max error found at long double precision: 8.928e-35 @@ -369,11 +369,11 @@ BOOST_MATH_GPU_ENABLED T expint_1_rational(const T& z, const boost::math::integr template struct expint_fraction { - typedef boost::math::pair result_type; + typedef BOOST_MATH_NAMESPACE::pair result_type; BOOST_MATH_GPU_ENABLED expint_fraction(unsigned n_, T z_) : b(n_ + z_), i(-1), n(n_){} - BOOST_MATH_GPU_ENABLED boost::math::pair operator()() + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::pair operator()() { - boost::math::pair result = boost::math::make_pair(-static_cast((i+1) * (n+i)), b); + BOOST_MATH_NAMESPACE::pair result = BOOST_MATH_NAMESPACE::make_pair(-static_cast((i+1) * (n+i)), b); b += 2; ++i; return result; @@ -389,15 +389,25 @@ BOOST_MATH_GPU_ENABLED inline T expint_as_fraction(unsigned n, T z, const Policy { BOOST_MATH_STD_USING BOOST_MATH_INSTRUMENT_VARIABLE(z) - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); expint_fraction f(n, z); T result = tools::continued_fraction_b( f, - boost::math::policies::get_epsilon(), + BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); policies::check_series_iterations("boost::math::expint_continued_fraction<%1%>(unsigned,%1%)", max_iter, pol); BOOST_MATH_INSTRUMENT_VARIABLE(result) BOOST_MATH_INSTRUMENT_VARIABLE(max_iter) + // + // The forward evaluation above multiplies together one factor per term, and their rounding errors + // add up to tens of eps. Worse, where it converges slowly it stops while the tail still changes the + // result by tens of eps. So evaluate the fraction again from the tail, which damps the rounding errors, + // and starting from twice as many terms: b[k-1] - k (n + k - 1) / (b[k] - ...), with b[k] = n + z + 2k. + // + BOOST_MATH_NAMESPACE::uintmax_t terms = 2 * max_iter; + result = n + z + 2 * T(terms); + for(BOOST_MATH_NAMESPACE::uintmax_t k = terms; k > 0; --k) + result = (n + z + 2 * T(k - 1)) - T(k) * T(n + k - 1) / result; result = exp(-z) / result; BOOST_MATH_INSTRUMENT_VARIABLE(result) return result; @@ -428,7 +438,7 @@ template BOOST_MATH_GPU_ENABLED inline T expint_as_series(unsigned n, T z, const Policy& pol) { BOOST_MATH_STD_USING - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); BOOST_MATH_INSTRUMENT_VARIABLE(z) @@ -446,7 +456,7 @@ BOOST_MATH_GPU_ENABLED inline T expint_as_series(unsigned n, T z, const Policy& } BOOST_MATH_INSTRUMENT_VARIABLE(result) result += pow(-z, static_cast(n - 1)) - * (boost::math::digamma(static_cast(n), pol) - log(z)) / fact; + * (BOOST_MATH_NAMESPACE::digamma(static_cast(n), pol) - log(z)) / fact; BOOST_MATH_INSTRUMENT_VARIABLE(result) expint_series s(k, z, x_k, denom, fact); @@ -528,7 +538,7 @@ BOOST_MATH_GPU_ENABLED T expint_i_as_series(T z, const Policy& pol) T result = log(z); // (log(z) - log(1 / z)) / 2; result += constants::euler(); expint_i_series s(z); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); result = tools::sum_series(s, policies::get_epsilon(), max_iter, result); policies::check_series_iterations("boost::math::expint_i_series<%1%>(%1%)", max_iter, pol); return result; @@ -546,7 +556,7 @@ BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const Tag& tag) } template -BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant& tag) { BOOST_MATH_STD_USING constexpr auto function = "boost::math::expint<%1%>(%1%)"; @@ -599,7 +609,7 @@ BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const boost::math: result *= t; if(fabs(t) < T(0.1)) { - result += boost::math::log1p(t / r, pol); + result += BOOST_MATH_NAMESPACE::log1p(t / r, pol); } else { @@ -767,7 +777,7 @@ BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const boost::math: } template -BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant& tag) { BOOST_MATH_STD_USING constexpr auto function = "boost::math::expint<%1%>(%1%)"; @@ -824,7 +834,7 @@ BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const boost::math: result *= t; if(fabs(t) < T(0.1)) { - result += boost::math::log1p(t / r, pol); + result += BOOST_MATH_NAMESPACE::log1p(t / r, pol); } else { @@ -1071,7 +1081,7 @@ BOOST_MATH_GPU_ENABLED void expint_i_imp_113a(T& result, const T& z, const Polic result *= t; if(fabs(t) < 0.1) { - result += boost::math::log1p(t / r, pol); + result += BOOST_MATH_NAMESPACE::log1p(t / r, pol); } else { @@ -1426,7 +1436,7 @@ BOOST_MATH_GPU_ENABLED void expint_i_113h(T& result, const T& z) } template -BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const boost::math::integral_constant& tag) +BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant& tag) { BOOST_MATH_STD_USING constexpr auto function = "boost::math::expint<%1%>(%1%)"; @@ -1531,7 +1541,7 @@ BOOST_MATH_GPU_ENABLED T expint_i_imp(T z, const Policy& pol, const boost::math: template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type - expint_forwarder(T z, const Policy& /*pol*/, boost::math::true_type const&) + expint_forwarder(T z, const Policy& /*pol*/, BOOST_MATH_NAMESPACE::true_type const&) { typedef typename tools::promote_args::type result_type; typedef typename policies::evaluation::type value_type; @@ -1542,7 +1552,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type policies::promote_double, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; - typedef boost::math::integral_constant::type template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type -expint_forwarder(unsigned n, T z, const boost::math::false_type&) +expint_forwarder(unsigned n, T z, const BOOST_MATH_NAMESPACE::false_type&) { - return boost::math::expint(n, z, policies::policy<>()); + return BOOST_MATH_NAMESPACE::expint(n, z, policies::policy<>()); } } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type expint(unsigned n, T z, const Policy& /*pol*/) { @@ -1574,7 +1584,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type policies::promote_double, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; - typedef boost::math::integral_constant::type tag_type()), "boost::math::expint<%1%>(unsigned, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::expint_result::type expint(T const z, U const u) { @@ -1596,14 +1606,14 @@ BOOST_MATH_GPU_ENABLED inline typename detail::expint_result::type return detail::expint_forwarder(z, u, tag_type()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type expint(T z) { return expint(z, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/expm1.hpp b/include/boost/math/special_functions/expm1.hpp index 7635c6471e..2260b1269c 100644 --- a/include/boost/math/special_functions/expm1.hpp +++ b/include/boost/math/special_functions/expm1.hpp @@ -18,7 +18,9 @@ #if defined __has_include # if ((__cplusplus > 202002L) || (defined(_MSVC_LANG) && (_MSVC_LANG > 202002L))) # if __has_include () +#ifndef BOOST_MATH_BUILD_MODULE # include +#endif # endif # endif #endif @@ -45,8 +47,7 @@ #pragma GCC system_header #endif -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -91,12 +92,12 @@ namespace boost { // This version uses a Taylor series expansion for 0.5 > |x| > epsilon. // template - T expm1_imp(T x, const boost::math::integral_constant&, const Policy& pol) + T expm1_imp(T x, const BOOST_MATH_NAMESPACE::integral_constant&, const Policy& pol) { BOOST_MATH_STD_USING T a = fabs(x); - if ((boost::math::isnan)(a)) + if ((BOOST_MATH_NAMESPACE::isnan)(a)) { return policies::raise_domain_error("boost::math::expm1<%1%>(%1%)", "expm1 requires a finite argument, but got %1%", a, pol); } @@ -113,7 +114,7 @@ namespace boost { if (a < tools::epsilon()) return x; detail::expm1_series s(x); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); T result = tools::sum_series(s, policies::get_epsilon(), max_iter); @@ -123,12 +124,12 @@ namespace boost { // LCOV_EXCL_STOP template - BOOST_MATH_GPU_ENABLED T expm1_imp(T x, const boost::math::integral_constant&, const P& pol) + BOOST_MATH_GPU_ENABLED T expm1_imp(T x, const BOOST_MATH_NAMESPACE::integral_constant&, const P& pol) { BOOST_MATH_STD_USING T a = fabs(x); - if ((boost::math::isnan)(a)) + if ((BOOST_MATH_NAMESPACE::isnan)(a)) { return policies::raise_domain_error("boost::math::expm1<%1%>(%1%)", "expm1 requires a finite argument, but got %1%", a, pol); } @@ -154,12 +155,12 @@ namespace boost { } template - BOOST_MATH_GPU_ENABLED T expm1_imp(T x, const boost::math::integral_constant&, const P& pol) + BOOST_MATH_GPU_ENABLED T expm1_imp(T x, const BOOST_MATH_NAMESPACE::integral_constant&, const P& pol) { BOOST_MATH_STD_USING T a = fabs(x); - if ((boost::math::isnan)(a)) + if ((BOOST_MATH_NAMESPACE::isnan)(a)) { return policies::raise_domain_error("boost::math::expm1<%1%>(%1%)", "expm1 requires a finite argument, but got %1%", a, pol); } @@ -203,12 +204,12 @@ namespace boost { } template - BOOST_MATH_GPU_ENABLED T expm1_imp(T x, const boost::math::integral_constant&, const P& pol) + BOOST_MATH_GPU_ENABLED T expm1_imp(T x, const BOOST_MATH_NAMESPACE::integral_constant&, const P& pol) { BOOST_MATH_STD_USING T a = fabs(x); - if ((boost::math::isnan)(a)) + if ((BOOST_MATH_NAMESPACE::isnan)(a)) { return policies::raise_domain_error("boost::math::expm1<%1%>(%1%)", "expm1 requires a finite argument, but got %1%", a, pol); } @@ -260,7 +261,7 @@ namespace boost { } // namespace detail - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type expm1(T x, const Policy& /* pol */) { typedef typename tools::promote_args::type result_type; @@ -273,7 +274,7 @@ namespace boost { policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; - typedef boost::math::integral_constant + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline float expm1(float x, const Policy&) { - BOOST_MATH_IF_CONSTEXPR(Policy::domain_error_type::value != boost::math::policies::ignore_error && Policy::domain_error_type::value != boost::math::policies::errno_on_error) + BOOST_MATH_IF_CONSTEXPR(Policy::domain_error_type::value != BOOST_MATH_NAMESPACE::policies::ignore_error && Policy::domain_error_type::value != BOOST_MATH_NAMESPACE::policies::errno_on_error) { - if ((boost::math::isnan)(x)) + if ((BOOST_MATH_NAMESPACE::isnan)(x)) return policies::raise_domain_error("boost::math::expm1<%1%>(%1%)", "expm1 requires a finite argument, but got %1%", x, Policy()); } - BOOST_MATH_IF_CONSTEXPR(Policy::overflow_error_type::value != boost::math::policies::ignore_error && Policy::overflow_error_type::value != boost::math::policies::errno_on_error) + BOOST_MATH_IF_CONSTEXPR(Policy::overflow_error_type::value != BOOST_MATH_NAMESPACE::policies::ignore_error && Policy::overflow_error_type::value != BOOST_MATH_NAMESPACE::policies::errno_on_error) { if (x >= tools::log_max_value()) return policies::raise_overflow_error("boost::math::expm1<%1%>(%1%)", nullptr, Policy()); @@ -304,15 +305,15 @@ namespace boost { return std::expm1(x); } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - template + BOOST_MATH_EXPORT template inline long double expm1(long double x, const Policy&) { - BOOST_MATH_IF_CONSTEXPR(Policy::domain_error_type::value != boost::math::policies::ignore_error && Policy::domain_error_type::value != boost::math::policies::errno_on_error) + BOOST_MATH_IF_CONSTEXPR(Policy::domain_error_type::value != BOOST_MATH_NAMESPACE::policies::ignore_error && Policy::domain_error_type::value != BOOST_MATH_NAMESPACE::policies::errno_on_error) { - if ((boost::math::isnan)(x)) + if ((BOOST_MATH_NAMESPACE::isnan)(x)) return policies::raise_domain_error("boost::math::expm1<%1%>(%1%)", "expm1 requires a finite argument, but got %1%", x, Policy()); } - BOOST_MATH_IF_CONSTEXPR(Policy::overflow_error_type::value != boost::math::policies::ignore_error && Policy::overflow_error_type::value != boost::math::policies::errno_on_error) + BOOST_MATH_IF_CONSTEXPR(Policy::overflow_error_type::value != BOOST_MATH_NAMESPACE::policies::ignore_error && Policy::overflow_error_type::value != BOOST_MATH_NAMESPACE::policies::errno_on_error) { if (x >= tools::log_max_value()) return policies::raise_overflow_error("boost::math::expm1<%1%>(%1%)", nullptr, Policy()); @@ -320,15 +321,15 @@ namespace boost { return std::expm1(x); } #endif - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline double expm1(double x, const Policy&) { - BOOST_MATH_IF_CONSTEXPR(Policy::domain_error_type::value != boost::math::policies::ignore_error && Policy::domain_error_type::value != boost::math::policies::errno_on_error) + BOOST_MATH_IF_CONSTEXPR(Policy::domain_error_type::value != BOOST_MATH_NAMESPACE::policies::ignore_error && Policy::domain_error_type::value != BOOST_MATH_NAMESPACE::policies::errno_on_error) { - if ((boost::math::isnan)(x)) + if ((BOOST_MATH_NAMESPACE::isnan)(x)) return policies::raise_domain_error("boost::math::expm1<%1%>(%1%)", "expm1 requires a finite argument, but got %1%", x, Policy()); } - BOOST_MATH_IF_CONSTEXPR(Policy::overflow_error_type::value != boost::math::policies::ignore_error && Policy::overflow_error_type::value != boost::math::policies::errno_on_error) + BOOST_MATH_IF_CONSTEXPR(Policy::overflow_error_type::value != BOOST_MATH_NAMESPACE::policies::ignore_error && Policy::overflow_error_type::value != BOOST_MATH_NAMESPACE::policies::errno_on_error) { if (x >= tools::log_max_value()) return policies::raise_overflow_error("boost::math::expm1<%1%>(%1%)", nullptr, Policy()); @@ -336,7 +337,7 @@ namespace boost { return std::expm1(x); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type expm1(T x) { return expm1(x, policies::policy<>()); @@ -345,42 +346,40 @@ namespace boost { // Specific width floating point types: // #ifdef __STDCPP_FLOAT32_T__ - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline std::float32_t expm1(std::float32_t x, const Policy& pol) { - return boost::math::expm1(static_cast(x), pol); + return BOOST_MATH_NAMESPACE::expm1(static_cast(x), pol); } #endif #ifdef __STDCPP_FLOAT64_T__ - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline std::float64_t expm1(std::float64_t x, const Policy& pol) { - return boost::math::expm1(static_cast(x), pol); + return BOOST_MATH_NAMESPACE::expm1(static_cast(x), pol); } #endif #ifdef __STDCPP_FLOAT128_T__ - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline std::float128_t expm1(std::float128_t x, const Policy& pol) { if constexpr (std::numeric_limits::digits == std::numeric_limits::digits) { - return boost::math::expm1(static_cast(x), pol); + return BOOST_MATH_NAMESPACE::expm1(static_cast(x), pol); } else { - return boost::math::detail::expm1_imp(x, boost::math::integral_constant(), pol); + return BOOST_MATH_NAMESPACE::detail::expm1_imp(x, BOOST_MATH_NAMESPACE::integral_constant(), pol); } } #endif -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else // Special handling for NVRTC -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto expm1(T x) { return ::expm1(x); @@ -392,20 +391,19 @@ BOOST_MATH_GPU_ENABLED auto expm1(float x) return ::expm1f(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto expm1(T x, const Policy&) { return ::expm1(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto expm1(float x, const Policy&) { return ::expm1f(x); } -} // Namespace math -} // Namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC diff --git a/include/boost/math/special_functions/factorials.hpp b/include/boost/math/special_functions/factorials.hpp index ec6978bdc5..c95f889b40 100644 --- a/include/boost/math/special_functions/factorials.hpp +++ b/include/boost/math/special_functions/factorials.hpp @@ -26,13 +26,12 @@ #pragma warning(pop) #endif -namespace boost { namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T factorial(unsigned i, const Policy& pol) { - static_assert(!boost::math::is_integral::value, "Type T must not be an integral type"); + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value, "Type T must not be an integral type"); // factorial(n) is not implemented // because it would overflow integral type T for too small n // to be useful. Use instead a floating-point type, @@ -44,13 +43,13 @@ BOOST_MATH_GPU_ENABLED inline T factorial(unsigned i, const Policy& pol) if(i <= max_factorial::value) return unchecked_factorial(i); - T result = boost::math::tgamma(static_cast(i+1), pol); + T result = BOOST_MATH_NAMESPACE::tgamma(static_cast(i+1), pol); if(result > tools::max_value()) return result; // Overflowed value! (But tgamma will have signalled the error already). return floor(result + 0.5f); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T factorial(unsigned i) { return factorial(i, policies::policy<>()); @@ -73,10 +72,10 @@ inline double factorial(unsigned i) return tools::overflow_error(BOOST_CURRENT_FUNCTION); } */ -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T double_factorial(unsigned i, const Policy& pol) { - static_assert(!boost::math::is_integral::value, "Type T must not be an integral type"); + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value, "Type T must not be an integral type"); BOOST_MATH_STD_USING // ADL lookup of std names if(i & 1) { @@ -90,7 +89,7 @@ BOOST_MATH_GPU_ENABLED T double_factorial(unsigned i, const Policy& pol) // Fallthrough: i is too large to use table lookup, try the // gamma function instead. // - T result = boost::math::tgamma(static_cast(i) / 2 + 1, pol) / sqrt(constants::pi()); + T result = BOOST_MATH_NAMESPACE::tgamma(static_cast(i) / 2 + 1, pol) / sqrt(constants::pi()); if(ldexp(tools::max_value(), -static_cast(i+1) / 2) > result) return ceil(result * ldexp(T(1), static_cast(i+1) / 2) - 0.5f); } @@ -108,7 +107,7 @@ BOOST_MATH_GPU_ENABLED T double_factorial(unsigned i, const Policy& pol) return policies::raise_overflow_error("boost::math::double_factorial<%1%>(unsigned)", 0, pol); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T double_factorial(unsigned i) { return double_factorial(i, policies::policy<>()); @@ -122,7 +121,7 @@ namespace detail{ template T rising_factorial_imp(T x, int n, const Policy& pol) { - static_assert(!boost::math::is_integral::value, "Type T must not be an integral type"); + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value, "Type T must not be an integral type"); if(x < 0) { // @@ -146,17 +145,17 @@ T rising_factorial_imp(T x, int n, const Policy& pol) return result; } if(n == 0) - return 1; + return T(1); if(x == 0) { if(n < 0) - return static_cast(-boost::math::tgamma_delta_ratio(x + 1, static_cast(-n), pol)); + return static_cast(-BOOST_MATH_NAMESPACE::tgamma_delta_ratio(x + 1, static_cast(-n), pol)); else - return 0; + return T(0); } if((x < 1) && (x + n < 0)) { - const auto val = static_cast(boost::math::tgamma_delta_ratio(1 - x, static_cast(-n), pol)); + const auto val = static_cast(BOOST_MATH_NAMESPACE::tgamma_delta_ratio(1 - x, static_cast(-n), pol)); return (n & 1) ? T(-val) : val; } // @@ -164,16 +163,16 @@ T rising_factorial_imp(T x, int n, const Policy& pol) // tgamma_delta_ratio is already optimised for that // use case: // - return 1 / static_cast(boost::math::tgamma_delta_ratio(x, static_cast(n), pol)); + return 1 / static_cast(BOOST_MATH_NAMESPACE::tgamma_delta_ratio(x, static_cast(n), pol)); } template inline T falling_factorial_imp(T x, unsigned n, const Policy& pol) { - static_assert(!boost::math::is_integral::value, "Type T must not be an integral type"); + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value, "Type T must not be an integral type"); BOOST_MATH_STD_USING // ADL of std names if(x == 0) - return 0; + return T(0); if(x < 0) { // @@ -183,7 +182,7 @@ inline T falling_factorial_imp(T x, unsigned n, const Policy& pol) return (n&1 ? -1 : 1) * rising_factorial(-x, n, pol); } if(n == 0) - return 1; + return T(1); if(x < 0.5f) { // @@ -193,13 +192,13 @@ inline T falling_factorial_imp(T x, unsigned n, const Policy& pol) { // If the two end of the range are far apart we have a ratio of two very large // numbers, split the calculation up into two blocks: - T t1 = x * boost::math::falling_factorial(x - 1, max_factorial::value - 2, pol); - T t2 = boost::math::falling_factorial(x - max_factorial::value + 1, n - max_factorial::value + 1, pol); + T t1 = x * BOOST_MATH_NAMESPACE::falling_factorial(x - 1, max_factorial::value - 2, pol); + T t2 = BOOST_MATH_NAMESPACE::falling_factorial(x - max_factorial::value + 1, n - max_factorial::value + 1, pol); if(tools::max_value() / fabs(t1) < fabs(t2)) - return boost::math::sign(t1) * boost::math::sign(t2) * policies::raise_overflow_error("boost::math::falling_factorial<%1%>", 0, pol); + return BOOST_MATH_NAMESPACE::sign(t1) * BOOST_MATH_NAMESPACE::sign(t2) * policies::raise_overflow_error("boost::math::falling_factorial<%1%>", 0, pol); return t1 * t2; } - return x * boost::math::falling_factorial(x - 1, n - 1, pol); + return x * BOOST_MATH_NAMESPACE::falling_factorial(x - 1, n - 1, pol); } if(x <= n - 1) { @@ -210,8 +209,8 @@ inline T falling_factorial_imp(T x, unsigned n, const Policy& pol) T xp1 = x + 1; unsigned n2 = itrunc((T)floor(xp1), pol); if(n2 == xp1) - return 0; - auto result = static_cast(boost::math::tgamma_delta_ratio(xp1, -static_cast(n2), pol)); + return T(0); + auto result = static_cast(BOOST_MATH_NAMESPACE::tgamma_delta_ratio(xp1, -static_cast(n2), pol)); x -= n2; result *= x; ++n2; @@ -226,12 +225,12 @@ inline T falling_factorial_imp(T x, unsigned n, const Policy& pol) // because tgamma_delta_ratio is already optimised // for that use case: // - return static_cast(boost::math::tgamma_delta_ratio(x + 1, -static_cast(n), pol)); + return static_cast(BOOST_MATH_NAMESPACE::tgamma_delta_ratio(x + 1, -static_cast(n), pol)); } } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type falling_factorial(RT x, unsigned n) { @@ -240,7 +239,7 @@ inline typename tools::promote_args::type static_cast(x), n, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type falling_factorial(RT x, unsigned n, const Policy& pol) { @@ -249,7 +248,7 @@ inline typename tools::promote_args::type static_cast(x), n, pol); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type rising_factorial(RT x, int n) { @@ -258,7 +257,7 @@ inline typename tools::promote_args::type static_cast(x), n, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type rising_factorial(RT x, int n, const Policy& pol) { @@ -269,8 +268,7 @@ inline typename tools::promote_args::type #endif // BOOST_MATH_HAS_GPU_SUPPORT -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SP_FACTORIALS_HPP diff --git a/include/boost/math/special_functions/fibonacci.hpp b/include/boost/math/special_functions/fibonacci.hpp index e62fa89281..d8e4b80d74 100644 --- a/include/boost/math/special_functions/fibonacci.hpp +++ b/include/boost/math/special_functions/fibonacci.hpp @@ -10,22 +10,23 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #ifdef _MSC_VER #pragma once #endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { constexpr double fib_bits_phi = 0.69424191363061730173879026; constexpr double fib_bits_deno = 1.1609640474436811739351597; } // namespace detail -template +BOOST_MATH_EXPORT template inline BOOST_MATH_CXX14_CONSTEXPR T unchecked_fibonacci(unsigned long long n) noexcept(std::is_fundamental::value) { // This function is called by the rest and computes the actual nth fibonacci number // First few fibonacci numbers: 0 (0th), 1 (1st), 1 (2nd), 2 (3rd), ... @@ -49,7 +50,7 @@ inline BOOST_MATH_CXX14_CONSTEXPR T unchecked_fibonacci(unsigned long long n) no return a; } -template +BOOST_MATH_EXPORT template T inline BOOST_MATH_CXX14_CONSTEXPR fibonacci(unsigned long long n, const Policy &pol) { // check for overflow using approximation to binet's formula: F_n ~ phi^n / sqrt(5) if (n > 20 && n * detail::fib_bits_phi - detail::fib_bits_deno > std::numeric_limits::digits) @@ -57,13 +58,13 @@ T inline BOOST_MATH_CXX14_CONSTEXPR fibonacci(unsigned long long n, const Policy return unchecked_fibonacci(n); } -template +BOOST_MATH_EXPORT template T inline BOOST_MATH_CXX14_CONSTEXPR fibonacci(unsigned long long n) { return fibonacci(n, policies::policy<>()); } // generator for next fibonacci number (see examples/reciprocal_fibonacci_constant.hpp) -template +BOOST_MATH_EXPORT template class fibonacci_generator { public: // return next fibonacci number @@ -86,7 +87,6 @@ class fibonacci_generator { T a = 0, b = 1; }; -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/fourier_transform_daubechies.hpp b/include/boost/math/special_functions/fourier_transform_daubechies.hpp index 982e740233..3393bcf2cd 100644 --- a/include/boost/math/special_functions/fourier_transform_daubechies.hpp +++ b/include/boost/math/special_functions/fourier_transform_daubechies.hpp @@ -8,16 +8,18 @@ #ifndef BOOST_MATH_SPECIAL_FOURIER_TRANSFORM_DAUBECHIES_HPP #define BOOST_MATH_SPECIAL_FOURIER_TRANSFORM_DAUBECHIES_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include +#endif #include #include #include -namespace boost::math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -183,13 +185,13 @@ template constexpr std::array ft_daubechies * See more discusion near equation 6.1.1, * as well as efficiency gains from equation 7.1.4. */ -template std::complex fourier_transform_daubechies_scaling(Real omega) { +BOOST_MATH_EXPORT template std::complex fourier_transform_daubechies_scaling(Real omega) { // This arg promotion is kinda sad, but IMO the accuracy is not good enough in // float precision using this method. Requesting a better algorithm! if constexpr (std::is_same_v) { return static_cast>(fourier_transform_daubechies_scaling(static_cast(omega))); } - using boost::math::constants::one_div_root_two_pi; + using BOOST_MATH_NAMESPACE::constants::one_div_root_two_pi; using std::abs; using std::exp; using std::norm; @@ -214,7 +216,7 @@ template std::complex fourier_transform_daubechie do { std::complex arg{0, xi}; auto z = exp(arg); - phi *= boost::math::tools::evaluate_polynomial_estrin(lxi, z); + phi *= BOOST_MATH_NAMESPACE::tools::evaluate_polynomial_estrin(lxi, z); xi /= 2; } while (abs(xi) > std::numeric_limits::epsilon()); std::complex arg{0, omega}; @@ -224,7 +226,7 @@ template std::complex fourier_transform_daubechie return phi * static_cast>(pow(prefactor, p)); } -template std::complex fourier_transform_daubechies_wavelet(Real omega) { +BOOST_MATH_EXPORT template std::complex fourier_transform_daubechies_wavelet(Real omega) { // See Daubechies, 10 Lectures on Wavelets, page 193, unlabelled equation in Theorem 6.3.6: // 𝓕[ψ](ω) = -exp(-iω/2)m₀(ω/2 + π)^{*}𝓕[𝜙](ω/2) if constexpr (std::is_same_v) { @@ -240,9 +242,9 @@ template std::complex fourier_transform_daubechie auto z = phase; // strange coincidence. //auto z = exp(std::complex(0, -omega/2 - boost::math::constants::pi())); auto constexpr lxi = detail::ft_daubechies_scaling_polynomial_coefficients(); - auto m0 = std::complex(pow((Real(1) + z)/Real(2), p))*boost::math::tools::evaluate_polynomial_estrin(lxi, z); + auto m0 = std::complex(pow((Real(1) + z)/Real(2), p))*BOOST_MATH_NAMESPACE::tools::evaluate_polynomial_estrin(lxi, z); return Fphi*std::conj(m0)*phase; } -} // namespace boost::math +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/fpclassify.hpp b/include/boost/math/special_functions/fpclassify.hpp index c17b4a3a0b..7f6412db13 100644 --- a/include/boost/math/special_functions/fpclassify.hpp +++ b/include/boost/math/special_functions/fpclassify.hpp @@ -19,9 +19,11 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif /*! \file fpclassify.hpp @@ -84,7 +86,7 @@ is used. #ifdef BOOST_MATH_HAS_GPU_SUPPORT -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN template<> BOOST_MATH_GPU_ENABLED inline bool (isnan)(float x) { return x != x; } template<> BOOST_MATH_GPU_ENABLED inline bool (isnan)(double x) { return x != x; } @@ -108,7 +110,7 @@ template<> BOOST_MATH_GPU_ENABLED inline bool (isnormal)(double x) template<> BOOST_MATH_GPU_ENABLED inline int (fpclassify)(float t) { - if((boost::math::isnan)(t)) + if((BOOST_MATH_NAMESPACE::isnan)(t)) return FP_NAN; // std::fabs broken on a few systems especially for long long!!!! float at = (t < 0.0f) ? -t : t; @@ -132,7 +134,7 @@ template<> BOOST_MATH_GPU_ENABLED inline int (fpclassify)(float t) template<> BOOST_MATH_GPU_ENABLED inline int (fpclassify)(double t) { - if((boost::math::isnan)(t)) + if((BOOST_MATH_NAMESPACE::isnan)(t)) return FP_NAN; // std::fabs broken on a few systems especially for long long!!!! double at = (t < 0.0) ? -t : t; @@ -157,8 +159,10 @@ template<> BOOST_MATH_GPU_ENABLED inline int (fpclassify)(double t) #else #if defined(_MSC_VER) || defined(BOOST_BORLANDC) +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif #ifdef BOOST_MATH_USE_FLOAT128 #ifdef __has_include #if __has_include("quadmath.h") @@ -172,14 +176,12 @@ template<> BOOST_MATH_GPU_ENABLED inline int (fpclassify)(double t) namespace std{ using ::abs; using ::fabs; } #endif -namespace boost{ - // // This must not be located in any namespace under boost::math // otherwise we can get into an infinite loop if isnan is // a #define for "isnan" ! // -namespace math_detail{ +BOOST_MATH_DETAIL_NAMESPACE_BEGIN #ifdef _MSC_VER #pragma warning(push) @@ -217,13 +219,13 @@ inline bool is_nan_helper(__float128 f, const std::false_type&) { return ::isnan inline bool is_nan_helper(__float128 f, const std::true_type&) { return std::isnan(static_cast(f)); } inline bool is_nan_helper(__float128 f, const std::false_type&) { return std::isnan(static_cast(f)); } #else -inline bool is_nan_helper(__float128 f, const std::true_type&) { return boost::math::isnan(static_cast(f)); } -inline bool is_nan_helper(__float128 f, const std::false_type&) { return boost::math::isnan(static_cast(f)); } +inline bool is_nan_helper(__float128 f, const std::true_type&) { return BOOST_MATH_NAMESPACE::isnan(static_cast(f)); } +inline bool is_nan_helper(__float128 f, const std::false_type&) { return BOOST_MATH_NAMESPACE::isnan(static_cast(f)); } #endif #endif -} +BOOST_MATH_DETAIL_NAMESPACE_END -namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -242,13 +244,13 @@ inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag&) // whenever possible check for Nan's first: #if defined(BOOST_HAS_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) - if(::boost::math_detail::is_nan_helper(t, typename std::is_floating_point::type())) + if(BOOST_MATH_DETAIL_NAMESPACE::is_nan_helper(t, typename std::is_floating_point::type())) return FP_NAN; // LCOV_EXCL_LINE only called in UDT contexts (excluded from coverage checks). #elif defined(isnan) - if(boost::math_detail::is_nan_helper(t, typename std::is_floating_point::type())) + if(BOOST_MATH_DETAIL_NAMESPACE::is_nan_helper(t, typename std::is_floating_point::type())) return FP_NAN; #elif defined(_MSC_VER) || defined(BOOST_BORLANDC) - if(::_isnan(boost::math::tools::real_cast(t))) + if(::_isnan(BOOST_MATH_NAMESPACE::tools::real_cast(t))) return FP_NAN; #endif // std::fabs broken on a few systems especially for long long!!!! @@ -346,13 +348,13 @@ int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag) #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)) inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) { - return boost::math::detail::fpclassify_imp(t, generic_tag()); + return BOOST_MATH_NAMESPACE::detail::fpclassify_imp(t, generic_tag()); } #endif } // namespace detail -template +BOOST_MATH_EXPORT template inline int fpclassify BOOST_NO_MACRO_EXPAND(T t) { typedef typename detail::fp_traits::type traits; @@ -425,7 +427,7 @@ namespace detail { #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) { - return boost::math::detail::isfinite_impl(t, generic_tag()); + return BOOST_MATH_NAMESPACE::detail::isfinite_impl(t, generic_tag()); } #endif @@ -496,7 +498,7 @@ namespace detail { #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) { - return boost::math::detail::isnormal_impl(t, generic_tag()); + return BOOST_MATH_NAMESPACE::detail::isnormal_impl(t, generic_tag()); } #endif @@ -585,7 +587,7 @@ namespace detail { #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) { - return boost::math::detail::isinf_impl(t, generic_tag()); + return BOOST_MATH_NAMESPACE::detail::isinf_impl(t, generic_tag()); } #endif @@ -691,9 +693,9 @@ inline bool (isnan)(T x) } #ifdef isnan -template <> inline bool isnan BOOST_NO_MACRO_EXPAND(float t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); } -template <> inline bool isnan BOOST_NO_MACRO_EXPAND(double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); } -template <> inline bool isnan BOOST_NO_MACRO_EXPAND(long double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); } +template <> inline bool isnan BOOST_NO_MACRO_EXPAND(float t){ return BOOST_MATH_DETAIL_NAMESPACE::is_nan_helper(t, std::true_type()); } +template <> inline bool isnan BOOST_NO_MACRO_EXPAND(double t){ return BOOST_MATH_DETAIL_NAMESPACE::is_nan_helper(t, std::true_type()); } +template <> inline bool isnan BOOST_NO_MACRO_EXPAND(long double t){ return BOOST_MATH_DETAIL_NAMESPACE::is_nan_helper(t, std::true_type()); } #elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) template<> inline bool (isnan)(long double x) @@ -714,69 +716,67 @@ inline bool (isnan)(__float128 x) #endif -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else // Special handling generally using the CUDA library #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> BOOST_MATH_GPU_ENABLED inline bool isnan(T x) { return false; } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> BOOST_MATH_GPU_ENABLED inline bool isnan(T x) { return ::isnan(x); } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> BOOST_MATH_GPU_ENABLED inline bool isinf(T x) { return false; } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> BOOST_MATH_GPU_ENABLED inline bool isinf(T x) { return ::isinf(x); } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> BOOST_MATH_GPU_ENABLED inline bool isfinite(T x) { return true; } -template , bool> = true> +BOOST_MATH_EXPORT template , bool> = true> BOOST_MATH_GPU_ENABLED inline bool isfinite(T x) { return ::isfinite(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline bool isnormal(T x) { return x != static_cast(0) && x != static_cast(-0) && - !boost::math::isnan(x) && - !boost::math::isinf(x); + !BOOST_MATH_NAMESPACE::isnan(x) && + !BOOST_MATH_NAMESPACE::isinf(x); } // We skip the check for FP_SUBNORMAL since they are not supported on these platforms -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline int fpclassify(T x) { - if (boost::math::isnan(x)) + if (BOOST_MATH_NAMESPACE::isnan(x)) { return BOOST_MATH_FP_NAN; } - else if (boost::math::isinf(x)) + else if (BOOST_MATH_NAMESPACE::isinf(x)) { return BOOST_MATH_FP_INFINITE; } @@ -788,8 +788,7 @@ BOOST_MATH_GPU_ENABLED inline int fpclassify(T x) return BOOST_MATH_FP_NORMAL; } -} // Namespace math -} // Namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC diff --git a/include/boost/math/special_functions/gamma.hpp b/include/boost/math/special_functions/gamma.hpp index a9c17da882..de3de96c13 100644 --- a/include/boost/math/special_functions/gamma.hpp +++ b/include/boost/math/special_functions/gamma.hpp @@ -54,18 +54,18 @@ // TODO - revisit this? #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template -BOOST_MATH_GPU_ENABLED inline bool is_odd(T v, const boost::math::true_type&) +BOOST_MATH_GPU_ENABLED inline bool is_odd(T v, const BOOST_MATH_NAMESPACE::true_type&) { int i = static_cast(v); return i&1; } template -BOOST_MATH_GPU_ENABLED inline bool is_odd(T v, const boost::math::false_type&) +BOOST_MATH_GPU_ENABLED inline bool is_odd(T v, const BOOST_MATH_NAMESPACE::false_type&) { // Oh dear can't cast T to int! BOOST_MATH_STD_USING @@ -75,7 +75,7 @@ BOOST_MATH_GPU_ENABLED inline bool is_odd(T v, const boost::math::false_type&) template BOOST_MATH_GPU_ENABLED inline bool is_odd(T v) { - return is_odd(v, ::boost::math::is_convertible()); + return is_odd(v, ::BOOST_MATH_NAMESPACE::is_convertible()); } template @@ -104,7 +104,7 @@ BOOST_MATH_GPU_ENABLED T sinpx(T z) BOOST_MATH_ASSERT(fl >= 0); if(dist > T(0.5)) dist = 1 - dist; - T result = sin(dist*boost::math::constants::pi()); + T result = sin(dist*BOOST_MATH_NAMESPACE::constants::pi()); return sign*z*result; } // template T sinpx(T z) // @@ -153,7 +153,7 @@ BOOST_MATH_GPU_ENABLED T gamma_imp_final(T z, const Policy& pol, const Lanczos& else { result *= Lanczos::lanczos_sum(z); - T zgh = (z + static_cast(Lanczos::g()) - boost::math::constants::half()); + T zgh = (z + static_cast(Lanczos::g()) - BOOST_MATH_NAMESPACE::constants::half()); T lzgh = log(zgh); BOOST_MATH_INSTRUMENT_VARIABLE(result); BOOST_MATH_INSTRUMENT_VARIABLE(tools::log_max_value()); @@ -162,22 +162,22 @@ BOOST_MATH_GPU_ENABLED T gamma_imp_final(T z, const Policy& pol, const Lanczos& // we're going to overflow unless this is done with care: BOOST_MATH_INSTRUMENT_VARIABLE(zgh); if(lzgh * z / 2 > tools::log_max_value()) - return boost::math::sign(result) * policies::raise_overflow_error(function, "Result of tgamma is too large to represent.", pol); + return BOOST_MATH_NAMESPACE::sign(result) * policies::raise_overflow_error(function, "Result of tgamma is too large to represent.", pol); T hp = pow(zgh, T((z / 2) - T(0.25))); BOOST_MATH_INSTRUMENT_VARIABLE(hp); result *= hp / exp(zgh); BOOST_MATH_INSTRUMENT_VARIABLE(result); if(tools::max_value() / hp < result) - return boost::math::sign(result) * policies::raise_overflow_error(function, "Result of tgamma is too large to represent.", pol); + return BOOST_MATH_NAMESPACE::sign(result) * policies::raise_overflow_error(function, "Result of tgamma is too large to represent.", pol); result *= hp; BOOST_MATH_INSTRUMENT_VARIABLE(result); } else { BOOST_MATH_INSTRUMENT_VARIABLE(zgh); - BOOST_MATH_INSTRUMENT_VARIABLE(pow(zgh, T(z - boost::math::constants::half()))); + BOOST_MATH_INSTRUMENT_VARIABLE(pow(zgh, T(z - BOOST_MATH_NAMESPACE::constants::half()))); BOOST_MATH_INSTRUMENT_VARIABLE(exp(zgh)); - result *= pow(zgh, T(z - boost::math::constants::half())) / exp(zgh); + result *= pow(zgh, T(z - BOOST_MATH_NAMESPACE::constants::half())) / exp(zgh); BOOST_MATH_INSTRUMENT_VARIABLE(result); } } @@ -216,9 +216,9 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T gamma_imp(T z, const Policy& pol } #endif BOOST_MATH_INSTRUMENT_VARIABLE(result); - BOOST_MATH_IF_CONSTEXPR(!boost::math::numeric_limits::is_specialized || (boost::math::numeric_limits::digits > 64)) + BOOST_MATH_IF_CONSTEXPR(!BOOST_MATH_NAMESPACE::numeric_limits::is_specialized || (BOOST_MATH_NAMESPACE::numeric_limits::digits > 64)) { - if ((fabs(result) < 1) && (tools::max_value() * fabs(result) < boost::math::constants::pi())) + if ((fabs(result) < 1) && (tools::max_value() * fabs(result) < BOOST_MATH_NAMESPACE::constants::pi())) { return policies::raise_overflow_error(function, nullptr, pol); // LCOV_EXCL_LINE MP only. @@ -230,14 +230,14 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T gamma_imp(T z, const Policy& pol // Specifically, sinpx can never be larger than 1 / epsilon which is too small to // ever generate a value less than one for `result`, unless T has a truely // exceptional number of digits precision. - BOOST_MATH_ASSERT((fabs(result) > 1) || (tools::max_value() * fabs(result) > boost::math::constants::pi())); + BOOST_MATH_ASSERT((fabs(result) > 1) || (tools::max_value() * fabs(result) > BOOST_MATH_NAMESPACE::constants::pi())); } - result = -boost::math::constants::pi() / result; + result = -BOOST_MATH_NAMESPACE::constants::pi() / result; if (result == 0) return policies::raise_underflow_error(function, "Result of tgamma is too small to represent.", pol); /* * Result can never be subnormal as we have a value > 1 in the numerator: - if((boost::math::fpclassify)(result) == (int)FP_SUBNORMAL) + if((BOOST_MATH_NAMESPACE::fpclassify)(result) == (int)FP_SUBNORMAL) return policies::raise_denorm_error(function, "Result of tgamma is denormalized.", result, pol); */ BOOST_MATH_INSTRUMENT_VARIABLE(result); @@ -288,7 +288,7 @@ BOOST_MATH_GPU_ENABLED T lgamma_imp_final(T z, const Policy& pol, const Lanczos& else if(z < 15) { typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant(z, T(z - 1), T(z - 2), tag_type(), pol, l); } - else if((z >= 3) && (z < 100) && (boost::math::numeric_limits::max_exponent >= 1024)) + else if((z >= 3) && (z < 100) && (BOOST_MATH_NAMESPACE::numeric_limits::max_exponent >= 1024)) { // taking the log of tgamma reduces the error, no danger of overflow here: result = log(gamma_imp(z, pol, l)); @@ -304,7 +304,7 @@ BOOST_MATH_GPU_ENABLED T lgamma_imp_final(T z, const Policy& pol, const Lanczos& else { // regular evaluation: - T zgh = static_cast(z + T(Lanczos::g()) - boost::math::constants::half()); + T zgh = static_cast(z + T(Lanczos::g()) - BOOST_MATH_NAMESPACE::constants::half()); result = log(zgh) - 1; result *= z - 0.5f; // @@ -349,7 +349,7 @@ BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T lgamma_imp(T z, const Policy& po { sresult = -sresult; } - result = log(boost::math::constants::pi()) - lgamma_imp_final(T(z), pol, l) - log(t); + result = log(BOOST_MATH_NAMESPACE::constants::pi()) - lgamma_imp_final(T(z), pol, l) - log(t); if(sign) { @@ -378,7 +378,7 @@ struct upper_incomplete_gamma_fract T z, a; int k; public: - typedef boost::math::pair result_type; + typedef BOOST_MATH_NAMESPACE::pair result_type; BOOST_MATH_GPU_ENABLED upper_incomplete_gamma_fract(T a1, T z1) : z(z1-a1+1), a(a1), k(0) @@ -400,7 +400,7 @@ BOOST_MATH_GPU_ENABLED inline T upper_gamma_fraction(T a, T z, T eps) // upper incomplete integral. Divide by tgamma(z) // to normalise. upper_incomplete_gamma_fract f(a, z); - return 1 / (z - a + 1 + boost::math::tools::continued_fraction_a(f, eps)); + return 1 / (z - a + 1 + BOOST_MATH_NAMESPACE::tools::continued_fraction_a(f, eps)); } template @@ -428,9 +428,9 @@ BOOST_MATH_GPU_ENABLED inline T lower_gamma_series(T a, T z, const Policy& pol, // lower incomplete integral. Then divide by tgamma(a) // to get the normalised value. lower_incomplete_gamma_series s(a, z); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); T factor = policies::get_epsilon(); - T result = boost::math::tools::sum_series(s, factor, max_iter, init_value); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, factor, max_iter, init_value); policies::check_series_iterations("boost::math::detail::lower_gamma_series<%1%>(%1%)", max_iter, pol); return result; } @@ -442,14 +442,14 @@ BOOST_MATH_GPU_ENABLED inline T lower_gamma_series(T a, T z, const Policy& pol, // with Bernoulli numbers. // template -boost::math::size_t highest_bernoulli_index() +BOOST_MATH_NAMESPACE::size_t highest_bernoulli_index() { - const float digits10_of_type = (boost::math::numeric_limits::is_specialized - ? static_cast(boost::math::numeric_limits::digits10) - : static_cast(boost::math::tools::digits() * 0.301F)); + const float digits10_of_type = (BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + ? static_cast(BOOST_MATH_NAMESPACE::numeric_limits::digits10) + : static_cast(BOOST_MATH_NAMESPACE::tools::digits() * 0.301F)); // Find the high index n for Bn to produce the desired precision in Stirling's calculation. - return static_cast(18.0F + (0.6F * digits10_of_type)); + return static_cast(18.0F + (0.6F * digits10_of_type)); } template @@ -457,9 +457,9 @@ int minimum_argument_for_bernoulli_recursion() { BOOST_MATH_STD_USING - const float digits10_of_type = (boost::math::numeric_limits::is_specialized - ? (float) boost::math::numeric_limits::digits10 - : (float) (boost::math::tools::digits() * 0.301F)); + const float digits10_of_type = (BOOST_MATH_NAMESPACE::numeric_limits::is_specialized + ? (float) BOOST_MATH_NAMESPACE::numeric_limits::digits10 + : (float) (BOOST_MATH_NAMESPACE::tools::digits() * 0.301F)); int min_arg = (int) (digits10_of_type * 1.7F); @@ -487,34 +487,28 @@ int minimum_argument_for_bernoulli_recursion() } template -T scaled_tgamma_no_lanczos(const T& z, const Policy& pol, bool islog = false) -{ +T bernoulli_stirling_series(const T& z, const Policy& pol) { BOOST_MATH_STD_USING - // - // Calculates tgamma(z) / (z/e)^z - // Requires that our argument is large enough for Sterling's approximation to hold. - // Used internally when combining gamma's of similar magnitude without logarithms. - // + BOOST_MATH_ASSERT(minimum_argument_for_bernoulli_recursion() <= z); // Perform the Bernoulli series expansion of Stirling's approximation. - const boost::math::size_t number_of_bernoullis_b2n = policies::get_max_series_iterations(); + const BOOST_MATH_NAMESPACE::size_t number_of_bernoullis_b2n = policies::get_max_series_iterations(); T one_over_x_pow_two_n_minus_one = 1 / z; const T one_over_x2 = one_over_x_pow_two_n_minus_one * one_over_x_pow_two_n_minus_one; - T sum = (boost::math::bernoulli_b2n(1) / 2) * one_over_x_pow_two_n_minus_one; - const T target_epsilon_to_break_loop = sum * boost::math::tools::epsilon(); - const T half_ln_two_pi_over_z = sqrt(boost::math::constants::two_pi() / z); + T sum = (BOOST_MATH_NAMESPACE::bernoulli_b2n(1) / 2) * one_over_x_pow_two_n_minus_one; + const T target_epsilon_to_break_loop = sum * BOOST_MATH_NAMESPACE::tools::epsilon(); T last_term = 2 * sum; - for (boost::math::size_t n = 2U;; ++n) + for (BOOST_MATH_NAMESPACE::size_t n = 2U;; ++n) { one_over_x_pow_two_n_minus_one *= one_over_x2; - const boost::math::size_t n2 = static_cast(n * 2U); + const BOOST_MATH_NAMESPACE::size_t n2 = static_cast(n * 2U); - const T term = (boost::math::bernoulli_b2n(static_cast(n)) * one_over_x_pow_two_n_minus_one) / (n2 * (n2 - 1U)); + const T term = (BOOST_MATH_NAMESPACE::bernoulli_b2n(static_cast(n)) * one_over_x_pow_two_n_minus_one) / (n2 * (n2 - 1U)); if ((n >= 3U) && (abs(term) < target_epsilon_to_break_loop)) { @@ -527,7 +521,7 @@ T scaled_tgamma_no_lanczos(const T& z, const Policy& pol, bool islog = false) } if (n > number_of_bernoullis_b2n) // Safety net, we hope to never get here: - return policies::raise_evaluation_error("scaled_tgamma_no_lanczos<%1%>()", "Exceeded maximum series iterations without reaching convergence, best approximation was %1%", T(exp(sum) * half_ln_two_pi_over_z), pol); // LCOV_EXCL_LINE + return policies::raise_evaluation_error("bernoulli_stirling_series<%1%>()", "Exceeded maximum series iterations without reaching convergence, best approximation was %1%", sum, pol); // LCOV_EXCL_LINE sum += term; @@ -535,9 +529,25 @@ T scaled_tgamma_no_lanczos(const T& z, const Policy& pol, bool islog = false) T fterm = fabs(term); if(fterm > last_term) // Safety net, we hope to never get here: - return policies::raise_evaluation_error("scaled_tgamma_no_lanczos<%1%>()", "Series became divergent without reaching convergence, best approximation was %1%", T(exp(sum) * half_ln_two_pi_over_z), pol); // LCOV_EXCL_LINE + return policies::raise_evaluation_error("bernoulli_stirling_series<%1%>()", "Series became divergent without reaching convergence, best approximation was %1%", sum, pol); // LCOV_EXCL_LINE last_term = fterm; } + return sum; +} + +template +T scaled_tgamma_no_lanczos(const T& z, const Policy& pol, bool islog = false) +{ + BOOST_MATH_STD_USING + // + // Calculates tgamma(z) / (z/e)^z + // Requires that our argument is large enough for Sterling's approximation to hold. + // Used internally when combining gamma's of similar magnitude without logarithms. + // + BOOST_MATH_ASSERT(minimum_argument_for_bernoulli_recursion() <= z); + + T sum = bernoulli_stirling_series(z, pol); + const T half_ln_two_pi_over_z = sqrt(BOOST_MATH_NAMESPACE::constants::two_pi() / z); // Complete Stirling's approximation. T scaled_gamma_value = islog ? T(sum + log(half_ln_two_pi_over_z)) : T(exp(sum) * half_ln_two_pi_over_z); @@ -558,7 +568,7 @@ T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&) // Check if the argument of tgamma is identically zero. const bool is_at_zero = (z == 0); - if((boost::math::isnan)(z) || (is_at_zero) || ((boost::math::isinf)(z) && (z < 0))) + if((BOOST_MATH_NAMESPACE::isnan)(z) || (is_at_zero) || ((BOOST_MATH_NAMESPACE::isinf)(z) && (z < 0))) return policies::raise_domain_error(function, "Evaluation of tgamma at %1%.", z, pol); const bool b_neg = (z < 0); @@ -566,9 +576,9 @@ T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&) const bool floor_of_z_is_equal_to_z = (floor(z) == z); // Special case handling of small factorials: - if((!b_neg) && floor_of_z_is_equal_to_z && (z < boost::math::max_factorial::value)) + if((!b_neg) && floor_of_z_is_equal_to_z && (z < BOOST_MATH_NAMESPACE::max_factorial::value)) { - return boost::math::unchecked_factorial(static_cast(itrunc(z) - 1)); + return BOOST_MATH_NAMESPACE::unchecked_factorial(static_cast(itrunc(z) - 1)); } // Make a local, unsigned copy of the input argument. @@ -578,9 +588,9 @@ T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&) if(zz < tools::cbrt_epsilon()) { const T a0(1); - const T a1(boost::math::constants::euler()); - const T six_euler_squared((boost::math::constants::euler() * boost::math::constants::euler()) * 6); - const T a2((six_euler_squared - boost::math::constants::pi_sqr()) / 12); + const T a1(BOOST_MATH_NAMESPACE::constants::euler()); + const T six_euler_squared((BOOST_MATH_NAMESPACE::constants::euler() * BOOST_MATH_NAMESPACE::constants::euler()) * 6); + const T a2((six_euler_squared - BOOST_MATH_NAMESPACE::constants::pi_sqr()) / 12); const T inverse_tgamma_series = z * ((a2 * z + a1) * z + a0); @@ -595,7 +605,7 @@ T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&) if(zz < min_arg_for_recursion) { - n_recur = boost::math::itrunc(min_arg_for_recursion - zz) + 1; + n_recur = BOOST_MATH_NAMESPACE::itrunc(min_arg_for_recursion - zz) + 1; zz += n_recur; } @@ -655,9 +665,9 @@ T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&) // // Result can never overflow, since sinpx(z) can never be smaller than machine epsilon and gamma_value > 1. // - BOOST_MATH_ASSERT( (abs(gamma_value) > 1) || ((tools::max_value() * abs(gamma_value)) > boost::math::constants::pi())); // LCOV_EXCL_LINE MP only + BOOST_MATH_ASSERT( (abs(gamma_value) > 1) || ((tools::max_value() * abs(gamma_value)) > BOOST_MATH_NAMESPACE::constants::pi())); // LCOV_EXCL_LINE MP only - gamma_value = -boost::math::constants::pi() / gamma_value; + gamma_value = -BOOST_MATH_NAMESPACE::constants::pi() / gamma_value; BOOST_MATH_INSTRUMENT_VARIABLE(gamma_value); // LCOV_EXCL_LINE MP only // @@ -677,6 +687,11 @@ inline T log_gamma_near_1(const T& z, Policy const& pol) // no lanczos support, use a taylor series at z = 1, // see https://www.wolframalpha.com/input/?i=taylor+series+lgamma(x)+at+x+%3D+1 // + // The series is lgamma(1 + z) = -gamma z + sum_{n >= 2} (-1)^n zeta(n) z^n / n, where + // polygamma(n - 1, 1) = (-1)^n (n - 1)! zeta(n). Since zeta(n) -> 1 this only converges + // like z^n, so remove the terms (-z)^n / n of zeta(n) = 1 + ..., which sum to + // -log1p(z) + z, leaving terms which converge like (z / 2)^n. + // BOOST_MATH_STD_USING // ADL of std names // For some reason, several lines aren't triggered for coverage even though @@ -684,18 +699,20 @@ inline T log_gamma_near_1(const T& z, Policy const& pol) BOOST_MATH_ASSERT(fabs(z) < 1); // LCOV_EXCL_LINE - T result = -constants::euler() * z; + T result = (1 - constants::euler()) * z - BOOST_MATH_NAMESPACE::log1p(z, pol); T power_term = z * z / 2; + T negated_power = z * z; int n = 2; // LCOV_EXCL_LINE T term = 0; // LCOV_EXCL_LINE do { - term = power_term * boost::math::polygamma(n - 1, T(1), pol); + term = power_term * BOOST_MATH_NAMESPACE::polygamma(n - 1, T(1), pol) - negated_power / n; result += term; // LCOV_EXCL_LINE ++n; power_term *= z / n; + negated_power *= -z; } while (fabs(result) * tools::epsilon() < fabs(term)); return result; @@ -713,9 +730,9 @@ T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sig if(is_at_zero) return policies::raise_domain_error(function, "Evaluation of lgamma at zero %1%.", z, pol); - if((boost::math::isnan)(z)) + if((BOOST_MATH_NAMESPACE::isnan)(z)) return policies::raise_domain_error(function, "Evaluation of lgamma at %1%.", z, pol); - if((boost::math::isinf)(z)) + if((BOOST_MATH_NAMESPACE::isinf)(z)) return policies::raise_overflow_error(function, nullptr, pol); const bool b_neg = (z < 0); @@ -723,11 +740,11 @@ T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sig const bool floor_of_z_is_equal_to_z = (floor(z) == z); // Special case handling of small factorials: - if((!b_neg) && floor_of_z_is_equal_to_z && (z < boost::math::max_factorial::value)) + if((!b_neg) && floor_of_z_is_equal_to_z && (z < BOOST_MATH_NAMESPACE::max_factorial::value)) { if (sign) *sign = 1; // LCOV_EXCL_LINE - return log(boost::math::unchecked_factorial(itrunc(z) - 1)); + return log(BOOST_MATH_NAMESPACE::unchecked_factorial(itrunc(z) - 1)); } // Make a local, unsigned copy of the input argument. @@ -801,7 +818,7 @@ T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sig sign_of_result = -sign_of_result; // LCOV_EXCL_LINE MP only } - log_gamma_value = - log_gamma_value + log(boost::math::constants::pi()) - log(t); + log_gamma_value = - log_gamma_value + log(BOOST_MATH_NAMESPACE::constants::pi()) - log(t); } if(sign != static_cast(nullptr)) { *sign = sign_of_result; } @@ -824,6 +841,30 @@ template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma(RT1 a, RT2 z, const Policy& pol); #endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT +// +// Calculates tgamma(z+1)-1 for -0.5 <= z < 2.5 for types without rational approximations +// to lgamma. Their lanczos approximations are accurate to the precision of the type, but +// this is not enough to avoid losing a few digits to cancellation here. +// Reduce to a Taylor series at 1 using tgamma(1 + w + n) = tgamma(1 + w) (1 + w) ... (n + w) +// with -1/2 <= w < 0.6 (w is exact), and take the expm1 of lgamma: +// +template +T tgammap1m1_series(T z, Policy const& pol) +{ + BOOST_MATH_STD_USING + + int n = z < T(0.6f) ? 0 : z < T(1.6f) ? 1 : 2; + T w = z - n; + T result = log_gamma_near_1(w, pol); + if(n >= 1) + result += BOOST_MATH_NAMESPACE::log1p(w, pol); + if(n == 2) + result += log(w + 2); + return BOOST_MATH_NAMESPACE::expm1(result, pol); +} +#endif // BOOST_MATH_HAS_GPU_SUPPORT + // // This helper calculates tgamma(dz+1)-1 without cancellation errors, // used by the upper incomplete gamma with z < 1: @@ -835,13 +876,22 @@ BOOST_MATH_GPU_ENABLED T tgammap1m1_imp(T dz, Policy const& pol, const Lanczos& typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant tag_type; T result{}; +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + BOOST_MATH_IF_CONSTEXPR(precision_type::value > 113) + { + // Too many digits for the rational approximations to lgamma, the generic code + // below is not accurate enough: + if((dz >= T(-0.5)) && (dz < T(2.5))) + return tgammap1m1_series(dz, pol); + } +#endif if(dz < 0) { if(dz < T(-0.5)) @@ -850,14 +900,14 @@ BOOST_MATH_GPU_ENABLED T tgammap1m1_imp(T dz, Policy const& pol, const Lanczos& #ifdef BOOST_MATH_HAS_NVRTC result = ::tgamma(1+dz); #else - result = boost::math::tgamma(1+dz, pol) - 1; + result = BOOST_MATH_NAMESPACE::tgamma(1+dz, pol) - 1; #endif BOOST_MATH_INSTRUMENT_CODE(result); } else { // Use expm1 on lgamma: - result = boost::math::expm1(-boost::math::log1p(dz, pol) + result = BOOST_MATH_NAMESPACE::expm1(-BOOST_MATH_NAMESPACE::log1p(dz, pol) + lgamma_small_imp(dz+2, dz + 1, dz, tag_type(), pol, l), pol); BOOST_MATH_INSTRUMENT_CODE(result); } @@ -867,7 +917,7 @@ BOOST_MATH_GPU_ENABLED T tgammap1m1_imp(T dz, Policy const& pol, const Lanczos& if(dz < 2) { // Use expm1 on lgamma: - result = boost::math::expm1(lgamma_small_imp(dz+1, dz, dz-1, tag_type(), pol, l), pol); + result = BOOST_MATH_NAMESPACE::expm1(lgamma_small_imp(dz+1, dz, dz-1, tag_type(), pol, l), pol); BOOST_MATH_INSTRUMENT_CODE(result); } else @@ -876,7 +926,7 @@ BOOST_MATH_GPU_ENABLED T tgammap1m1_imp(T dz, Policy const& pol, const Lanczos& #ifdef BOOST_MATH_HAS_NVRTC result = ::tgamma(1+dz); #else - result = boost::math::tgamma(1+dz, pol) - 1; + result = BOOST_MATH_NAMESPACE::tgamma(1+dz, pol) - 1; #endif BOOST_MATH_INSTRUMENT_CODE(result); } @@ -889,15 +939,15 @@ BOOST_MATH_GPU_ENABLED T tgammap1m1_imp(T dz, Policy const& pol, const Lanczos& template inline T tgammap1m1_imp(T z, Policy const& pol, - const ::boost::math::lanczos::undefined_lanczos&) + const ::BOOST_MATH_NAMESPACE::lanczos::undefined_lanczos&) { BOOST_MATH_STD_USING // ADL of std names - if(fabs(z) < T(0.55)) + if((z >= T(-0.5)) && (z < T(2.5))) { - return boost::math::expm1(log_gamma_near_1(z, pol)); + return tgammap1m1_series(z, pol); } - return boost::math::expm1(boost::math::lgamma(1 + z, pol)); + return BOOST_MATH_NAMESPACE::expm1(BOOST_MATH_NAMESPACE::lgamma(1 + z, pol)); } #endif // BOOST_MATH_HAS_GPU_SUPPORT @@ -979,7 +1029,7 @@ BOOST_MATH_GPU_ENABLED T full_igamma_prefix(T a, T z, const Policy& pol) // rather than before it... // Typically though this method is used when the result is small, we should probably not overflow here... // - if((boost::math::fpclassify)(prefix) == (int)BOOST_MATH_FP_INFINITE) + if((BOOST_MATH_NAMESPACE::fpclassify)(prefix) == (int)BOOST_MATH_FP_INFINITE) return policies::raise_overflow_error("boost::math::detail::full_igamma_prefix<%1%>(%1%, %1%)", "Result of incomplete gamma function is too large to represent.", pol); // LCOV_EXCL_LINE return prefix; @@ -1024,7 +1074,7 @@ BOOST_MATH_GPU_ENABLED T regularised_gamma_prefix(T a, T z, const Policy& pol, c else if((fabs(d*d*a) <= 100) && (a > 150)) { // special case for large a and a ~ z. - prefix = a * boost::math::log1pmx(d, pol) + z * static_cast(0.5 - Lanczos::g()) / agh; + prefix = a * BOOST_MATH_NAMESPACE::log1pmx(d, pol) + z * static_cast(0.5 - Lanczos::g()) / agh; prefix = exp(prefix); } else @@ -1066,7 +1116,7 @@ BOOST_MATH_GPU_ENABLED T regularised_gamma_prefix(T a, T z, const Policy& pol, c prefix = pow(T(z / agh), a) * exp(amz); } } - prefix *= sqrt(agh / boost::math::constants::e()) / Lanczos::lanczos_sum_expG_scaled(a); + prefix *= sqrt(agh / BOOST_MATH_NAMESPACE::constants::e()) / Lanczos::lanczos_sum_expG_scaled(a); return prefix; } @@ -1083,11 +1133,19 @@ T regularised_gamma_prefix(T a, T z, const Policy& pol, const lanczos::undefined if((a < 1) && (z < 1)) { // No overflow possible since the power terms tend to unity as a,z -> 0 - return pow(z, a) * exp(-z) / boost::math::tgamma(a, pol); + return pow(z, a) * exp(-z) / BOOST_MATH_NAMESPACE::tgamma(a, pol); } else if(a > minimum_argument_for_bernoulli_recursion()) { T scaled_gamma = scaled_tgamma_no_lanczos(a, pol); + // (z / a)^a e^(a - z) = exp(a log1pmx(d)) with d = (z - a) / a, where z - a is exact. pow(z / a, a) + // instead turns the rounding of z / a into a relative error of eps a: + T d = (z - a) / a; + if (fabs(d) < 0.5) + { + T log_term = a * BOOST_MATH_NAMESPACE::log1pmx(d, pol); + return log_term > tools::log_min_value() ? T(exp(log_term) / scaled_gamma) : T(exp(log_term - log(scaled_gamma))); + } T power_term = pow(z / a, a / 2); T a_minus_z = a - z; if ((0 == power_term) || (fabs(a_minus_z) > tools::log_max_value())) @@ -1130,7 +1188,7 @@ T regularised_gamma_prefix(T a, T z, const Policy& pol, const lanczos::undefined { // We have no test case that gets here, most likely the type T // has a high precision but low exponent range: - return exp(a * log(z) - z - boost::math::lgamma(a, pol)); + return exp(a * log(z) - z - BOOST_MATH_NAMESPACE::lgamma(a, pol)); } result = power_term_1 * power_term_2 * power_term_3 / scaled_gamma; for (long i = 0; i < shift; ++i) @@ -1161,21 +1219,21 @@ BOOST_MATH_GPU_ENABLED inline T tgamma_small_upper_part(T a, T x, const Policy& typedef typename lanczos::lanczos::type evaluation_type; T result {detail::tgammap1m1_imp(static_cast(a), pol, evaluation_type())}; #else - T result { boost::math::tgamma1pm1(a, pol) }; + T result { BOOST_MATH_NAMESPACE::tgamma1pm1(a, pol) }; #endif if(pgam) *pgam = (result + 1) / a; - T p = boost::math::powm1(x, a, pol); + T p = BOOST_MATH_NAMESPACE::powm1(x, a, pol); result -= p; result /= a; detail::small_gamma2_series s(a, x); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations() - 10; + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations() - 10; p += 1; if(pderivative) *pderivative = p / (*pgam * exp(x)); T init_value = invert ? *pgam : 0; - result = -p * tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter, (init_value - result) / p); + result = -p * tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter, (init_value - result) / p); policies::check_series_iterations("boost::math::tgamma_small_upper_part<%1%>(%1%, %1%)", max_iter, pol); if(invert) result = -result; @@ -1205,7 +1263,7 @@ BOOST_MATH_GPU_ENABLED inline T finite_gamma_q(T a, T x, Policy const& pol, T* p } if(pderivative) { - *pderivative = e * pow(x, a) / boost::math::unchecked_factorial(itrunc(T(a - 1), pol)); + *pderivative = e * pow(x, a) / BOOST_MATH_NAMESPACE::unchecked_factorial(itrunc(T(a - 1), pol)); } return sum; } @@ -1222,7 +1280,7 @@ BOOST_MATH_GPU_ENABLED T finite_half_gamma_q(T a, T x, T* p_derivative, const Po #ifdef BOOST_MATH_HAS_NVRTC T e; - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { e = ::erfcf(::sqrtf(x)); } @@ -1231,7 +1289,7 @@ BOOST_MATH_GPU_ENABLED T finite_half_gamma_q(T a, T x, T* p_derivative, const Po e = ::erfc(::sqrt(x)); } #else - T e = boost::math::erfc(sqrt(x), pol); + T e = BOOST_MATH_NAMESPACE::erfc(sqrt(x), pol); #endif if((e != 0) && (a > 1)) @@ -1284,9 +1342,9 @@ BOOST_MATH_GPU_ENABLED T incomplete_tgamma_large_x(const T& a, const T& x, const { BOOST_MATH_STD_USING incomplete_tgamma_large_x_series s(a, x); - boost::math::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon(), max_iter); - boost::math::policies::check_series_iterations("boost::math::tgamma<%1%>(%1%,%1%)", max_iter, pol); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, BOOST_MATH_NAMESPACE::policies::get_epsilon(), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("boost::math::tgamma<%1%>(%1%,%1%)", max_iter, pol); return result; } @@ -1382,7 +1440,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b // series and continued fractions are slow to converge: // bool use_temme = false; - if(normalised && boost::math::numeric_limits::is_specialized && (a > 20)) + if(normalised && BOOST_MATH_NAMESPACE::numeric_limits::is_specialized && (a > 20)) { T sigma = fabs((x-a)/a); if((a > 200) && (policies::digits() <= 113)) @@ -1403,7 +1461,11 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b // Note in this zone we can't use Temme's expansion for // types longer than an 80-bit real: // it would require too many terms in the polynomials. - if(sigma < 0.4) + // + // For x < a and small a the expansion is only good to ~100 eps as sigma approaches 0.4, + // whereas the series is good to ~10 eps there: + // + if(sigma < ((x < a) && (a < 50) ? 0.3f : 0.4f)) use_temme = true; } } @@ -1441,7 +1503,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b if(!normalised) { #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { result *= ::tgammaf(a); } @@ -1450,7 +1512,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b result *= ::tgamma(a); } #else - result *= boost::math::tgamma(a, pol); + result *= BOOST_MATH_NAMESPACE::tgamma(a, pol); #endif } break; @@ -1461,7 +1523,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b if(!normalised) { #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { result *= ::tgammaf(a); } @@ -1470,7 +1532,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b result *= ::tgamma(a); } #else - result *= boost::math::tgamma(a, pol); + result *= BOOST_MATH_NAMESPACE::tgamma(a, pol); #endif } if(p_derivative && (*p_derivative == 0)) @@ -1502,7 +1564,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b if(invert) { #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { init_value = (normalised ? T(1) : ::tgammaf(a)); } @@ -1511,7 +1573,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b init_value = (normalised ? T(1) : ::tgamma(a)); } #else - init_value = (normalised ? T(1) : boost::math::tgamma(a, pol)); + init_value = (normalised ? T(1) : BOOST_MATH_NAMESPACE::tgamma(a, pol)); #endif if(normalised || (result >= 1) || (tools::max_value() * result > init_value)) @@ -1570,7 +1632,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b // typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant) + if (BOOST_MATH_NAMESPACE::is_same_v) { result = ::powf(x, a) / ::tgammaf(a + 1); } @@ -1606,7 +1668,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b result = ::pow(x, a) / ::tgamma(a + 1); } #else - result = pow(x, a) / boost::math::tgamma(a + 1, pol); + result = pow(x, a) / BOOST_MATH_NAMESPACE::tgamma(a + 1, pol); #endif #ifndef BOOST_MATH_NO_EXCEPTIONS } @@ -1641,7 +1703,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b { #ifdef BOOST_MATH_HAS_NVRTC T gam; - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { gam = normalised ? T(1) : ::tgammaf(a); } @@ -1650,7 +1712,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b gam = normalised ? T(1) : ::tgamma(a); } #else - T gam = normalised ? T(1) : boost::math::tgamma(a, pol); + T gam = normalised ? T(1) : BOOST_MATH_NAMESPACE::tgamma(a, pol); #endif result = gam - result; } @@ -1682,7 +1744,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp(T a, T x, bool normalised, bool in BOOST_MATH_STD_USING - T result = 0; // Just to avoid warning C4701: potentially uninitialized local variable 'result' used + T result = T(0); // Just to avoid warning C4701: potentially uninitialized local variable 'result' used if(x > 0 && a >= max_factorial::value && !normalised) { @@ -1714,7 +1776,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp(T a, T x, bool normalised, bool in // Not currently used for non-normalized igamma: //if(p_derivative) // *p_derivative = exp(result); - T init_value = 0; + T init_value = T(0); result += log(detail::lower_gamma_series(a, x, pol, init_value) / a); } else @@ -1726,7 +1788,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp(T a, T x, bool normalised, bool in { // Try http://functions.wolfram.com/06.06.06.0039.01 result = 1 + 1 / (12 * a) + 1 / (288 * a * a); - result = log(result) - a + (a - 0.5f) * log(a) + log(boost::math::constants::root_two_pi()); + result = log(result) - a + (a - 0.5f) * log(a) + log(BOOST_MATH_NAMESPACE::constants::root_two_pi()); BOOST_MATH_ASSERT(p_derivative == nullptr); // Not currently used for non-normalized igamma: //if(p_derivative) @@ -1742,14 +1804,14 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp(T a, T x, bool normalised, bool in // Not currently used for non-normalized igamma: //if(p_derivative) // *p_derivative = exp(result); - T init_value = 0; + T init_value = T(0); result += log(detail::lower_gamma_series(a, x, pol, init_value) / a); } } else { #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { result = ::logf(result) + ::lgammaf(a); } @@ -1758,7 +1820,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp(T a, T x, bool normalised, bool in result = ::log(result) + ::lgamma(a); } #else - result = log(result) + boost::math::lgamma(a, pol); + result = log(result) + BOOST_MATH_NAMESPACE::lgamma(a, pol); #endif } } @@ -1775,7 +1837,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp(T a, T x, bool normalised, bool in template BOOST_MATH_GPU_ENABLED T lgamma_incomplete_imp(T a, T x, const Policy& pol) { - using namespace boost::math; // temporary until we're in the right namespace + using namespace BOOST_MATH_NAMESPACE; // temporary until we're in the right namespace BOOST_MATH_STD_USING_CORE @@ -1785,6 +1847,9 @@ BOOST_MATH_GPU_ENABLED T lgamma_incomplete_imp(T a, T x, const Policy& pol) return policies::raise_domain_error(function, "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol); if(x < 0) return policies::raise_domain_error(function, "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol); + // The log of an exact zero; the overflow policy decides, as for ligamma: + if((BOOST_MATH_NAMESPACE::isinf)(x)) + return -policies::raise_overflow_error(function, nullptr, pol); if (((x > 1000) || (x > tools::log_max_value() - 10)) && (a + 50 < x)) { @@ -1812,11 +1877,36 @@ BOOST_MATH_GPU_ENABLED T lgamma_incomplete_imp(T a, T x, const Policy& pol) return log(gamma_q(a, x, pol)); } +// +// log(x^a e^-x / tgamma(a)), the log of regularised_gamma_prefix, for a >= 1. With agh = a + g - 1/2 +// and d = (x - agh) / agh, a log(x) - x - lgamma(a) is exactly +// a log1pmx(d) + x (1/2 - g) / agh + log(agh / e) / 2 - log(lanczos_sum_expG_scaled(a)), +// which has none of the cancellation of the direct form when a and x are large. +// +template +BOOST_MATH_GPU_ENABLED T log_regularised_gamma_prefix(T a, T x, const Policy& pol, const Lanczos&) +{ + BOOST_MATH_STD_USING + if(a < 1) + return a * log(x) - x - BOOST_MATH_NAMESPACE::lgamma(a, pol); + T agh = a + static_cast(Lanczos::g()) - T(0.5); + T d = ((x - a) - static_cast(Lanczos::g()) + T(0.5)) / agh; + return a * BOOST_MATH_NAMESPACE::log1pmx(d, pol) + x * static_cast(0.5 - Lanczos::g()) / agh + + (log(agh) - 1) / 2 - log(Lanczos::lanczos_sum_expG_scaled(a)); +} + +template +BOOST_MATH_GPU_ENABLED T log_regularised_gamma_prefix(T a, T x, const Policy& pol, const lanczos::undefined_lanczos&) +{ + BOOST_MATH_STD_USING + return a * log(x) - x - BOOST_MATH_NAMESPACE::lgamma(a, pol); +} + // Calculate log of incomplete gamma function template BOOST_MATH_GPU_ENABLED T lgamma_incomplete_lower_imp(T a, T x, const Policy& pol) { - using namespace boost::math; // temporary until we're in the right namespace + using namespace BOOST_MATH_NAMESPACE; // temporary until we're in the right namespace BOOST_MATH_STD_USING_CORE @@ -1826,6 +1916,9 @@ BOOST_MATH_GPU_ENABLED T lgamma_incomplete_lower_imp(T a, T x, const Policy& pol return policies::raise_domain_error(function, "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol); if(x < 0) return policies::raise_domain_error(function, "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol); + // The log of an exact zero; the overflow policy decides, as for ligamma: + if(x == 0) + return -policies::raise_overflow_error(function, nullptr, pol); // Taken from conditions on Line 1709. There are also // conditions on Line 1368, but didn't implement that one here. @@ -1848,10 +1941,112 @@ BOOST_MATH_GPU_ENABLED T lgamma_incomplete_lower_imp(T a, T x, const Policy& pol need_p = true; if (need_p) - return log(gamma_p(a, x, pol)); + { + // Method 2 in logs, P = prefix * series / a. It works where P underflows (#1564), and for + // large a it is more accurate than log(P), since log P is far better conditioned than P + // there. For smaller a, or without a Lanczos approximation for the prefix, log(P) is the + // more accurate of the two. + typedef typename lanczos::lanczos::type lanczos_type; + constexpr bool accurate_log_prefix = !BOOST_MATH_NAMESPACE::is_same::value; + if(accurate_log_prefix && (x < a) && (a > 1000)) + return log_regularised_gamma_prefix(a, x, pol, lanczos_type()) + log(detail::lower_gamma_series(a, x, pol) / a); + typedef typename policies::normalise >::type quiet_policy; + T p = gamma_p(a, x, quiet_policy()); + if(p >= tools::min_value()) + return log(p); + return log_regularised_gamma_prefix(a, x, pol, lanczos_type()) + log(detail::lower_gamma_series(a, x, pol) / a); + } return log1p(-gamma_q(a, x, pol), pol); } +// +// Logarithm of the non-normalised upper (upper == true) or lower incomplete gamma function. +// +// Where the non-normalised value is representable it is the logarithm of that. Otherwise this +// uses the regularised value, the target T = Q (upper) or P (lower), and its complement C: +// +// T >= 1/2: lgamma(a) + log1p(-C) +// T representable: lgamma(a) + log(T) +// T underflows: a log(x) - x + log(continued fraction), upper, x > a +// a log(x) - x + log(series / a), lower, x < a +// +// The last two are the methods that gamma_incomplete_imp uses in logs for large a, here applied +// only far out in the tail, where they converge quickly. As in Abergel and Moisan's G-function +// (ACM TOMS 46(1), Algorithm 1006), the prefix x^a e^-x is never formed. +// +template +BOOST_MATH_GPU_ENABLED T ligamma_imp(T a, T x, const Policy& pol, bool upper) +{ + BOOST_MATH_STD_USING + const char* function = upper ? "boost::math::ligamma<%1%>(%1%, %1%)" : "boost::math::ligamma_lower<%1%>(%1%, %1%)"; + + // These checks also reject NaN arguments: + if(!(BOOST_MATH_NAMESPACE::isfinite)(a)) + return policies::raise_domain_error(function, "Argument a to the incomplete gamma function must be finite (got a=%1%).", a, pol); + if(a <= 0) + return policies::raise_domain_error(function, "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol); + if(!(x >= 0)) + return policies::raise_domain_error(function, "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol); + + // At the ends of the range, the target is either the complete gamma function or zero: + bool target_is_zero = upper ? (BOOST_MATH_NAMESPACE::isinf)(x) : (x == 0); + if(target_is_zero) + { + // -infinity is exact here; as for every other exact infinity, the overflow policy decides: + return -policies::raise_overflow_error(function, nullptr, pol); + } + if(upper ? (x == 0) : (BOOST_MATH_NAMESPACE::isinf)(x)) + return BOOST_MATH_NAMESPACE::lgamma(a, pol); + + // Under- and overflow are ours to handle, so stop the evaluations below from reporting them: + typedef typename policies::normalise, policies::overflow_error >::type quiet_policy; + + if(upper && (a < 2) && (x < 1.1f)) + { + // + // tgamma_small_upper_part forms tgamma(a, x) as R - x^a S, with R = (tgamma1pm1(a) - powm1(x, a)) / a, + // without the cancellation in tgamma(a) - tgamma_lower(a, x) that the general method has here. + // Subtracting 1 from R instead gives tgamma(a, x) - 1 directly, so that log1p is accurate where + // tgamma(a, x) is near 1; away from 1, the log of the value itself is better. For a >= 1 and + // small x, tgamma1pm1(a) - a and powm1(x, a) ~ -1 cancel, and the methods below do better: + // + T pm1 = BOOST_MATH_NAMESPACE::powm1(x, a, pol); + if((a < 1) || (pm1 > -0.5f)) + { + T result = ((BOOST_MATH_NAMESPACE::tgamma1pm1(a, pol) - a) - pm1) / a; + detail::small_gamma2_series s(a, x); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); + result -= (pm1 + 1) * tools::sum_series(s, policies::get_epsilon(), max_iter, T(0)); + policies::check_series_iterations(function, max_iter, pol); + if(fabs(result) <= 0.5f) + return BOOST_MATH_NAMESPACE::log1p(result, pol); + return log(tgamma_small_upper_part(a, x, pol)); + } + } + if(a < max_factorial::value) + { + // The non-normalised value cannot overflow, as it is at most tgamma(a): + T value = gamma_incomplete_imp(a, x, false, upper, quiet_policy(), static_cast(nullptr)); + // Near 1 the log would turn the value's relative error into a far larger one in the result, + // so there the regularised forms below, which never form the value, are used instead: + if((value >= tools::min_value()) && ((value < 0.5f) || (value > 2))) + return log(value); + } + T target = gamma_incomplete_imp(a, x, true, upper, quiet_policy(), static_cast(nullptr)); + if(target > 0.5f) + return BOOST_MATH_NAMESPACE::lgamma(a, pol) + BOOST_MATH_NAMESPACE::log1p(-gamma_incomplete_imp(a, x, true, !upper, quiet_policy(), static_cast(nullptr)), pol); + if(target >= tools::min_value()) + return BOOST_MATH_NAMESPACE::lgamma(a, pol) + log(target); + + // The target underflows, so x is far out in its tail: + T result = a * log(x) - x; + if(upper) + result += log(upper_gamma_fraction(a, x, policies::get_epsilon())); + else + result += log(detail::lower_gamma_series(a, x, pol, T(0)) / a); + return result; +} + // // Ratios of two gamma functions: // @@ -1867,7 +2062,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_delta_ratio_imp_lanczos_final(T z, T delta, cons // Given delta < z * eps // and zgh > z // Then this must follow: - BOOST_MATH_ASSERT(fabs(delta / zgh) < boost::math::tools::epsilon()); + BOOST_MATH_ASSERT(fabs(delta / zgh) < BOOST_MATH_NAMESPACE::tools::epsilon()); // We have: // result = exp((constants::half() - z) * boost::math::log1p(delta / zgh, pol)); // 0.5 - z == -z @@ -1879,7 +2074,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_delta_ratio_imp_lanczos_final(T z, T delta, cons { if(fabs(delta) < 10) { - result = exp((constants::half() - z) * boost::math::log1p(delta / zgh, pol)); + result = exp((constants::half() - z) * BOOST_MATH_NAMESPACE::log1p(delta / zgh, pol)); } else { @@ -1908,17 +2103,17 @@ BOOST_MATH_GPU_ENABLED T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Poli // G(z) / G(L) = 1 / (z * G(L)) ; z < eps, L = z + delta = delta // z * G(L) = z * G(lim) * (G(L)/G(lim)) ; lim = largest factorial // - if(boost::math::max_factorial::value < delta) + if(BOOST_MATH_NAMESPACE::max_factorial::value < delta) { - T ratio = tgamma_delta_ratio_imp_lanczos_final(T(delta), T(boost::math::max_factorial::value - delta), pol, l); + T ratio = tgamma_delta_ratio_imp_lanczos_final(T(delta), T(BOOST_MATH_NAMESPACE::max_factorial::value - delta), pol, l); ratio *= z; - ratio *= boost::math::unchecked_factorial(boost::math::max_factorial::value - 1); + ratio *= BOOST_MATH_NAMESPACE::unchecked_factorial(BOOST_MATH_NAMESPACE::max_factorial::value - 1); return 1 / ratio; } else { #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { return 1 / (z * ::tgammaf(z + delta)); } @@ -1927,7 +2122,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Poli return 1 / (z * ::tgamma(z + delta)); } #else - return 1 / (z * boost::math::tgamma(z + delta, pol)); + return 1 / (z * BOOST_MATH_NAMESPACE::tgamma(z + delta, pol)); #endif } } @@ -1969,7 +2164,7 @@ T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const lanczos: T scaled_tgamma_num = scaled_tgamma_no_lanczos(z, pol); T scaled_tgamma_denom = scaled_tgamma_no_lanczos(T(z + delta), pol); T result = scaled_tgamma_num / scaled_tgamma_denom; - result *= exp(z * boost::math::log1p(-delta / (z + delta), pol)) * pow(T((delta + z) / constants::e()), -delta); + result *= exp(z * BOOST_MATH_NAMESPACE::log1p(-delta / (z + delta), pol)) * pow(T((delta + z) / constants::e()), -delta); return result; } // @@ -2007,7 +2202,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_delta_ratio_imp(T z, T delta, const Policy& pol) { // This isn't very sophisticated, or accurate, but it does work: #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { return ::tgammaf(z) / ::tgammaf(z + delta); } @@ -2016,7 +2211,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_delta_ratio_imp(T z, T delta, const Policy& pol) return ::tgamma(z) / ::tgamma(z + delta); } #else - return boost::math::tgamma(z, pol) / boost::math::tgamma(z + delta, pol); + return BOOST_MATH_NAMESPACE::tgamma(z, pol) / BOOST_MATH_NAMESPACE::tgamma(z + delta, pol); #endif } @@ -2072,9 +2267,9 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) { BOOST_MATH_STD_USING - if((x <= 0) || (boost::math::isinf)(x)) + if((x <= 0) || (BOOST_MATH_NAMESPACE::isinf)(x)) return policies::raise_domain_error("boost::math::tgamma_ratio<%1%>(%1%, %1%)", "Gamma function ratios only implemented for positive arguments (got a=%1%).", x, pol); - if((y <= 0) || (boost::math::isinf)(y)) + if((y <= 0) || (BOOST_MATH_NAMESPACE::isinf)(y)) return policies::raise_domain_error("boost::math::tgamma_ratio<%1%>(%1%, %1%)", "Gamma function ratios only implemented for positive arguments (got b=%1%).", y, pol); // We don't need to worry about the denorm case on device @@ -2092,7 +2287,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) { // Rather than subtracting values, lets just call the gamma functions directly: #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { return ::tgammaf(x) / ::tgammaf(y); } @@ -2101,7 +2296,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) return ::tgamma(x) / ::tgamma(y); } #else - return boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol); + return BOOST_MATH_NAMESPACE::tgamma(x, pol) / BOOST_MATH_NAMESPACE::tgamma(y, pol); #endif } T prefix = 1; @@ -2120,7 +2315,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) } #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { return prefix * ::tgammaf(x) / ::tgammaf(y); } @@ -2129,14 +2324,14 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) return prefix * ::tgamma(x) / ::tgamma(y); } #else - return prefix * boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol); + return prefix * BOOST_MATH_NAMESPACE::tgamma(x, pol) / BOOST_MATH_NAMESPACE::tgamma(y, pol); #endif } // // result is almost certainly going to underflow to zero, try logs just in case: // #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { return ::expf(::lgammaf(x) - ::lgammaf(y)); } @@ -2145,7 +2340,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) return ::exp(::lgamma(x) - ::lgamma(y)); } #else - return exp(boost::math::lgamma(x, pol) - boost::math::lgamma(y, pol)); + return exp(BOOST_MATH_NAMESPACE::lgamma(x, pol) - BOOST_MATH_NAMESPACE::lgamma(y, pol)); #endif } if(y < 1) @@ -2163,7 +2358,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) } #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { return prefix * ::tgammaf(x) / ::tgammaf(y); } @@ -2172,13 +2367,13 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) return prefix * ::tgamma(x) / ::tgamma(y); } #else - return prefix * boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol); + return prefix * BOOST_MATH_NAMESPACE::tgamma(x, pol) / BOOST_MATH_NAMESPACE::tgamma(y, pol); #endif } // // Result will almost certainly overflow, try logs just in case: // - BOOST_MATH_IF_CONSTEXPR(boost::math::is_same::value || boost::math::is_same::value) + BOOST_MATH_IF_CONSTEXPR(BOOST_MATH_NAMESPACE::is_same::value || BOOST_MATH_NAMESPACE::is_same::value) { // straight to the scene of the accident, since the result is larger than max_factorial: return policies::raise_overflow_error("tgamma_ratio", nullptr, pol); @@ -2186,7 +2381,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) else { #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { prefix = ::lgammaf(x) - ::lgammaf(y); } @@ -2195,9 +2390,9 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) prefix = ::lgamma(x) - ::lgamma(y); } #else - prefix = boost::math::lgamma(x, pol) - boost::math::lgamma(y, pol); + prefix = BOOST_MATH_NAMESPACE::lgamma(x, pol) - BOOST_MATH_NAMESPACE::lgamma(y, pol); #endif - if (prefix > boost::math::tools::log_max_value()) + if (prefix > BOOST_MATH_NAMESPACE::tools::log_max_value()) return policies::raise_overflow_error("tgamma_ratio", nullptr, pol); // // This is unreachable, unless max_factorial is small compared to the exponent @@ -2212,7 +2407,7 @@ BOOST_MATH_GPU_ENABLED T tgamma_ratio_imp(T x, T y, const Policy& pol) #ifdef BOOST_MATH_HAS_NVRTC return detail::tgamma_delta_ratio_imp(x, y - x, pol); #else - return boost::math::tgamma_delta_ratio(x, y - x, pol); + return BOOST_MATH_NAMESPACE::tgamma_delta_ratio(x, y - x, pol); #endif } @@ -2253,7 +2448,7 @@ BOOST_MATH_GPU_ENABLED T gamma_p_derivative_imp(T a, T x, const Policy& pol) { // Underflow in calculation, use logs instead: #ifdef BOOST_MATH_HAS_NVRTC - if (boost::math::is_same_v) + if (BOOST_MATH_NAMESPACE::is_same_v) { f1 = a * ::logf(x) - x - ::lgammaf(a) - ::logf(x); } @@ -2274,7 +2469,7 @@ BOOST_MATH_GPU_ENABLED T gamma_p_derivative_imp(T a, T x, const Policy& pol) template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type - tgamma(T z, const Policy& /* pol */, const boost::math::true_type) + tgamma(T z, const Policy& /* pol */, const BOOST_MATH_NAMESPACE::true_type) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -2291,7 +2486,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t - tgamma(T1 a, T2 z, const Policy&, const boost::math::false_type) + tgamma(T1 a, T2 z, const Policy&, const BOOST_MATH_NAMESPACE::false_type) { BOOST_FPU_EXCEPTION_GUARD typedef tools::promote_args_t result_type; @@ -2312,7 +2507,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t - tgamma(T1 a, T2 z, const boost::math::false_type& tag) + tgamma(T1 a, T2 z, const BOOST_MATH_NAMESPACE::false_type& tag) { return tgamma(a, z, policies::policy<>(), tag); } @@ -2320,7 +2515,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type lgamma(T z, int* sign, const Policy&) { @@ -2338,28 +2533,28 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::lgamma_imp(static_cast(z), forwarding_policy(), evaluation_type(), sign), "boost::math::lgamma<%1%>(%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type lgamma(T z, int* sign) { return lgamma(z, sign, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type lgamma(T x, const Policy& pol) { - return ::boost::math::lgamma(x, nullptr, pol); + return ::BOOST_MATH_NAMESPACE::lgamma(x, nullptr, pol); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type lgamma(T x) { - return ::boost::math::lgamma(x, nullptr, policies::policy<>()); + return ::BOOST_MATH_NAMESPACE::lgamma(x, nullptr, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type tgamma1pm1(T z, const Policy& /* pol */) { @@ -2374,10 +2569,10 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; - return policies::checked_narrowing_cast::type, forwarding_policy>(detail::tgammap1m1_imp(static_cast(z), forwarding_policy(), evaluation_type()), "boost::math::tgamma1pm1<%!%>(%1%)"); + return policies::checked_narrowing_cast::type, forwarding_policy>(detail::tgammap1m1_imp(static_cast(z), forwarding_policy(), evaluation_type()), "boost::math::tgamma1pm1<%!%>(%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type tgamma1pm1(T z) { @@ -2387,7 +2582,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type // // Full upper incomplete gamma: // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t tgamma(T1 a, T2 z) { @@ -2399,14 +2594,14 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t using result_type = tools::promote_args_t; return static_cast(detail::tgamma(a, z, maybe_policy())); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t tgamma(T1 a, T2 z, const Policy& pol) { using result_type = tools::promote_args_t; - return static_cast(detail::tgamma(a, z, pol, boost::math::false_type())); + return static_cast(detail::tgamma(a, z, pol, BOOST_MATH_NAMESPACE::false_type())); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type tgamma(T z) { @@ -2415,7 +2610,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type // // Full lower incomplete gamma: // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t tgamma_lower(T1 a, T2 z, const Policy&) { @@ -2435,7 +2630,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t static_cast(z), false, false, forwarding_policy(), static_cast(nullptr)), "tgamma_lower<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t tgamma_lower(T1 a, T2 z) { @@ -2444,7 +2639,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t // // Regularised upper incomplete gamma: // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t gamma_q(T1 a, T2 z, const Policy& /* pol */) { @@ -2464,14 +2659,14 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t static_cast(z), true, true, forwarding_policy(), static_cast(nullptr)), "gamma_q<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t gamma_q(T1 a, T2 z) { return gamma_q(a, z, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t lgamma_q(T1 a, T2 z, const Policy& /* pol */) { typedef tools::promote_args_t result_type; @@ -2488,13 +2683,13 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t lgamma_q(T1 a, T2 z, static_cast(z), forwarding_policy()), "lgamma_q<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t lgamma_q(T1 a, T2 z) { return lgamma_q(a, z, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t lgamma_p(T1 a, T2 z, const Policy& /* pol */) { typedef tools::promote_args_t result_type; @@ -2511,15 +2706,61 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t lgamma_p(T1 a, T2 z, static_cast(z), forwarding_policy()), "lgamma_p<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t lgamma_p(T1 a, T2 z) { return lgamma_p(a, z, policies::policy<>()); } + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline tools::promote_args_t ligamma(T1 a, T2 z, const Policy&) +{ + BOOST_FPU_EXCEPTION_GUARD + typedef tools::promote_args_t result_type; + typedef typename policies::evaluation::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + value_type result = detail::ligamma_imp(static_cast(a), static_cast(z), forwarding_policy(), true); + return policies::checked_narrowing_cast(result, "boost::math::ligamma<%1%>(%1%, %1%)"); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline tools::promote_args_t ligamma(T1 a, T2 z) +{ + return ligamma(a, z, policies::policy<>()); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline tools::promote_args_t ligamma_lower(T1 a, T2 z, const Policy&) +{ + BOOST_FPU_EXCEPTION_GUARD + typedef tools::promote_args_t result_type; + typedef typename policies::evaluation::type value_type; + typedef typename policies::normalise< + Policy, + policies::promote_float, + policies::promote_double, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + value_type result = detail::ligamma_imp(static_cast(a), static_cast(z), forwarding_policy(), false); + return policies::checked_narrowing_cast(result, "boost::math::ligamma_lower<%1%>(%1%, %1%)"); +} + +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline tools::promote_args_t ligamma_lower(T1 a, T2 z) +{ + return ligamma_lower(a, z, policies::policy<>()); +} // // Regularised lower incomplete gamma: // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t gamma_p(T1 a, T2 z, const Policy&) { @@ -2539,7 +2780,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t static_cast(z), true, false, forwarding_policy(), static_cast(nullptr)), "gamma_p<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t gamma_p(T1 a, T2 z) { @@ -2547,7 +2788,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t } // ratios of gamma functions: -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta, const Policy& /* pol */) { @@ -2563,13 +2804,13 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t return policies::checked_narrowing_cast(detail::tgamma_delta_ratio_imp(static_cast(z), static_cast(delta), forwarding_policy()), "boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta) { return tgamma_delta_ratio(z, delta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t tgamma_ratio(T1 a, T2 b, const Policy&) { @@ -2584,14 +2825,14 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t return policies::checked_narrowing_cast(detail::tgamma_ratio_imp(static_cast(a), static_cast(b), forwarding_policy()), "boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t tgamma_ratio(T1 a, T2 b) { return tgamma_ratio(a, b, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t gamma_p_derivative(T1 a, T2 x, const Policy&) { @@ -2607,15 +2848,14 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t return policies::checked_narrowing_cast(detail::gamma_p_derivative_imp(static_cast(a), static_cast(x), forwarding_policy()), "boost::math::gamma_p_derivative<%1%>(%1%, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t gamma_p_derivative(T1 a, T2 x) { return gamma_p_derivative(a, x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER # pragma warning(pop) diff --git a/include/boost/math/special_functions/gegenbauer.hpp b/include/boost/math/special_functions/gegenbauer.hpp index 70324cf656..8d4a07e105 100644 --- a/include/boost/math/special_functions/gegenbauer.hpp +++ b/include/boost/math/special_functions/gegenbauer.hpp @@ -12,20 +12,22 @@ #include #ifndef BOOST_MATH_NO_EXCEPTIONS +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED Real gegenbauer(unsigned n, Real lambda, Real x) { - static_assert(!boost::math::is_integral::value, "Gegenbauer polynomials required floating point arguments."); + static_assert(!BOOST_MATH_NAMESPACE::is_integral::value, "Gegenbauer polynomials required floating point arguments."); if (lambda <= -1/Real(2)) { #ifndef BOOST_MATH_NO_EXCEPTIONS throw std::domain_error("lambda > -1/2 is required."); #else - return boost::math::numeric_limits::quiet_NaN(); + return BOOST_MATH_NAMESPACE::numeric_limits::quiet_NaN(); #endif } // The only reason to do this is because of some instability that could be present for x < 0 that is not present for x > 0. @@ -46,7 +48,7 @@ BOOST_MATH_GPU_ENABLED Real gegenbauer(unsigned n, Real lambda, Real x) Real yk = y1; Real k = 2; - Real k_max = n*(1+boost::math::numeric_limits::epsilon()); + Real k_max = n*(1+BOOST_MATH_NAMESPACE::numeric_limits::epsilon()); Real gamma = 2*(lambda - 1); while(k < k_max) { @@ -59,7 +61,7 @@ BOOST_MATH_GPU_ENABLED Real gegenbauer(unsigned n, Real lambda, Real x) } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED Real gegenbauer_derivative(unsigned n, Real lambda, Real x, unsigned k) { if (k > n) { @@ -74,11 +76,11 @@ BOOST_MATH_GPU_ENABLED Real gegenbauer_derivative(unsigned n, Real lambda, Real return scale*gegen; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED Real gegenbauer_prime(unsigned n, Real lambda, Real x) { return gegenbauer_derivative(n, lambda, x, 1); } -}} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/hankel.hpp b/include/boost/math/special_functions/hankel.hpp index 730c7afa03..733b1297e8 100644 --- a/include/boost/math/special_functions/hankel.hpp +++ b/include/boost/math/special_functions/hankel.hpp @@ -16,12 +16,12 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template -BOOST_MATH_GPU_ENABLED boost::math::complex hankel_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol, int sign) +BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex hankel_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol, int sign) { BOOST_MATH_STD_USING constexpr auto function = "boost::math::cyl_hankel_1<%1%>(%1%,%1%)"; @@ -31,8 +31,8 @@ BOOST_MATH_GPU_ENABLED boost::math::complex hankel_imp(T v, T x, const bessel bool isint_v = floor(v) == v; T j, y; bessel_jy(v, -x, &j, &y, need_j | need_y, pol); - boost::math::complex cx(x), cv(v); - boost::math::complex j_result, y_result; + BOOST_MATH_NAMESPACE::complex cx(x), cv(v); + BOOST_MATH_NAMESPACE::complex j_result, y_result; if(isint_v) { int s = (iround(v) & 1) ? -1 : 1; @@ -43,12 +43,12 @@ BOOST_MATH_GPU_ENABLED boost::math::complex hankel_imp(T v, T x, const bessel { j_result = pow(cx, v) * pow(-cx, -v) * j; T p1 = pow(-x, v); - boost::math::complex p2 = pow(cx, v); + BOOST_MATH_NAMESPACE::complex p2 = pow(cx, v); y_result = p1 * y / p2 + (p2 / p1 - p1 / p2) * j / tan(constants::pi() * v); } // multiply y_result by i: - y_result = boost::math::complex(-sign * y_result.imag(), sign * y_result.real()); + y_result = BOOST_MATH_NAMESPACE::complex(-sign * y_result.imag(), sign * y_result.real()); return j_result + y_result; } @@ -57,25 +57,25 @@ BOOST_MATH_GPU_ENABLED boost::math::complex hankel_imp(T v, T x, const bessel if(v == 0) { // J is 1, Y is -INF - return boost::math::complex(1, sign * -policies::raise_overflow_error(function, nullptr, pol)); + return BOOST_MATH_NAMESPACE::complex(1, sign * -policies::raise_overflow_error(function, nullptr, pol)); } else { // At least one of J and Y is complex infinity: - return boost::math::complex(policies::raise_overflow_error(function, nullptr, pol), sign * policies::raise_overflow_error(function, nullptr, pol)); + return BOOST_MATH_NAMESPACE::complex(policies::raise_overflow_error(function, nullptr, pol), sign * policies::raise_overflow_error(function, nullptr, pol)); } } T j, y; bessel_jy(v, x, &j, &y, need_j | need_y, pol); - return boost::math::complex(j, sign * y); + return BOOST_MATH_NAMESPACE::complex(j, sign * y); } template -BOOST_MATH_GPU_ENABLED boost::math::complex hankel_imp(int v, T x, const bessel_int_tag&, const Policy& pol, int sign); +BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex hankel_imp(int v, T x, const bessel_int_tag&, const Policy& pol, int sign); template -BOOST_MATH_GPU_ENABLED inline boost::math::complex hankel_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol, int sign) +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex hankel_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol, int sign) { BOOST_MATH_STD_USING // ADL of std names. int ival = detail::iconv(v, pol); @@ -87,57 +87,57 @@ BOOST_MATH_GPU_ENABLED inline boost::math::complex hankel_imp(T v, T x, const } template -BOOST_MATH_GPU_ENABLED inline boost::math::complex hankel_imp(int v, T x, const bessel_int_tag&, const Policy& pol, int sign) +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex hankel_imp(int v, T x, const bessel_int_tag&, const Policy& pol, int sign) { BOOST_MATH_STD_USING if((abs(v) < 200) && (x > 0)) - return boost::math::complex(bessel_jn(v, x, pol), sign * bessel_yn(v, x, pol)); + return BOOST_MATH_NAMESPACE::complex(bessel_jn(v, x, pol), sign * bessel_yn(v, x, pol)); return hankel_imp(static_cast(v), x, bessel_no_int_tag(), pol, sign); } template -BOOST_MATH_GPU_ENABLED inline boost::math::complex sph_hankel_imp(T v, T x, const Policy& pol, int sign) +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex sph_hankel_imp(T v, T x, const Policy& pol, int sign) { BOOST_MATH_STD_USING - return constants::root_half_pi() * hankel_imp(v + 0.5f, x, bessel_no_int_tag(), pol, sign) / sqrt(boost::math::complex(x)); + return constants::root_half_pi() * hankel_imp(v + 0.5f, x, bessel_no_int_tag(), pol, sign) / sqrt(BOOST_MATH_NAMESPACE::complex(x)); } } // namespace detail -template -BOOST_MATH_GPU_ENABLED inline boost::math::complex::result_type> cyl_hankel_1(T1 v, T2 x, const Policy& pol) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex::result_type> cyl_hankel_1(T1 v, T2 x, const Policy& pol) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; typedef typename detail::bessel_traits::optimisation_tag tag_type; typedef typename policies::evaluation::type value_type; - return policies::checked_narrowing_cast, Policy>(detail::hankel_imp(v, static_cast(x), tag_type(), pol, 1), "boost::math::cyl_hankel_1<%1%>(%1%,%1%)"); + return policies::checked_narrowing_cast, Policy>(detail::hankel_imp(v, static_cast(x), tag_type(), pol, 1), "boost::math::cyl_hankel_1<%1%>(%1%,%1%)"); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::complex >::result_type> cyl_hankel_1(T1 v, T2 x) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex >::result_type> cyl_hankel_1(T1 v, T2 x) { return cyl_hankel_1(v, x, policies::policy<>()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::complex::result_type> cyl_hankel_2(T1 v, T2 x, const Policy& pol) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex::result_type> cyl_hankel_2(T1 v, T2 x, const Policy& pol) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; typedef typename detail::bessel_traits::optimisation_tag tag_type; typedef typename policies::evaluation::type value_type; - return policies::checked_narrowing_cast, Policy>(detail::hankel_imp(v, static_cast(x), tag_type(), pol, -1), "boost::math::cyl_hankel_1<%1%>(%1%,%1%)"); + return policies::checked_narrowing_cast, Policy>(detail::hankel_imp(v, static_cast(x), tag_type(), pol, -1), "boost::math::cyl_hankel_1<%1%>(%1%,%1%)"); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::complex >::result_type> cyl_hankel_2(T1 v, T2 x) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex >::result_type> cyl_hankel_2(T1 v, T2 x) { return cyl_hankel_2(v, x, policies::policy<>()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::complex::result_type> sph_hankel_1(T1 v, T2 x, const Policy&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex::result_type> sph_hankel_1(T1 v, T2 x, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; @@ -149,17 +149,17 @@ BOOST_MATH_GPU_ENABLED inline boost::math::complex, policies::assert_undefined<> >::type forwarding_policy; - return policies::checked_narrowing_cast, Policy>(detail::sph_hankel_imp(static_cast(v), static_cast(x), forwarding_policy(), 1), "boost::math::sph_hankel_1<%1%>(%1%,%1%)"); + return policies::checked_narrowing_cast, Policy>(detail::sph_hankel_imp(static_cast(v), static_cast(x), forwarding_policy(), 1), "boost::math::sph_hankel_1<%1%>(%1%,%1%)"); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::complex >::result_type> sph_hankel_1(T1 v, T2 x) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex >::result_type> sph_hankel_1(T1 v, T2 x) { return sph_hankel_1(v, x, policies::policy<>()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::complex::result_type> sph_hankel_2(T1 v, T2 x, const Policy&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex::result_type> sph_hankel_2(T1 v, T2 x, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; @@ -171,16 +171,16 @@ BOOST_MATH_GPU_ENABLED inline boost::math::complex, policies::assert_undefined<> >::type forwarding_policy; - return policies::checked_narrowing_cast, Policy>(detail::sph_hankel_imp(static_cast(v), static_cast(x), forwarding_policy(), -1), "boost::math::sph_hankel_1<%1%>(%1%,%1%)"); + return policies::checked_narrowing_cast, Policy>(detail::sph_hankel_imp(static_cast(v), static_cast(x), forwarding_policy(), -1), "boost::math::sph_hankel_1<%1%>(%1%,%1%)"); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::complex >::result_type> sph_hankel_2(T1 v, T2 x) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex >::result_type> sph_hankel_2(T1 v, T2 x) { return sph_hankel_2(v, x, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HANKEL_HPP diff --git a/include/boost/math/special_functions/hermite.hpp b/include/boost/math/special_functions/hermite.hpp index 3d77fc03e3..2e80904cd7 100644 --- a/include/boost/math/special_functions/hermite.hpp +++ b/include/boost/math/special_functions/hermite.hpp @@ -17,11 +17,10 @@ #include #include -namespace boost{ -namespace math{ +BOOST_MATH_NAMESPACE_BEGIN // Recurrence relation for Hermite polynomials: -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type hermite_next(unsigned n, T1 x, T2 Hn, T3 Hnm1) { @@ -54,7 +53,7 @@ BOOST_MATH_GPU_ENABLED T hermite_imp(unsigned n, T x) } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type hermite(unsigned n, T x, const Policy&) { @@ -63,15 +62,14 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::hermite_imp(n, static_cast(x)), "boost::math::hermite<%1%>(unsigned, %1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type hermite(unsigned n, T x) { - return boost::math::hermite(n, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::hermite(n, x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_HERMITE_HPP diff --git a/include/boost/math/special_functions/heuman_lambda.hpp b/include/boost/math/special_functions/heuman_lambda.hpp index 05002725f2..261a38672e 100644 --- a/include/boost/math/special_functions/heuman_lambda.hpp +++ b/include/boost/math/special_functions/heuman_lambda.hpp @@ -24,7 +24,7 @@ // Elliptic integral the Jacobi Zeta function. -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -33,8 +33,8 @@ template BOOST_MATH_GPU_ENABLED T heuman_lambda_imp(T phi, T k, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; constexpr auto function = "boost::math::heuman_lambda<%1%>(%1%, %1%)"; @@ -44,20 +44,22 @@ BOOST_MATH_GPU_ENABLED T heuman_lambda_imp(T phi, T k, const Policy& pol) T result; T sinp = sin(phi); T cosp = cos(phi); - T s2 = sinp * sinp; T k2 = k * k; T kp = 1 - k2; - T delta = sqrt(1 - (kp * s2)); + T c2 = cosp * cosp; + // 1 - kp * s2 written without cancellation, as phi -> pi/2 and/or k -> 0: + T delta2 = k2 + kp * c2; + T delta = sqrt(delta2); if(fabs(phi) <= constants::half_pi()) { result = kp * sinp * cosp / (delta * constants::half_pi()); - result *= ellint_rf_imp(T(0), kp, T(1), pol) + k2 * ellint_rj(T(0), kp, T(1), T(1 - k2 / (delta * delta)), pol) / (3 * delta * delta); + result *= ellint_rf_imp(T(0), kp, T(1), pol) + k2 * ellint_rj(T(0), kp, T(1), T(kp * c2 / delta2), pol) / (3 * delta2); } else { - typedef boost::math::integral_constant::value && boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 54) ? 0 : - boost::math::is_floating_point::value && boost::math::numeric_limits::digits && (boost::math::numeric_limits::digits <= 64) ? 1 : 2 + typedef BOOST_MATH_NAMESPACE::integral_constant::value && BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 54) ? 0 : + BOOST_MATH_NAMESPACE::is_floating_point::value && BOOST_MATH_NAMESPACE::numeric_limits::digits && (BOOST_MATH_NAMESPACE::numeric_limits::digits <= 64) ? 1 : 2 > precision_tag_type; T rkp = sqrt(kp); @@ -77,7 +79,7 @@ BOOST_MATH_GPU_ENABLED T heuman_lambda_imp(T phi, T k, const Policy& pol) } // detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type heuman_lambda(T1 k, T2 phi, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -85,13 +87,13 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type heuman_ return policies::checked_narrowing_cast(detail::heuman_lambda_imp(static_cast(phi), static_cast(k), pol), "boost::math::heuman_lambda<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type heuman_lambda(T1 k, T2 phi) { - return boost::math::heuman_lambda(k, phi, policies::policy<>()); + return BOOST_MATH_NAMESPACE::heuman_lambda(k, phi, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_D_HPP diff --git a/include/boost/math/special_functions/hypergeometric_0F1.hpp b/include/boost/math/special_functions/hypergeometric_0F1.hpp index a721e7e462..0b4f15b4cc 100644 --- a/include/boost/math/special_functions/hypergeometric_0F1.hpp +++ b/include/boost/math/special_functions/hypergeometric_0F1.hpp @@ -15,7 +15,7 @@ #include #include -namespace boost { namespace math { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template @@ -71,8 +71,10 @@ namespace boost { namespace math { namespace detail { // Series is alternating and divergent, need to do something else here, // Bessel function relation is much more accurate, unless |b| is similarly // large to |z|, otherwise the CF formula suffers from cancellation when - // the result would be very small. - if (fabs(z / b) > 4) + // the result would be very small. For positive b the CF's error grows rapidly + // once |z/b| > 2, but for b > max_factorial the Bessel relation needs lgamma and + // is only accurate to a few hundred eps. + if (fabs(z / b) > (((b > 0) && (b <= BOOST_MATH_NAMESPACE::max_factorial::value)) ? 2 : 4)) return hypergeometric_0F1_bessel(b, z, pol); return hypergeometric_0F1_cf_imp(b, z, pol, function); } @@ -84,7 +86,7 @@ namespace boost { namespace math { namespace detail { } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_0F1(T1 b, T2 z, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -104,13 +106,13 @@ inline typename tools::promote_args::type hypergeometric_0F1(T1 b, T2 z, "boost::math::hypergeometric_0F1<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_0F1(T1 b, T2 z) { return hypergeometric_0F1(b, z, policies::policy<>()); } -} } // namespace boost::math +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_HPP diff --git a/include/boost/math/special_functions/hypergeometric_1F0.hpp b/include/boost/math/special_functions/hypergeometric_1F0.hpp index 3fbf81ba8d..0cd709fb84 100644 --- a/include/boost/math/special_functions/hypergeometric_1F0.hpp +++ b/include/boost/math/special_functions/hypergeometric_1F0.hpp @@ -16,7 +16,7 @@ #include -namespace boost { namespace math { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template inline T hypergeometric_1F0_imp(const T& a, const T& z, const Policy& pol) @@ -37,7 +37,7 @@ inline T hypergeometric_1F0_imp(const T& a, const T& z, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_1F0(T1 a, T2 z, const Policy&) { BOOST_FPU_EXCEPTION_GUARD @@ -57,13 +57,13 @@ inline typename tools::promote_args::type hypergeometric_1F0(T1 a, T2 z, "boost::math::hypergeometric_1F0<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_1F0(T1 a, T2 z) { return hypergeometric_1F0(a, z, policies::policy<>()); } - } } // namespace boost::math + BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_1F0_HPP diff --git a/include/boost/math/special_functions/hypergeometric_1F1.hpp b/include/boost/math/special_functions/hypergeometric_1F1.hpp index 21e25670c8..76cdf28fea 100644 --- a/include/boost/math/special_functions/hypergeometric_1F1.hpp +++ b/include/boost/math/special_functions/hypergeometric_1F1.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,7 @@ #include #include -namespace boost { namespace math { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // check when 1F1 series can't decay to polynom template @@ -67,7 +68,7 @@ namespace boost { namespace math { namespace detail { T convergence_at_50 = (b - a + 50) * k / (z * 50); if ((k > 0) && (k < 50) && (fabs(convergence_at_50) < 1) && (z > z_limit)) { - return boost::math::detail::hypergeometric_1f1_recurrence_on_z_minus_zero(a, b, T(z - k), k, pol, log_scaling); + return BOOST_MATH_NAMESPACE::detail::hypergeometric_1f1_recurrence_on_z_minus_zero(a, b, T(z - k), k, pol, log_scaling); } #endif if (z < b) @@ -90,7 +91,7 @@ namespace boost { namespace math { namespace detail { // Note that if sqr is negative then we have no solution, so assign an arbitrarily large value to the // number of iterations. // - bool can_use_recursion = (z - b + 100 < boost::math::policies::get_max_series_iterations()) && (100 - a < boost::math::policies::get_max_series_iterations()); + bool can_use_recursion = (z - b + 100 < BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()) && (100 - a < BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()); T sqr = 4 * a * z + b * b - 2 * b * z + z * z; T iterations_to_convergence = sqr > 0 ? T(0.5f * (-sqrt(sqr) - b + z)) : T(-a - b); if(can_use_recursion && ((std::max)(a, b) + iterations_to_convergence > -300)) @@ -118,11 +119,11 @@ namespace boost { namespace math { namespace detail { // OK as long as a > 1 whatever the precision though. // int domain = hypergeometric_1F1_negative_b_recurrence_region(a, b, z); - if ((domain < 0) && ((a > 1) || (boost::math::policies::digits() <= 64))) + if ((domain < 0) && ((a > 1) || (BOOST_MATH_NAMESPACE::policies::digits() <= 64))) return hypergeometric_1F1_from_function_ratio_negative_b(a, b, z, pol, log_scaling); else if (domain > 0) { - if (boost::math::policies::digits() <= 64) + if (BOOST_MATH_NAMESPACE::policies::digits() <= 64) return hypergeometric_1F1_from_function_ratio_negative_b_forwards(a, b, z, pol, log_scaling); // LCOV_EXCL_START, what follows is multiprecision only #ifndef BOOST_MATH_NO_EXCEPTIONS @@ -340,7 +341,7 @@ namespace boost { namespace math { namespace detail { if ((a < -20) && (z > 0) && (z < 1)) { // https://functions.wolfram.com/HypergeometricFunctions/Hypergeometric1F1/03/01/04/02/0002/ - return exp(z) * boost::math::gamma_q(1 - a, z, pol); + return exp(z) * BOOST_MATH_NAMESPACE::gamma_q(1 - a, z, pol); } // https://functions.wolfram.com/HypergeometricFunctions/Hypergeometric1F1/03/01/04/02/0003/ return hypergeometric_1F1_checked_series_impl(a, b, z, pol, log_scaling); @@ -362,7 +363,7 @@ namespace boost { namespace math { namespace detail { } if ((a == 1) && (b == 2)) - return boost::math::expm1(z, pol) / z; + return BOOST_MATH_NAMESPACE::expm1(z, pol) / z; if ((b - a == b) && (fabs(z / b) < policies::get_epsilon())) return 1; @@ -375,7 +376,7 @@ namespace boost { namespace math { namespace detail { { // a is tiny compared to b, and z < 0 // 13.3.6 appears to be the most efficient and often the most accurate method. - T r = boost::math::detail::hypergeometric_1F1_AS_13_3_6(b_minus_a, b, T(-z), a, pol, log_scaling); + T r = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_AS_13_3_6(b_minus_a, b, T(-z), a, pol, log_scaling); long long scale = lltrunc(z, pol); log_scaling += scale; return r * exp(z - scale); @@ -406,7 +407,7 @@ namespace boost { namespace math { namespace detail { // // We've got nothing left but 13.3.6, even though it may be initially divergent: // - T r = boost::math::detail::hypergeometric_1F1_AS_13_3_6(b_minus_a, b, T(-z), a, pol, log_scaling); + T r = BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_AS_13_3_6(b_minus_a, b, T(-z), a, pol, log_scaling); long long scale = lltrunc(z, pol); log_scaling += scale; return r * exp(z - scale); @@ -453,7 +454,7 @@ namespace boost { namespace math { namespace detail { // if (is_convergent_negative_z_series(a, b, z, b_minus_a)) { - if ((boost::math::sign(b_minus_a) == boost::math::sign(b)) && ((b > 0) || (b < -200))) + if ((BOOST_MATH_NAMESPACE::sign(b_minus_a) == BOOST_MATH_NAMESPACE::sign(b)) && ((b > 0) || (b < -200))) { // Series is close enough to convergent that we should be OK, // In this domain b - a ~ b and since 1F1[a, a, z] = e^z 1F1[b-a, b, -z] @@ -597,7 +598,7 @@ namespace boost { namespace math { namespace detail { { // b_minus_a is tiny compared to b, and -z < 0 // 13.3.6 appears to be the most efficient and often the most accurate method. - return boost::math::detail::hypergeometric_1F1_AS_13_3_6(a, b, z, b_minus_a, pol, log_scaling); + return BOOST_MATH_NAMESPACE::detail::hypergeometric_1F1_AS_13_3_6(a, b, z, b_minus_a, pol, log_scaling); } #if 0 if ((a > 0) && (b > 0) && (a * z / b > 2)) @@ -634,10 +635,10 @@ namespace boost { namespace math { namespace detail { // // Actual result will be result * e^log_scaling. // - static const thread_local long long max_scaling = lltrunc(boost::math::tools::log_max_value()) - 2; + static const thread_local long long max_scaling = lltrunc(BOOST_MATH_NAMESPACE::tools::log_max_value()) - 2; static const thread_local T max_scale_factor = exp(T(max_scaling)); - while (log_scaling > max_scaling) + while (!(BOOST_MATH_NAMESPACE::isinf)(result) && (log_scaling > max_scaling)) { result *= max_scale_factor; log_scaling -= max_scaling; @@ -674,9 +675,9 @@ namespace boost { namespace math { namespace detail { // Actual result will be result * e^log_scaling / tgamma(b). // int result_sign = 1; - T scale = log_scaling - boost::math::lgamma(b, &result_sign, pol); + T scale = log_scaling - BOOST_MATH_NAMESPACE::lgamma(b, &result_sign, pol); - static const thread_local T max_scaling = boost::math::tools::log_max_value() - 2; + static const thread_local T max_scaling = BOOST_MATH_NAMESPACE::tools::log_max_value() - 2; static const thread_local T max_scale_factor = exp(max_scaling); while (scale > max_scaling) @@ -706,7 +707,7 @@ namespace boost { namespace math { namespace detail { } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_1F1(T1 a, T2 b, T3 z, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -727,13 +728,13 @@ inline typename tools::promote_args::type hypergeometric_1F1(T1 a, T "boost::math::hypergeometric_1F1<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_1F1(T1 a, T2 b, T3 z) { return hypergeometric_1F1(a, b, z, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_1F1_regularized(T1 a, T2 b, T3 z, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -754,13 +755,13 @@ inline typename tools::promote_args::type hypergeometric_1F1_regular "boost::math::hypergeometric_1F1<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_1F1_regularized(T1 a, T2 b, T3 z) { return hypergeometric_1F1_regularized(a, b, z, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type log_hypergeometric_1F1(T1 a, T2 b, T3 z, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -782,13 +783,13 @@ inline typename tools::promote_args::type log_hypergeometric_1F1(T1 "boost::math::hypergeometric_1F1<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type log_hypergeometric_1F1(T1 a, T2 b, T3 z) { return log_hypergeometric_1F1(a, b, z, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type log_hypergeometric_1F1(T1 a, T2 b, T3 z, int* sign, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -810,13 +811,13 @@ inline typename tools::promote_args::type log_hypergeometric_1F1(T1 "boost::math::hypergeometric_1F1<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type log_hypergeometric_1F1(T1 a, T2 b, T3 z, int* sign) { return log_hypergeometric_1F1(a, b, z, sign, policies::policy<>()); } - } } // namespace boost::math + BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_HPP diff --git a/include/boost/math/special_functions/hypergeometric_2F0.hpp b/include/boost/math/special_functions/hypergeometric_2F0.hpp index d22e6a029d..5ed64e55b2 100644 --- a/include/boost/math/special_functions/hypergeometric_2F0.hpp +++ b/include/boost/math/special_functions/hypergeometric_2F0.hpp @@ -15,9 +15,11 @@ #include #include #include +#include +#include #include -namespace boost { namespace math { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { template struct hypergeometric_2F0_cf @@ -46,7 +48,7 @@ namespace boost { namespace math { namespace detail { template T hypergeometric_2F0_cf_imp(T a1, T a2, T z, const Policy& pol, const char* function) { - using namespace boost::math; + using namespace BOOST_MATH_NAMESPACE; hypergeometric_2F0_cf evaluator(a1, a2, z); std::uintmax_t max_iter = policies::get_max_series_iterations(); T cf = tools::continued_fraction_b(evaluator, policies::get_epsilon(), max_iter); @@ -55,6 +57,57 @@ namespace boost { namespace math { namespace detail { } + // + // 2F0(-n, b; z) for b > 0 and z > 0, where the series alternates and cancels badly. Instead use the recurrence + // g[k+1] = (1 - (k + b) z) g[k] + k z g[k-1], with g[0] = 1 and g[1] = 1 - b z. Where g is close to the + // minimal solution of the recurrence its rounding errors grow, so as in laguerre.hpp we find the rounding error + // of each step almost exactly, and carry it forward with the same recurrence. The result is then correctly + // rounded unless the uncorrected recurrence was out by more than a few percent, which only happens for n > 50 + // and n z between about 1 and 20, and there we raise an evaluation_error rather than return a wrong value. + // + template + T hypergeometric_2F0_neg_int_recurrence(unsigned n, const T& b, const T& z, const Policy& pol, const char* function) + { + BOOST_MATH_STD_USING + two_product product; + // g1 + e1 = 1 - b z exactly: + T bz, rbz; + product(b, z, bz, rbz); + T g1 = 1 - bz; + T e1 = two_sum_error(T(1), T(-bz), g1) - rbz; + T g0 = 1; + T e0 = 0; + for (unsigned k = 1; k < n; ++k) + { + // a + ea = 1 - (k + b) z and c + ec = k z exactly: + T u = k + b; + T eu = two_sum_error(T(k), b, u); + T v, rv; + product(u, z, v, rv); + rv += eu * z; + T a = 1 - v; + T ea = two_sum_error(T(1), T(-v), a) - rv; + T c, ec; + product(T(k), z, c, ec); + // s1 + r1 = a g1, s2 + r2 = c g0 and d + ed = s1 + s2 exactly: + T s1, r1, s2, r2; + product(a, g1, s1, r1); + product(c, g0, s2, r2); + T d = s1 + s2; + T ed = two_sum_error(s1, s2, d); + T e2 = a * e1 + c * e0 + ed + r1 + r2 + ea * g1 + ec * g0; + g0 = g1; + g1 = d; + e0 = e1; + e1 = e2; + } + if (!(BOOST_MATH_NAMESPACE::isfinite)(g1)) + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); + if (!(fabs(e1) < fabs(g1) / 32)) + return BOOST_MATH_NAMESPACE::policies::raise_evaluation_error(function, "The recurrence loses too many digits to give an accurate result, last value was %1%", T(g1 + e1), pol); + return g1 + e1; + } + template inline T hypergeometric_2F0_imp(T a1, T a2, const T& z, const Policy& pol, bool asymptotic = false) { @@ -73,7 +126,7 @@ namespace boost { namespace math { namespace detail { bool is_a2_integer = (a2 == floor(a2)); if (!asymptotic && !is_a1_integer && !is_a2_integer) - return boost::math::policies::raise_overflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); if (!is_a1_integer || (a1 > 0)) { swap(a1, a2); @@ -83,7 +136,7 @@ namespace boost { namespace math { namespace detail { // At this point a1 must be a negative integer: // if(!asymptotic && (!is_a1_integer || (a1 > 0))) - return boost::math::policies::raise_overflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); // // Special cases first: // @@ -92,32 +145,35 @@ namespace boost { namespace math { namespace detail { if ((a1 == a2 - 0.5f) && (z < 0)) { // http://functions.wolfram.com/07.31.03.0083.01 - int n = static_cast(static_cast(boost::math::lltrunc(-2 * a1))); + int n = static_cast(static_cast(BOOST_MATH_NAMESPACE::lltrunc(-2 * a1))); T smz = sqrt(-z); - return static_cast(pow(2 / smz, T(-n)) * boost::math::hermite(n, 1 / smz, pol)); // Warning suppression: integer power returns at least a double + return static_cast(pow(2 / smz, T(-n)) * BOOST_MATH_NAMESPACE::hermite(n, 1 / smz, pol)); // Warning suppression: integer power returns at least a double } if (is_a1_integer && is_a2_integer) { if ((a1 < 1) && (a2 <= a1)) { - const unsigned int n = static_cast(static_cast(boost::math::lltrunc(-a1))); - const unsigned int m = static_cast(static_cast(boost::math::lltrunc(-a2 - n))); + const unsigned int n = static_cast(static_cast(BOOST_MATH_NAMESPACE::lltrunc(-a1))); + const unsigned int m = static_cast(static_cast(BOOST_MATH_NAMESPACE::lltrunc(-a2 - n))); - return (pow(z, T(n)) * boost::math::factorial(n, pol)) * - boost::math::laguerre(n, m, -(1 / z), pol); + return (pow(z, T(n)) * BOOST_MATH_NAMESPACE::factorial(n, pol)) * + BOOST_MATH_NAMESPACE::laguerre(n, m, -(1 / z), pol); } else if ((a2 < 1) && (a1 <= a2)) { // function is symmetric for a1 and a2 - const unsigned int n = static_cast(static_cast(boost::math::lltrunc(-a2))); - const unsigned int m = static_cast(static_cast(boost::math::lltrunc(-a1 - n))); + const unsigned int n = static_cast(static_cast(BOOST_MATH_NAMESPACE::lltrunc(-a2))); + const unsigned int m = static_cast(static_cast(BOOST_MATH_NAMESPACE::lltrunc(-a1 - n))); - return (pow(z, T(n)) * boost::math::factorial(n, pol)) * - boost::math::laguerre(n, m, -(1 / z), pol); + return (pow(z, T(n)) * BOOST_MATH_NAMESPACE::factorial(n, pol)) * + BOOST_MATH_NAMESPACE::laguerre(n, m, -(1 / z), pol); } } + if ((a2 > 0) && (z > 0)) + return hypergeometric_2F0_neg_int_recurrence(static_cast(BOOST_MATH_NAMESPACE::lltrunc(-a1)), a2, z, pol, function); + if ((a1 * a2 * z < 0) && (a2 < -5) && (fabs(a1 * a2 * z) > 0.5)) { // Series is alternating and maybe divergent at least for the first few terms @@ -130,7 +186,7 @@ namespace boost { namespace math { namespace detail { } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_2F0(T1 a1, T2 a2, T3 z, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD @@ -151,13 +207,13 @@ inline typename tools::promote_args::type hypergeometric_2F0(T1 a1, "boost::math::hypergeometric_2F0<%1%>(%1%,%1%,%1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_2F0(T1 a1, T2 a2, T3 z) { return hypergeometric_2F0(a1, a2, z, policies::policy<>()); } - } } // namespace boost::math + BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPERGEOMETRIC_HPP diff --git a/include/boost/math/special_functions/hypergeometric_pFq.hpp b/include/boost/math/special_functions/hypergeometric_pFq.hpp index 96f68e510e..d76de1637a 100644 --- a/include/boost/math/special_functions/hypergeometric_pFq.hpp +++ b/include/boost/math/special_functions/hypergeometric_pFq.hpp @@ -10,11 +10,12 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -30,9 +31,9 @@ namespace boost { bool operator()(std::uintmax_t iter)const { if (iter > max_iter) - BOOST_MATH_THROW_EXCEPTION(boost::math::detail::pFq_termination_exception("pFq exceeded maximum permitted iterations.")); + BOOST_MATH_THROW_EXCEPTION(BOOST_MATH_NAMESPACE::detail::pFq_termination_exception("pFq exceeded maximum permitted iterations.")); if (std::chrono::duration(std::chrono::system_clock::now() - start_time).count() > max_time) - BOOST_MATH_THROW_EXCEPTION(boost::math::detail::pFq_termination_exception("pFq exceeded maximum permitted evaluation time.")); + BOOST_MATH_THROW_EXCEPTION(BOOST_MATH_NAMESPACE::detail::pFq_termination_exception("pFq exceeded maximum permitted evaluation time.")); return false; } @@ -43,7 +44,7 @@ namespace boost { } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* p_abs_error, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -59,7 +60,7 @@ namespace boost { long long scale = 0; static const char* function = "boost::math::hypergeometric_pFq<%1%>(%1%,%1%,%1%)"; - std::pair r = boost::math::detail::hypergeometric_pFq_checked_series_impl(aj, bj, value_type(z), pol, boost::math::detail::iteration_terminator(boost::math::policies::get_max_series_iterations()), scale); + std::pair r = BOOST_MATH_NAMESPACE::detail::hypergeometric_pFq_checked_series_impl(aj, bj, value_type(z), pol, BOOST_MATH_NAMESPACE::detail::iteration_terminator(BOOST_MATH_NAMESPACE::policies::get_max_series_iterations()), scale); // // Overflow check: // @@ -72,23 +73,32 @@ namespace boost { r.first *= mul; r.second *= mul; if (p_abs_error) - *p_abs_error = static_cast(r.second) * boost::math::tools::epsilon(); + *p_abs_error = static_cast(r.second) * BOOST_MATH_NAMESPACE::tools::epsilon(); + else if ((r.first != 0) && !(r.second * BOOST_MATH_NAMESPACE::tools::epsilon() <= BOOST_MATH_NAMESPACE::tools::root_epsilon() * fabs(r.first))) + { + // + // The series calculation has lost more than half the digits of the result to cancellation, + // and the caller didn't ask for the error estimate so can't know about it: raise an error + // rather than return a value that is wrong in most of its digits. + // + return policies::raise_evaluation_error(function, "Cancellation is so severe that fewer than half the digits in the result are correct, last result was %1%", static_cast(r.first), pol); + } return policies::checked_narrowing_cast(r.first, function); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* p_abs_error = 0) { - return hypergeometric_pFq(aj, bj, z, p_abs_error, boost::math::policies::policy<>()); + return hypergeometric_pFq(aj, bj, z, p_abs_error, BOOST_MATH_NAMESPACE::policies::policy<>()); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* p_abs_error, const Policy& pol) { return hypergeometric_pFq, Real, Policy>(aj, bj, z, p_abs_error, pol); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type hypergeometric_pFq(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, Real* p_abs_error = nullptr) { return hypergeometric_pFq, Real>(aj, bj, z, p_abs_error); @@ -110,7 +120,7 @@ namespace boost { unsigned old_p; }; - template + BOOST_MATH_EXPORT template Real hypergeometric_pFq_precision(const Seq& aj, const Seq& bj, Real z, unsigned digits10, double timeout, const Policy& pol) { unsigned current_precision = digits10 + 5; @@ -138,7 +148,7 @@ namespace boost { try { long long scale = 0; - std::pair rp = boost::math::detail::hypergeometric_pFq_checked_series_impl(aa, bb, z, pol, boost::math::detail::timed_iteration_terminator(boost::math::policies::get_max_series_iterations(), timeout), scale); + std::pair rp = BOOST_MATH_NAMESPACE::detail::hypergeometric_pFq_checked_series_impl(aa, bb, z, pol, BOOST_MATH_NAMESPACE::detail::timed_iteration_terminator(BOOST_MATH_NAMESPACE::policies::get_max_series_iterations(), timeout), scale); rp.first *= exp(Real(scale)); rp.second *= exp(Real(scale)); @@ -149,7 +159,7 @@ namespace boost { try { cancellation = itrunc(log10(abs(norm / r))); } - catch (const boost::math::rounding_error&) + catch (const BOOST_MATH_NAMESPACE::rounding_error&) { // Happens when r is near enough zero: cancellation = UINT_MAX; @@ -167,7 +177,7 @@ namespace boost { else break; } - catch (const boost::math::evaluation_error&) + catch (const BOOST_MATH_NAMESPACE::evaluation_error&) { current_precision *= 2; } @@ -176,30 +186,29 @@ namespace boost { // // Either we have exhausted the number of series iterations, or the timeout. // Either way we quit now. - throw boost::math::evaluation_error(e.what()); + throw BOOST_MATH_NAMESPACE::evaluation_error(e.what()); } } while (true); return r; } - template + BOOST_MATH_EXPORT template Real hypergeometric_pFq_precision(const Seq& aj, const Seq& bj, const Real& z, unsigned digits10, double timeout = 0.5) { - return hypergeometric_pFq_precision(aj, bj, z, digits10, timeout, boost::math::policies::policy<>()); + return hypergeometric_pFq_precision(aj, bj, z, digits10, timeout, BOOST_MATH_NAMESPACE::policies::policy<>()); } - template + BOOST_MATH_EXPORT template Real hypergeometric_pFq_precision(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, unsigned digits10, double timeout, const Policy& pol) { return hypergeometric_pFq_precision< std::initializer_list, Real>(aj, bj, z, digits10, timeout, pol); } - template + BOOST_MATH_EXPORT template Real hypergeometric_pFq_precision(const std::initializer_list& aj, const std::initializer_list& bj, const Real& z, unsigned digits10, double timeout = 0.5) { - return hypergeometric_pFq_precision< std::initializer_list, Real>(aj, bj, z, digits10, timeout, boost::math::policies::policy<>()); + return hypergeometric_pFq_precision< std::initializer_list, Real>(aj, bj, z, digits10, timeout, BOOST_MATH_NAMESPACE::policies::policy<>()); } #endif - } -} // namespaces + BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_BESSEL_ITERATORS_HPP diff --git a/include/boost/math/special_functions/hypot.hpp b/include/boost/math/special_functions/hypot.hpp index 66a9492541..f581c1a1c6 100644 --- a/include/boost/math/special_functions/hypot.hpp +++ b/include/boost/math/special_functions/hypot.hpp @@ -19,7 +19,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED T hypot_imp(T x, T y, const Policy& pol) @@ -37,9 +37,9 @@ BOOST_MATH_GPU_ENABLED T hypot_imp(T x, T y, const Policy& pol) #pragma warning(disable: 4127) #endif // special case, see C99 Annex F: - if(boost::math::numeric_limits::has_infinity - && ((x == boost::math::numeric_limits::infinity()) - || (y == boost::math::numeric_limits::infinity()))) + if(BOOST_MATH_NAMESPACE::numeric_limits::has_infinity + && ((x == BOOST_MATH_NAMESPACE::numeric_limits::infinity()) + || (y == BOOST_MATH_NAMESPACE::numeric_limits::infinity()))) return policies::raise_overflow_error("boost::math::hypot<%1%>(%1%,%1%)", nullptr, pol); #ifdef _MSC_VER #pragma warning(pop) @@ -69,11 +69,11 @@ BOOST_MATH_GPU_ENABLED T hypot_imp(T x, T y, T z, const Policy& pol) #pragma warning(disable: 4127) #endif // special case, see C99 Annex F: - BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + BOOST_MATH_IF_CONSTEXPR (BOOST_MATH_NAMESPACE::numeric_limits::has_infinity) { - if(((x == boost::math::numeric_limits::infinity()) - || (y == boost::math::numeric_limits::infinity()) - || (z == boost::math::numeric_limits::infinity()))) + if(((x == BOOST_MATH_NAMESPACE::numeric_limits::infinity()) + || (y == BOOST_MATH_NAMESPACE::numeric_limits::infinity()) + || (z == BOOST_MATH_NAMESPACE::numeric_limits::infinity()))) return policies::raise_overflow_error("boost::math::hypot<%1%>(%1%,%1%,%1%)", nullptr, pol); } #ifdef _MSC_VER @@ -99,7 +99,7 @@ BOOST_MATH_GPU_ENABLED T hypot_imp(T x, T y, T z, const Policy& pol) } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type hypot(T1 x, T2 y) { @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type static_cast(x), static_cast(y), policies::policy<>()); } -template , bool>> +BOOST_MATH_EXPORT template , bool>> BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type hypot(T1 x, T2 y, const Policy& pol) { @@ -117,7 +117,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type static_cast(x), static_cast(y), pol); } -template , bool>> +BOOST_MATH_EXPORT template , bool>> BOOST_MATH_GPU_ENABLED inline tools::promote_args_t hypot(T1 x, T2 y, T3 z) { @@ -128,7 +128,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t hypot(T1 x, T2 y, T3 z, const Policy& pol) { @@ -139,8 +139,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t pol); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HYPOT_INCLUDED diff --git a/include/boost/math/special_functions/jacobi.hpp b/include/boost/math/special_functions/jacobi.hpp index e4703be307..fec5b957af 100644 --- a/include/boost/math/special_functions/jacobi.hpp +++ b/include/boost/math/special_functions/jacobi.hpp @@ -6,12 +6,16 @@ #ifndef BOOST_MATH_SPECIAL_JACOBI_HPP #define BOOST_MATH_SPECIAL_JACOBI_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif + +#include -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template Real jacobi(unsigned n, Real alpha, Real beta, Real x) { static_assert(!std::is_integral::value, "Jacobi polynomials do not work with integer arguments."); @@ -39,7 +43,7 @@ Real jacobi(unsigned n, Real alpha, Real beta, Real x) return yk; } -template +BOOST_MATH_EXPORT template Real jacobi_derivative(unsigned n, Real alpha, Real beta, Real x, unsigned k) { if (k > n) { @@ -53,17 +57,17 @@ Real jacobi_derivative(unsigned n, Real alpha, Real beta, Real x, unsigned k) return scale*jacobi(n-k, alpha + k, beta+k, x); } -template +BOOST_MATH_EXPORT template Real jacobi_prime(unsigned n, Real alpha, Real beta, Real x) { return jacobi_derivative(n, alpha, beta, x, 1); } -template +BOOST_MATH_EXPORT template Real jacobi_double_prime(unsigned n, Real alpha, Real beta, Real x) { return jacobi_derivative(n, alpha, beta, x, 2); } -}} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/jacobi_elliptic.hpp b/include/boost/math/special_functions/jacobi_elliptic.hpp index 149e9fb1ca..6b2c455e20 100644 --- a/include/boost/math/special_functions/jacobi_elliptic.hpp +++ b/include/boost/math/special_functions/jacobi_elliptic.hpp @@ -12,12 +12,12 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template -T jacobi_recurse(const T& x, const T& k, T anm1, T bnm1, unsigned N, T* pTn, const Policy& pol) +T jacobi_recurse(const T& x, const T& k, T anm1, T bnm1, unsigned N, const Policy& pol) { BOOST_MATH_STD_USING ++N; @@ -29,9 +29,7 @@ T jacobi_recurse(const T& x, const T& k, T anm1, T bnm1, unsigned N, T* pTn, con Tn = ldexp(T(1), (int)N) * x * an; } else - Tn = jacobi_recurse(x, k, an, sqrt(anm1 * bnm1), N, 0, pol); - if(pTn) - *pTn = Tn; + Tn = jacobi_recurse(x, k, an, sqrt(anm1 * bnm1), N, pol); return (Tn + asin((cn / an) * sin(Tn))) / 2; } @@ -103,18 +101,22 @@ T jacobi_imp(const T& x, const T& k, T* cn, T* dn, const Policy& pol, const char T sn3 = (72 * x * cu + 4 * (8 * x * x - 5) * su - 19 * sinh(3 * x) + sinh(5 * x)) * sec * sec * sec * m1 * m1 / 512; return sn + sn2 - sn3; }*/ - T T1; T kc = 1 - k; T k_prime = k < T(0.5) ? T(sqrt(1 - k * k)) : T(sqrt(2 * kc - kc * kc)); - T T0 = jacobi_recurse(x, k, T(1), k_prime, 0, &T1, pol); - *cn = cos(T0); - *dn = cos(T0) / cos(T1 - T0); - return sin(T0); + T T0 = jacobi_recurse(x, k, T(1), k_prime, 0, pol); + T sn = sin(T0); + T c = cos(T0); + *cn = c; + // + // dn^2 = 1 - k^2 sn^2 = cn^2 + k'^2 sn^2, which doesn't lose digits near the zeros of cn: + // + *dn = sqrt(c * c + k_prime * k_prime * sn * sn); + return sn; } } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn, const Policy&) { BOOST_FPU_EXCEPTION_GUARD @@ -138,26 +140,26 @@ inline typename tools::promote_args::type jacobi_elliptic(T k, U theta, return policies::checked_narrowing_cast(sn, function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn) { return jacobi_elliptic(k, theta, pcn, pdn, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_sn(U k, T theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; return jacobi_elliptic(static_cast(k), static_cast(theta), static_cast(nullptr), static_cast(nullptr), pol); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_sn(U k, T theta) { return jacobi_sn(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_cn(T k, U theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -166,13 +168,13 @@ inline typename tools::promote_args::type jacobi_cn(T k, U theta, const Po return cn; } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_cn(T k, U theta) { return jacobi_cn(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_dn(T k, U theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -181,13 +183,13 @@ inline typename tools::promote_args::type jacobi_dn(T k, U theta, const Po return dn; } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_dn(T k, U theta) { return jacobi_dn(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_cd(T k, U theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -196,13 +198,13 @@ inline typename tools::promote_args::type jacobi_cd(T k, U theta, const Po return cn / dn; } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_cd(T k, U theta) { return jacobi_cd(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_dc(T k, U theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -211,26 +213,26 @@ inline typename tools::promote_args::type jacobi_dc(T k, U theta, const Po return dn / cn; } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_dc(T k, U theta) { return jacobi_dc(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_ns(T k, U theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; return 1 / jacobi_elliptic(static_cast(k), static_cast(theta), static_cast(nullptr), static_cast(nullptr), pol); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_ns(T k, U theta) { return jacobi_ns(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_sd(T k, U theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -239,13 +241,13 @@ inline typename tools::promote_args::type jacobi_sd(T k, U theta, const Po return sn / dn; } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_sd(T k, U theta) { return jacobi_sd(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_ds(T k, U theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -254,37 +256,37 @@ inline typename tools::promote_args::type jacobi_ds(T k, U theta, const Po return dn / sn; } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_ds(T k, U theta) { return jacobi_ds(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_nc(T k, U theta, const Policy& pol) { return 1 / jacobi_cn(k, theta, pol); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_nc(T k, U theta) { return jacobi_nc(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_nd(T k, U theta, const Policy& pol) { return 1 / jacobi_dn(k, theta, pol); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_nd(T k, U theta) { return jacobi_nd(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_sc(T k, U theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -293,13 +295,13 @@ inline typename tools::promote_args::type jacobi_sc(T k, U theta, const Po return sn / cn; } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_sc(T k, U theta) { return jacobi_sc(k, theta, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_cs(T k, U theta, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -308,12 +310,12 @@ inline typename tools::promote_args::type jacobi_cs(T k, U theta, const Po return cn / sn; } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_cs(T k, U theta) { return jacobi_cs(k, theta, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_JACOBI_ELLIPTIC_HPP diff --git a/include/boost/math/special_functions/jacobi_theta.hpp b/include/boost/math/special_functions/jacobi_theta.hpp index e3e17e7e03..09abfb827f 100644 --- a/include/boost/math/special_functions/jacobi_theta.hpp +++ b/include/boost/math/special_functions/jacobi_theta.hpp @@ -100,450 +100,863 @@ #ifndef BOOST_MATH_JACOBI_THETA_HPP #define BOOST_MATH_JACOBI_THETA_HPP +#include +#include #include #include #include #include #include +#include +#include +#include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN // Simple functions - parameterized by q -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta1(T z, U q); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta2(T z, U q); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3(T z, U q); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4(T z, U q); // Simple functions - parameterized by tau (assumed imaginary) // q = exp(i*PI*TAU) // tau = -log(q)/PI -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta1tau(T z, U tau); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta2tau(T z, U tau); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3tau(T z, U tau); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4tau(T z, U tau); // Minus one versions for small q / large tau -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3m1(T z, U q); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4m1(T z, U q); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3m1tau(T z, U tau); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4m1tau(T z, U tau); // Policied versions - parameterized by q -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta1(T z, U q, const Policy& pol); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta2(T z, U q, const Policy& pol); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3(T z, U q, const Policy& pol); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4(T z, U q, const Policy& pol); // Policied versions - parameterized by tau -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta1tau(T z, U tau, const Policy& pol); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta2tau(T z, U tau, const Policy& pol); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3tau(T z, U tau, const Policy& pol); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4tau(T z, U tau, const Policy& pol); // Policied m1 functions -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3m1(T z, U q, const Policy& pol); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4m1(T z, U q, const Policy& pol); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3m1tau(T z, U tau, const Policy& pol); -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4m1tau(T z, U tau, const Policy& pol); +namespace detail { + // Compare the non-oscillating component of the delta to the previous delta. -// Both are assumed to be non-negative. +// Both are assumed to be non-negative. Written so that a NaN delta counts as +// converged: otherwise a NaN would never satisfy the test and the summation +// loops below would never terminate. template inline bool -_jacobi_theta_converged(RealType last_delta, RealType delta, RealType eps) { - return delta == 0.0 || delta < eps*last_delta; +jacobi_theta_converged(RealType last_delta, RealType delta, RealType eps) { + return !(delta > eps*last_delta); +} + +template +inline bool +jacobi_theta_check_z(RealType z, const Policy& pol, const char* function, RealType* result) { + if (!(BOOST_MATH_NAMESPACE::isfinite)(z)) { + *result = policies::raise_domain_error(function, "z must be finite but got %1%.", z, pol); + return false; + } + return true; +} + +template +inline bool +jacobi_theta_check_tau(RealType tau, const Policy& pol, const char* function, RealType* result) { + // The negated comparison also rejects NaN. + if (!(tau > 0)) { + *result = policies::raise_domain_error(function, "tau must be greater than 0 but got %1%.", tau, pol); + return false; + } + return true; +} + +template +inline bool +jacobi_theta_check_q(RealType q, const Policy& pol, const char* function, RealType* result) { + // The negated comparison also rejects NaN. + if (!(q > 0 && q < 1)) { + *result = policies::raise_domain_error(function, "q must be greater than 0 and less than 1 but got %1%.", q, pol); + return false; + } + return true; } +// Powers of the nome for the direct Fourier series below. When the caller +// supplies q directly we raise q to the power with pow(), which is accurate to +// about an ulp for any exponent. Going through tau = -log(q)/pi and back via +// exp() would multiply the rounding error by |log q|, which is exactly the +// small-q regime the "m1" functions exist to serve. +template +struct jacobi_theta_q_power { + RealType q; + RealType operator()(RealType exponent) const { + BOOST_MATH_STD_USING + return pow(q, exponent); + } +}; + +// When the caller supplies tau, every term is an exponential exp(-E) whose +// argument E is a product or quotient of tau, pi and a small integer (or, for +// tau < 1, the square of z plus a multiple of pi/2). Rounding E to working +// precision costs |E| ulps in the exponential, so instead the rounding +// errors of pi, of the products and of the division are tracked exactly with +// two_product and two_sum_error (which work for any binary floating-point +// type) and applied as a correction factor exp(-dE) = 1 - dE. What remains +// is the rounding of tau itself, which is the caller's. + +// Pi as hi + lo + lo2: hi holds the leading 24 bits exactly, so that hi * e +// is exact for small integers e, and lo the following ones to the type's own +// precision, so that hi + lo carries pi to about 24 bits beyond it. lo2 is +// what lo could not hold, which only matters for the large multiples of the +// argument reduction. The 16 pieces of 24 bits cover 384 bits; types with more +// precision than that can use use their own rounding of pi with lo = 0. template +inline RealType jacobi_theta_pi(RealType& lo, RealType& lo2) { + BOOST_MATH_STD_USING + if (tools::digits() > 360) { + lo = 0; + lo2 = 0; + return constants::pi(); + } + static const int pieces[16] = {13176794, 10625384, 12727492, 13001355, 8444956, 13707522, 5113994, 6802548, 134078, 10894099, 10166865, 4851833, 9319428, 14544789, 1684429, 3818267}; + static const RealType pi_hi = ldexp(RealType(pieces[0]), -22); + static const RealType pi_lo = [] { + RealType s = 0; + for (int i = 15; i > 0; --i) + s += ldexp(RealType(pieces[i]), -22 - 24 * i); + return s; + }(); + static const RealType pi_lo2 = [] { + RealType r = ldexp(RealType(pieces[1]), -46) - pi_lo; + for (int i = 2; i < 16; ++i) + r += ldexp(RealType(pieces[i]), -22 - 24 * i); + return r; + }(); + lo = pi_lo; + lo2 = pi_lo2; + return pi_hi; +} + +// The quantity everything is expressed in is a = pi*tau = -ln(q), held as +// a_hi + a_lo. Built from tau it is exact (to second order); built from q it +// carries the rounding of the logarithm, which is inherent to that +// parameterization, but nothing else. +template +struct jacobi_theta_exponents { + RealType tau; // only used for the scale factor 1/sqrt(tau) + two_product product; + RealType pi_hi, pi_lo, pi_lo2; // pi = pi_hi + pi_lo + pi_lo2 + RealType a_hi, a_lo; // pi * tau = -ln(q) = a_hi + a_lo + RealType inv_a_hi; // 1 / a_hi, only needed when tau < 1 + + static jacobi_theta_exponents from_tau(RealType tau) { + jacobi_theta_exponents x; + x.tau = tau; + x.a_hi = x.pi_times(tau, x.a_lo); + x.inv_a_hi = (tau < 1) ? 1 / x.a_hi : RealType(0); + return x; + } + + static jacobi_theta_exponents from_nome(RealType q) { + BOOST_MATH_STD_USING + jacobi_theta_exponents x; + x.a_hi = -log(q); + x.a_lo = 0; + x.tau = x.a_hi / constants::pi(); + x.inv_a_hi = (x.tau < 1) ? 1 / x.a_hi : RealType(0); + return x; + } + + // pi * e as hi + lo for a small exact e + RealType pi_times(RealType e, RealType& lo) const { + RealType p, ep, q, eq; + product(pi_hi, e, p, ep); + product(pi_lo, e, q, eq); + RealType hi = p + q; + // |q| << |p|, so the sum's error is simply q - (hi - p). The rounding + // of q itself only matters for the large multiples of the argument + // reduction, but it is cheap to carry. + lo = (q - (hi - p)) + ep + eq; + return hi; + } + + // (N + dN) / (a_hi + a_lo) as E + dE, to second order + RealType divide_by_a(RealType N, RealType dN, RealType& dE) const { + RealType E = N * inv_a_hi; + RealType Ea, eEa; + product(E, a_hi, Ea, eEa); + RealType r = (N - Ea) - eEa; + dE = (r + dN - E * a_lo) * inv_a_hi; + return E; + } + + // exp(-a * e) = q^e for a small exact e such as n^2 or (n+1/2)^2 + RealType direct(RealType e) const { + BOOST_MATH_STD_USING + RealType E = a_hi * e; + RealType result = exp(-E); + if (result == 0) + return result; + RealType dE = product.error(a_hi, e, E) + a_lo * e; + return result * (1 - dE); + } + + // exp(-pi * e / tau) = exp(-pi^2 * e / a), the nome of 1/tau raised to e + RealType inverse(RealType e) const { + BOOST_MATH_STD_USING + RealType dN, dP; + RealType N = pi_times(e, dN); + RealType P = pi_times(N, dP); + dP += pi_hi * dN; + RealType dE; + RealType E = divide_by_a(P, dP, dE); + RealType result = exp(-E); + if (result == 0) + return result; + return result * (1 - dE); + } + + // Reduces z by the nearest multiple of the period (half_pis * pi/2), + // returning the remainder along with its rounding dz, and in k an integer + // with the parity of the multiple for the caller's sign. The Gaussians + // below amplify an error in the argument by 2z/(pi*tau), so the multiple + // of pi is formed to well beyond working precision. + RealType reduce(RealType z, int half_pis, RealType& dz, RealType& k) const { + BOOST_MATH_STD_USING + // The multiple is chosen with the type's full pi: pi_hi alone has only + // 24 bits, and its relative error times z would pick the wrong multiple + // once z exceeds a few times 10^7. Beyond 2^digits periods the quotient + // itself is rounded and a pass only gets within a few periods, so the + // remainder is reduced again. + RealType period = (pi_hi + pi_lo) * RealType(half_pis) / 2; + RealType reduced = z; + dz = 0; + k = 0; + do { + RealType m = floor(reduced / period + RealType(0.5)); + RealType e = m * RealType(half_pis) / 2; + RealType dc; + RealType c = pi_times(e, dc); + dc += pi_lo2 * e; + RealType r = reduced - c; // exact, c being within a factor of two of reduced + RealType err = (two_sum_error(reduced, RealType(-c), r) - dc) + dz; + // err can be as large as half an ulp of z, too large for the + // first-order corrections applied to the terms, so it is folded + // into the remainder, leaving only the rounding of that. + reduced = r + err; + dz = two_sum_error(r, err, reduced); + // m may exceed the integers the type holds exactly, but such + // values are even, so their parity is still right. + k += fmod(m, RealType(2)); + } while (abs(reduced) > period); + return reduced; + } + + // exp(-(z + m*pi/2)^2 / (pi * tau)) for an integer m, where dz is the + // error in z from the argument reduction + RealType gaussian(RealType z, RealType dz, int m) const { + BOOST_MATH_STD_USING + RealType z_n = z; + if (m != 0) { + RealType dc; + RealType c = pi_times(RealType(m), dc) / 2; + z_n = z + c; + dz += two_sum_error(z, c, z_n) + dc / 2; + } + RealType s, ds; + product(z_n, z_n, s, ds); + ds += 2 * z_n * dz; + RealType dE; + RealType E = divide_by_a(s, ds, dE); + RealType result = exp(-E); + if (result == 0) + return result; + return result * (1 - dE); + } + + // expm1(-2 * z * k / tau) = expm1(-2 * pi * z * k / a) for a small exact + // k, where dz is the error in z + RealType expm1_scaled(RealType z, RealType dz, RealType k) const { + BOOST_MATH_STD_USING + RealType P, dP; + product(z, k, P, dP); + dP += dz * k; + RealType dN; + RealType N = pi_times(P, dN); + dN += pi_hi * dP; + RealType dQ; + RealType Q = divide_by_a(N, dN, dQ); + RealType result = BOOST_MATH_NAMESPACE::expm1(RealType(-2 * Q)); + if (result == -1) + return result; + return result - 2 * dQ * (1 + result); + } + +private: + jacobi_theta_exponents() { + pi_hi = jacobi_theta_pi(pi_lo, pi_lo2); + } +}; + +template +struct jacobi_theta_tau_power { + const jacobi_theta_exponents& x; + RealType operator()(RealType exponent) const { + return x.direct(exponent); + } +}; + +// exp(-pi * e / tau): the nome of 1/tau, used by the modular transformation +// at z = 0 without forming the rounded reciprocal. +template +struct jacobi_theta_inverse_tau_power { + const jacobi_theta_exponents& x; + RealType operator()(RealType exponent) const { + return x.inverse(exponent); + } +}; + +// Direct Fourier series (DLMF 20.2.1 - 20.2.4). These converge quickly when +// q < exp(-Pi), i.e. tau > 1, and are used in that regime by both the q and +// the tau parameterizations. NomePower(e) must return q^e. + +// = 2 * SUM (-1)^n * q^(n+1/2)^2 * sin((2n+1)z) +template +inline RealType +jacobi_theta1_series(RealType z, const NomePower& q_pow, const Policy&) { + BOOST_MATH_STD_USING + unsigned n = 0; + RealType eps = policies::get_epsilon(); + RealType q_n = 0, last_q_n, delta, result = 0; + + do { + last_q_n = q_n; + q_n = q_pow(RealType(n + 0.5)*RealType(n + 0.5)); + delta = q_n * sin(RealType(2*n+1)*z); + if (n%2) + delta = -delta; + + result += delta + delta; + n++; + } while (!jacobi_theta_converged(last_q_n, q_n, eps)); + + return result; +} + +// = 2 * SUM q^(n+1/2)^2 * cos((2n+1)z) +template inline RealType -_jacobi_theta_sum(RealType tau, RealType z_n, RealType z_increment, RealType eps) { +jacobi_theta2_series(RealType z, const NomePower& q_pow, const Policy&) { BOOST_MATH_STD_USING + unsigned n = 0; + RealType eps = policies::get_epsilon(); + RealType q_n = 0, last_q_n, delta, result = 0; + + do { + last_q_n = q_n; + q_n = q_pow(RealType(n + 0.5)*RealType(n + 0.5)); + delta = q_n * cos(RealType(2*n+1)*z); + result += delta + delta; + n++; + } while (!jacobi_theta_converged(last_q_n, q_n, eps)); + + return result; +} + +// = 2 * SUM q^n^2 * cos(2nz), n >= 1 (i.e. theta3 minus one) +template +inline RealType +jacobi_theta3m1_series(RealType z, const NomePower& q_pow, const Policy&) { + BOOST_MATH_STD_USING + unsigned n = 1; + RealType eps = policies::get_epsilon(); + RealType q_n = 0, last_q_n, delta, result = 0; + + do { + last_q_n = q_n; + q_n = q_pow(RealType(n)*RealType(n)); + delta = q_n * cos(RealType(2*n)*z); + result += delta + delta; + n++; + } while (!jacobi_theta_converged(last_q_n, q_n, eps)); + + return result; +} + +// = 2 * SUM (-1)^n q^n^2 * cos(2nz), n >= 1 (i.e. theta4 minus one) +template +inline RealType +jacobi_theta4m1_series(RealType z, const NomePower& q_pow, const Policy&) { + BOOST_MATH_STD_USING + unsigned n = 1; + RealType eps = policies::get_epsilon(); + RealType q_n = 0, last_q_n, delta, result = 0; + + do { + last_q_n = q_n; + q_n = q_pow(RealType(n)*RealType(n)); + delta = q_n * cos(RealType(2*n)*z); + if (n%2) + delta = -delta; + + result += delta + delta; + n++; + } while (!jacobi_theta_converged(last_q_n, q_n, eps)); + + return result; +} + +// SUM exp(-(z + m*pi/2)^2 / (pi*tau)) over m = m0, m0 + m_step, ... until the +// terms are negligible. +template +inline RealType +jacobi_theta_sum(const jacobi_theta_exponents& x, RealType z, RealType dz, int m, int m_step, RealType eps) { RealType delta = 0, partial_result = 0; RealType last_delta = 0; do { last_delta = delta; - delta = exp(-tau*z_n*z_n/constants::pi()); + delta = x.gaussian(z, dz, m); partial_result += delta; - z_n += z_increment; - } while (!_jacobi_theta_converged(last_delta, delta, eps)); + m += m_step; + } while (!jacobi_theta_converged(last_delta, delta, eps)); return partial_result; } -// The following _IMAGINARY theta functions assume imaginary z and are for +// The following imaginary theta functions assume imaginary z and are for // internal use only. They are designed to increase accuracy and reduce the // number of iterations required for convergence for large |q|. The z argument -// is scaled by tau, and the summations are rewritten to be double-sided -// following DLMF 20.13.4 and 20.13.5. The return values are scaled by -// exp(-tau*z^2/Pi)/sqrt(tau). +// is scaled by 1/tau, and the summations are rewritten to be double-sided +// following DLMF 20.13.4 and 20.13.5. Each term is a Gaussian +// exp(-(z - c)^2/(Pi*tau)) centered at a multiple of Pi or Pi/2, and the +// results are scaled by 1/sqrt(tau). // // These functions are triggered when tau < 1, i.e. |q| > exp(-Pi) = 0.043 // // Note that jacobi_theta4 uses the imaginary version of jacobi_theta2 (and // vice-versa). jacobi_theta1 and jacobi_theta3 use the imaginary versions of // themselves, following DLMF 20.7.30 - 20.7.33. + +// theta1(z|tau) = 1/sqrt(tau) * SUM_{n>=0} (-1)^n [G(z - c_n) - G(z + c_n)] +// with c_n = Pi*(n+1/2) and G(x) = exp(-x^2/(Pi*tau)). +// +// Each bracket is a difference of two Gaussians which nearly cancel when z is +// small, so it is evaluated instead through the exact identity +// G(z - c) - G(z + c) = -G(z - c) * expm1(-2*z*(2n+1)/tau), +// which keeps full relative precision all the way down to z -> 0. +// Requires 0 <= z <= Pi/2; the caller reduces z into this range, and +// passes the error dz of the reduced z. template inline RealType -_IMAGINARY_jacobi_theta1tau(RealType z, RealType tau, const Policy&) { +imaginary_jacobi_theta1tau(RealType z, RealType dz, const jacobi_theta_exponents& x, const Policy&) { BOOST_MATH_STD_USING RealType eps = policies::get_epsilon(); - RealType result = RealType(0); + RealType result = 0, g = 0, last_g, pair; + unsigned n = 0; - // n>=0 even - result -= _jacobi_theta_sum(tau, RealType(z + constants::half_pi()), constants::two_pi(), eps); - // n>0 odd - result += _jacobi_theta_sum(tau, RealType(z + constants::half_pi() + constants::pi()), constants::two_pi(), eps); - // n<0 odd - result += _jacobi_theta_sum(tau, RealType(z - constants::half_pi()), RealType (-constants::two_pi()), eps); - // n<0 even - result -= _jacobi_theta_sum(tau, RealType(z - constants::half_pi() - constants::pi()), RealType (-constants::two_pi()), eps); + do { + last_g = g; + g = x.gaussian(z, dz, -static_cast(2*n + 1)); + pair = -g * x.expm1_scaled(z, dz, RealType(2*n + 1)); + if (n%2) + pair = -pair; - return result * sqrt(tau); + result += pair; + n++; + } while (!jacobi_theta_converged(last_g, g, eps)); + + return result / sqrt(x.tau); } template inline RealType -_IMAGINARY_jacobi_theta2tau(RealType z, RealType tau, const Policy&) { +imaginary_jacobi_theta2tau(RealType z, RealType dz, const jacobi_theta_exponents& x, const Policy&) { BOOST_MATH_STD_USING RealType eps = policies::get_epsilon(); RealType result = RealType(0); - // n>=0 - result += _jacobi_theta_sum(tau, RealType(z + constants::half_pi()), constants::pi(), eps); + // n>=0: centers at z + Pi/2 + n*Pi + result += jacobi_theta_sum(x, z, dz, 1, 2, eps); // n<0 - result += _jacobi_theta_sum(tau, RealType(z - constants::half_pi()), RealType (-constants::pi()), eps); + result += jacobi_theta_sum(x, z, dz, -1, -2, eps); - return result * sqrt(tau); + return result / sqrt(x.tau); } template inline RealType -_IMAGINARY_jacobi_theta3tau(RealType z, RealType tau, const Policy&) { +imaginary_jacobi_theta3tau(RealType z, RealType dz, const jacobi_theta_exponents& x, const Policy&) { BOOST_MATH_STD_USING RealType eps = policies::get_epsilon(); RealType result = 0; // n=0 - result += exp(-z*z*tau/constants::pi()); - // n>0 - result += _jacobi_theta_sum(tau, RealType(z + constants::pi()), constants::pi(), eps); + result += x.gaussian(z, dz, 0); + // n>0: centers at z + n*Pi + result += jacobi_theta_sum(x, z, dz, 2, 2, eps); // n<0 - result += _jacobi_theta_sum(tau, RealType(z - constants::pi()), RealType(-constants::pi()), eps); + result += jacobi_theta_sum(x, z, dz, -2, -2, eps); - return result * sqrt(tau); + return result / sqrt(x.tau); } template inline RealType -_IMAGINARY_jacobi_theta4tau(RealType z, RealType tau, const Policy&) { +imaginary_jacobi_theta4tau(RealType z, RealType dz, const jacobi_theta_exponents& x, const Policy&) { BOOST_MATH_STD_USING RealType eps = policies::get_epsilon(); RealType result = 0; // n = 0 - result += exp(-z*z*tau/constants::pi()); + result += x.gaussian(z, dz, 0); - // n > 0 odd - result -= _jacobi_theta_sum(tau, RealType(z + constants::pi()), constants::two_pi(), eps); + // n > 0 odd: centers at z + Pi + 2n*Pi + result -= jacobi_theta_sum(x, z, dz, 2, 4, eps); // n < 0 odd - result -= _jacobi_theta_sum(tau, RealType(z - constants::pi()), RealType (-constants::two_pi()), eps); - // n > 0 even - result += _jacobi_theta_sum(tau, RealType(z + constants::two_pi()), constants::two_pi(), eps); + result -= jacobi_theta_sum(x, z, dz, -2, -4, eps); + // n > 0 even: centers at z + 2*Pi + 2n*Pi + result += jacobi_theta_sum(x, z, dz, 4, 4, eps); // n < 0 even - result += _jacobi_theta_sum(tau, RealType(z - constants::two_pi()), RealType (-constants::two_pi()), eps); + result += jacobi_theta_sum(x, z, dz, -4, -4, eps); - return result * sqrt(tau); + return result / sqrt(x.tau); } -// First Jacobi theta function (Parameterized by tau - assumed imaginary) +// Dispatch on the size of tau (i.e. of the nome): the direct Fourier series +// for tau >= 1, otherwise the modular transformation to 1/tau. At z = 0 the +// transformed series is evaluated directly (single-sided, with the nome of +// 1/tau formed without rounding the reciprocal); otherwise as double-sided +// Gaussian sums. + // = 2 * SUM (-1)^n * exp(i*Pi*Tau*(n+1/2)^2) * sin((2n+1)z) template inline RealType -jacobi_theta1tau_imp(RealType z, RealType tau, const Policy& pol, const char *function) -{ +jacobi_theta1_dispatch(RealType z, const jacobi_theta_exponents& x, const Policy& pol) { BOOST_MATH_STD_USING - unsigned n = 0; - RealType eps = policies::get_epsilon(); - RealType q_n = 0, last_q_n, delta, result = 0; + if (x.tau < 1.0) { + // Reduce to -Pi/2 <= z <= Pi/2 using theta1(z + Pi) = -theta1(z)... + RealType dz, k; + z = x.reduce(z, 2, dz, k); + RealType sign = (fmod(k, RealType(2)) == 0) ? 1 : -1; + // ...and then to 0 <= z <= Pi/2 since theta1 is odd. + if (z < 0) { + z = -z; + dz = -dz; + sign = -sign; + } + return sign * imaginary_jacobi_theta1tau(z, dz, x, pol); + } + return jacobi_theta1_series(z, jacobi_theta_tau_power{x}, pol); +} - if (tau <= 0.0) - return policies::raise_domain_error(function, "tau must be greater than 0 but got %1%.", tau, pol); +// = 2 * SUM exp(i*Pi*Tau*(n+1/2)^2) * cos((2n+1)z) +template +inline RealType +jacobi_theta2_dispatch(RealType z, const jacobi_theta_exponents& x, const Policy& pol) { + BOOST_MATH_STD_USING + if (x.tau < 1.0 && abs(z) == 0.0) { // theta4(0|1/tau)/sqrt(tau) + return (RealType(1) + jacobi_theta4m1_series(z, jacobi_theta_inverse_tau_power{x}, pol)) / sqrt(x.tau); + } else if (x.tau < 1.0) { // DLMF 20.7.31 + // Reduce to -Pi <= z <= Pi (theta2 has period 2*Pi) + RealType dz, k; + z = x.reduce(z, 4, dz, k); + return imaginary_jacobi_theta4tau(z, dz, x, pol); + } + return jacobi_theta2_series(z, jacobi_theta_tau_power{x}, pol); +} - if (abs(z) == 0.0) - return result; +// = 1 + 2 * SUM exp(i*Pi*Tau*(n)^2) * cos(2nz) +template +inline RealType +jacobi_theta3_dispatch(RealType z, const jacobi_theta_exponents& x, const Policy& pol) { + BOOST_MATH_STD_USING + if (x.tau < 1.0 && abs(z) == 0.0) { // theta3(0|1/tau)/sqrt(tau) + return (RealType(1) + jacobi_theta3m1_series(z, jacobi_theta_inverse_tau_power{x}, pol)) / sqrt(x.tau); + } else if (x.tau < 1.0) { // DLMF 20.7.32 + // Reduce to -Pi/2 <= z <= Pi/2 (theta3 has period Pi) + RealType dz, k; + z = x.reduce(z, 2, dz, k); + return imaginary_jacobi_theta3tau(z, dz, x, pol); + } + return RealType(1) + jacobi_theta3m1_series(z, jacobi_theta_tau_power{x}, pol); +} - if (tau < 1.0) { - z = fmod(z, constants::two_pi()); - while (z > constants::pi()) { - z -= constants::two_pi(); - } - while (z < -constants::pi()) { - z += constants::two_pi(); - } +// = 2 * SUM exp(i*Pi*Tau*(n)^2) * cos(2nz), n >= 1 (theta3 minus one) +// This preserves accuracy for small values of q (i.e. tau > 1). For larger +// values of q, the minus one version usually won't help. +template +inline RealType +jacobi_theta3m1_dispatch(RealType z, const jacobi_theta_exponents& x, const Policy& pol) { + if (x.tau < 1.0) + return jacobi_theta3_dispatch(z, x, pol) - RealType(1); + return jacobi_theta3m1_series(z, jacobi_theta_tau_power{x}, pol); +} - return _IMAGINARY_jacobi_theta1tau(z, RealType(1/tau), pol); +// = 1 + 2 * SUM (-1)^n exp(i*Pi*Tau*(n)^2) * cos(2nz) +template +inline RealType +jacobi_theta4_dispatch(RealType z, const jacobi_theta_exponents& x, const Policy& pol) { + BOOST_MATH_STD_USING + if (x.tau < 1.0 && abs(z) == 0.0) { // theta2(0|1/tau)/sqrt(tau) + return jacobi_theta2_series(z, jacobi_theta_inverse_tau_power{x}, pol) / sqrt(x.tau); + } else if (x.tau < 1.0) { // DLMF 20.7.33 + // Reduce to -Pi/2 <= z <= Pi/2 (theta4 has period Pi) + RealType dz, k; + z = x.reduce(z, 2, dz, k); + return imaginary_jacobi_theta2tau(z, dz, x, pol); } + return RealType(1) + jacobi_theta4m1_series(z, jacobi_theta_tau_power{x}, pol); +} - do { - last_q_n = q_n; - q_n = exp(-tau * constants::pi() * RealType(n + 0.5)*RealType(n + 0.5) ); - delta = q_n * sin(RealType(2*n+1)*z); - if (n%2) - delta = -delta; +// = 2 * SUM (-1)^n exp(i*Pi*Tau*(n)^2) * cos(2nz), n >= 1 (theta4 minus one) +// This preserves accuracy for small values of q (i.e. tau > 1). +template +inline RealType +jacobi_theta4m1_dispatch(RealType z, const jacobi_theta_exponents& x, const Policy& pol) { + if (x.tau < 1.0) + return jacobi_theta4_dispatch(z, x, pol) - RealType(1); + return jacobi_theta4m1_series(z, jacobi_theta_tau_power{x}, pol); +} - result += delta + delta; - n++; - } while (!_jacobi_theta_converged(last_q_n, q_n, eps)); +} // namespace detail - return result; +// The twelve _imp functions below validate their arguments and then hand +// over to the dispatchers above. The q versions use the direct series with +// pow() when q < exp(-Pi), and otherwise go through a = -ln(q). + +template +inline RealType +jacobi_theta1tau_imp(RealType z, RealType tau, const Policy& pol, const char *function) +{ + BOOST_MATH_STD_USING + RealType result = 0; + + if (!detail::jacobi_theta_check_tau(tau, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; + if (abs(z) == 0.0) + return result; + + return detail::jacobi_theta1_dispatch(z, detail::jacobi_theta_exponents::from_tau(tau), pol); } -// First Jacobi theta function (Parameterized by q) -// = 2 * SUM (-1)^n * q^(n+1/2)^2 * sin((2n+1)z) template inline RealType jacobi_theta1_imp(RealType z, RealType q, const Policy& pol, const char *function) { BOOST_MATH_STD_USING - if (q <= 0.0 || q >= 1.0) { - return policies::raise_domain_error(function, "q must be greater than 0 and less than 1 but got %1%.", q, pol); - } - return jacobi_theta1tau_imp(z, RealType (-log(q)/constants::pi()), pol, function); + RealType result = 0; + + if (!detail::jacobi_theta_check_q(q, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; + if (abs(z) == 0.0) + return result; + + if (q < exp(-constants::pi())) + return detail::jacobi_theta1_series(z, detail::jacobi_theta_q_power{q}, pol); + + return detail::jacobi_theta1_dispatch(z, detail::jacobi_theta_exponents::from_nome(q), pol); } -// Second Jacobi theta function (Parameterized by tau - assumed imaginary) -// = 2 * SUM exp(i*Pi*Tau*(n+1/2)^2) * cos((2n+1)z) template inline RealType jacobi_theta2tau_imp(RealType z, RealType tau, const Policy& pol, const char *function) { - BOOST_MATH_STD_USING - unsigned n = 0; - RealType eps = policies::get_epsilon(); - RealType q_n = 0, last_q_n, delta, result = 0; - - if (tau <= 0.0) { - return policies::raise_domain_error(function, "tau must be greater than 0 but got %1%.", tau, pol); - } else if (tau < 1.0 && abs(z) == 0.0) { - return jacobi_theta4tau(z, 1/tau, pol) / sqrt(tau); - } else if (tau < 1.0) { // DLMF 20.7.31 - z = fmod(z, constants::two_pi()); - while (z > constants::pi()) { - z -= constants::two_pi(); - } - while (z < -constants::pi()) { - z += constants::two_pi(); - } - - return _IMAGINARY_jacobi_theta4tau(z, RealType(1/tau), pol); - } + RealType result = 0; - do { - last_q_n = q_n; - q_n = exp(-tau * constants::pi() * RealType(n + 0.5)*RealType(n + 0.5)); - delta = q_n * cos(RealType(2*n+1)*z); - result += delta + delta; - n++; - } while (!_jacobi_theta_converged(last_q_n, q_n, eps)); + if (!detail::jacobi_theta_check_tau(tau, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; - return result; + return detail::jacobi_theta2_dispatch(z, detail::jacobi_theta_exponents::from_tau(tau), pol); } -// Second Jacobi theta function, parameterized by q -// = 2 * SUM q^(n+1/2)^2 * cos((2n+1)z) template inline RealType jacobi_theta2_imp(RealType z, RealType q, const Policy& pol, const char *function) { BOOST_MATH_STD_USING - if (q <= 0.0 || q >= 1.0) { - return policies::raise_domain_error(function, "q must be greater than 0 and less than 1 but got %1%.", q, pol); - } - return jacobi_theta2tau_imp(z, RealType (-log(q)/constants::pi()), pol, function); + RealType result = 0; + + if (!detail::jacobi_theta_check_q(q, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; + + if (q < exp(-constants::pi())) + return detail::jacobi_theta2_series(z, detail::jacobi_theta_q_power{q}, pol); + + return detail::jacobi_theta2_dispatch(z, detail::jacobi_theta_exponents::from_nome(q), pol); } -// Third Jacobi theta function, minus one (Parameterized by tau - assumed imaginary) -// This function preserves accuracy for small values of q (i.e. |q| < exp(-Pi) = 0.043) -// For larger values of q, the minus one version usually won't help. -// = 2 * SUM exp(i*Pi*Tau*(n)^2) * cos(2nz) template inline RealType -jacobi_theta3m1tau_imp(RealType z, RealType tau, const Policy& pol) +jacobi_theta3tau_imp(RealType z, RealType tau, const Policy& pol, const char *function) { - BOOST_MATH_STD_USING - - RealType eps = policies::get_epsilon(); - RealType q_n = 0, last_q_n, delta, result = 0; - unsigned n = 1; - - if (tau < 1.0) - return jacobi_theta3tau(z, tau, pol) - RealType(1); + RealType result = 0; - do { - last_q_n = q_n; - q_n = exp(-tau * constants::pi() * RealType(n)*RealType(n)); - delta = q_n * cos(RealType(2*n)*z); - result += delta + delta; - n++; - } while (!_jacobi_theta_converged(last_q_n, q_n, eps)); + if (!detail::jacobi_theta_check_tau(tau, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; - return result; + return detail::jacobi_theta3_dispatch(z, detail::jacobi_theta_exponents::from_tau(tau), pol); } -// Third Jacobi theta function, parameterized by tau -// = 1 + 2 * SUM exp(i*Pi*Tau*(n)^2) * cos(2nz) template inline RealType -jacobi_theta3tau_imp(RealType z, RealType tau, const Policy& pol, const char *function) +jacobi_theta3m1tau_imp(RealType z, RealType tau, const Policy& pol, const char *function) { - BOOST_MATH_STD_USING - if (tau <= 0.0) { - return policies::raise_domain_error(function, "tau must be greater than 0 but got %1%.", tau, pol); - } else if (tau < 1.0 && abs(z) == 0.0) { - return jacobi_theta3tau(z, RealType(1/tau), pol) / sqrt(tau); - } else if (tau < 1.0) { // DLMF 20.7.32 - z = fmod(z, constants::pi()); - while (z > constants::half_pi()) { - z -= constants::pi(); - } - while (z < -constants::half_pi()) { - z += constants::pi(); - } - return _IMAGINARY_jacobi_theta3tau(z, RealType(1/tau), pol); - } - return RealType(1) + jacobi_theta3m1tau_imp(z, tau, pol); + RealType result = 0; + + if (!detail::jacobi_theta_check_tau(tau, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; + + return detail::jacobi_theta3m1_dispatch(z, detail::jacobi_theta_exponents::from_tau(tau), pol); } -// Third Jacobi theta function, minus one (parameterized by q) -// = 2 * SUM q^n^2 * cos(2nz) template inline RealType jacobi_theta3m1_imp(RealType z, RealType q, const Policy& pol, const char *function) { BOOST_MATH_STD_USING - if (q <= 0.0 || q >= 1.0) { - return policies::raise_domain_error(function, "q must be greater than 0 and less than 1 but got %1%.", q, pol); - } - return jacobi_theta3m1tau_imp(z, RealType (-log(q)/constants::pi()), pol); + RealType result = 0; + + if (!detail::jacobi_theta_check_q(q, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; + + if (q < exp(-constants::pi())) + return detail::jacobi_theta3m1_series(z, detail::jacobi_theta_q_power{q}, pol); + + return detail::jacobi_theta3m1_dispatch(z, detail::jacobi_theta_exponents::from_nome(q), pol); } -// Third Jacobi theta function (parameterized by q) -// = 1 + 2 * SUM q^n^2 * cos(2nz) template inline RealType jacobi_theta3_imp(RealType z, RealType q, const Policy& pol, const char *function) { BOOST_MATH_STD_USING - if (q <= 0.0 || q >= 1.0) { - return policies::raise_domain_error(function, "q must be greater than 0 and less than 1 but got %1%.", q, pol); - } - return jacobi_theta3tau_imp(z, RealType (-log(q)/constants::pi()), pol, function); + RealType result = 0; + + if (!detail::jacobi_theta_check_q(q, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; + + if (q < exp(-constants::pi())) + return RealType(1) + detail::jacobi_theta3m1_series(z, detail::jacobi_theta_q_power{q}, pol); + + return detail::jacobi_theta3_dispatch(z, detail::jacobi_theta_exponents::from_nome(q), pol); } -// Fourth Jacobi theta function, minus one (Parameterized by tau) -// This function preserves accuracy for small values of q (i.e. tau > 1) -// = 2 * SUM (-1)^n exp(i*Pi*Tau*(n)^2) * cos(2nz) template inline RealType -jacobi_theta4m1tau_imp(RealType z, RealType tau, const Policy& pol) +jacobi_theta4tau_imp(RealType z, RealType tau, const Policy& pol, const char *function) { - BOOST_MATH_STD_USING - - RealType eps = policies::get_epsilon(); - RealType q_n = 0, last_q_n, delta, result = 0; - unsigned n = 1; - - if (tau < 1.0) - return jacobi_theta4tau(z, tau, pol) - RealType(1); - - do { - last_q_n = q_n; - q_n = exp(-tau * constants::pi() * RealType(n)*RealType(n)); - delta = q_n * cos(RealType(2*n)*z); - if (n%2) - delta = -delta; + RealType result = 0; - result += delta + delta; - n++; - } while (!_jacobi_theta_converged(last_q_n, q_n, eps)); + if (!detail::jacobi_theta_check_tau(tau, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; - return result; + return detail::jacobi_theta4_dispatch(z, detail::jacobi_theta_exponents::from_tau(tau), pol); } -// Fourth Jacobi theta function (Parameterized by tau) -// = 1 + 2 * SUM (-1)^n exp(i*Pi*Tau*(n)^2) * cos(2nz) template inline RealType -jacobi_theta4tau_imp(RealType z, RealType tau, const Policy& pol, const char *function) +jacobi_theta4m1tau_imp(RealType z, RealType tau, const Policy& pol, const char *function) { - BOOST_MATH_STD_USING - if (tau <= 0.0) { - return policies::raise_domain_error(function, "tau must be greater than 0 but got %1%.", tau, pol); - } else if (tau < 1.0 && abs(z) == 0.0) { - return jacobi_theta2tau(z, 1/tau, pol) / sqrt(tau); - } else if (tau < 1.0) { // DLMF 20.7.33 - z = fmod(z, constants::pi()); - while (z > constants::half_pi()) { - z -= constants::pi(); - } - while (z < -constants::half_pi()) { - z += constants::pi(); - } - return _IMAGINARY_jacobi_theta2tau(z, RealType(1/tau), pol); - } + RealType result = 0; + + if (!detail::jacobi_theta_check_tau(tau, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; - return RealType(1) + jacobi_theta4m1tau_imp(z, tau, pol); + return detail::jacobi_theta4m1_dispatch(z, detail::jacobi_theta_exponents::from_tau(tau), pol); } -// Fourth Jacobi theta function, minus one (Parameterized by q) -// This function preserves accuracy for small values of q -// = 2 * SUM q^n^2 * cos(2nz) template inline RealType jacobi_theta4m1_imp(RealType z, RealType q, const Policy& pol, const char *function) { BOOST_MATH_STD_USING - if (q <= 0.0 || q >= 1.0) { - return policies::raise_domain_error(function, "q must be greater than 0 and less than 1 but got %1%.", q, pol); - } - return jacobi_theta4m1tau_imp(z, RealType (-log(q)/constants::pi()), pol); + RealType result = 0; + + if (!detail::jacobi_theta_check_q(q, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; + + if (q < exp(-constants::pi())) + return detail::jacobi_theta4m1_series(z, detail::jacobi_theta_q_power{q}, pol); + + return detail::jacobi_theta4m1_dispatch(z, detail::jacobi_theta_exponents::from_nome(q), pol); } -// Fourth Jacobi theta function, parameterized by q -// = 1 + 2 * SUM q^n^2 * cos(2nz) template inline RealType jacobi_theta4_imp(RealType z, RealType q, const Policy& pol, const char *function) { BOOST_MATH_STD_USING - if (q <= 0.0 || q >= 1.0) { - return policies::raise_domain_error(function, "|q| must be greater than zero and less than 1, but got %1%.", q, pol); - } - return jacobi_theta4tau_imp(z, RealType(-log(q)/constants::pi()), pol, function); + RealType result = 0; + + if (!detail::jacobi_theta_check_q(q, pol, function, &result)) + return result; + if (!detail::jacobi_theta_check_z(z, pol, function, &result)) + return result; + + if (q < exp(-constants::pi())) + return RealType(1) + detail::jacobi_theta4m1_series(z, detail::jacobi_theta_q_power{q}, pol); + + return detail::jacobi_theta4_dispatch(z, detail::jacobi_theta_exponents::from_nome(q), pol); } // Begin public API -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta1tau(T z, U tau, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -559,12 +972,12 @@ inline typename tools::promote_args::type jacobi_theta1tau(T z, U tau, con return policies::checked_narrowing_cast(jacobi_theta1tau_imp(static_cast(z), static_cast(tau), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta1tau(T z, U tau) { return jacobi_theta1tau(z, tau, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta1(T z, U q, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -580,12 +993,12 @@ inline typename tools::promote_args::type jacobi_theta1(T z, U q, const Po return policies::checked_narrowing_cast(jacobi_theta1_imp(static_cast(z), static_cast(q), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta1(T z, U q) { return jacobi_theta1(z, q, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta2tau(T z, U tau, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -601,12 +1014,12 @@ inline typename tools::promote_args::type jacobi_theta2tau(T z, U tau, con return policies::checked_narrowing_cast(jacobi_theta2tau_imp(static_cast(z), static_cast(tau), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta2tau(T z, U tau) { return jacobi_theta2tau(z, tau, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta2(T z, U q, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -622,12 +1035,12 @@ inline typename tools::promote_args::type jacobi_theta2(T z, U q, const Po return policies::checked_narrowing_cast(jacobi_theta2_imp(static_cast(z), static_cast(q), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta2(T z, U q) { return jacobi_theta2(z, q, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3m1tau(T z, U tau, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -641,15 +1054,15 @@ inline typename tools::promote_args::type jacobi_theta3m1tau(T z, U tau, c static const char* function = "boost::math::jacobi_theta3m1tau<%1%>(%1%)"; return policies::checked_narrowing_cast( - jacobi_theta3m1tau_imp(static_cast(z), static_cast(tau), forwarding_policy()), function); + jacobi_theta3m1tau_imp(static_cast(z), static_cast(tau), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3m1tau(T z, U tau) { return jacobi_theta3m1tau(z, tau, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3tau(T z, U tau, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -665,13 +1078,13 @@ inline typename tools::promote_args::type jacobi_theta3tau(T z, U tau, con return policies::checked_narrowing_cast(jacobi_theta3tau_imp(static_cast(z), static_cast(tau), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3tau(T z, U tau) { return jacobi_theta3tau(z, tau, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3m1(T z, U q, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -687,12 +1100,12 @@ inline typename tools::promote_args::type jacobi_theta3m1(T z, U q, const return policies::checked_narrowing_cast(jacobi_theta3m1_imp(static_cast(z), static_cast(q), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3m1(T z, U q) { return jacobi_theta3m1(z, q, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3(T z, U q, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -708,12 +1121,12 @@ inline typename tools::promote_args::type jacobi_theta3(T z, U q, const Po return policies::checked_narrowing_cast(jacobi_theta3_imp(static_cast(z), static_cast(q), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta3(T z, U q) { return jacobi_theta3(z, q, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4m1tau(T z, U tau, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -726,15 +1139,15 @@ inline typename tools::promote_args::type jacobi_theta4m1tau(T z, U tau, c static const char* function = "boost::math::jacobi_theta4m1tau<%1%>(%1%)"; - return policies::checked_narrowing_cast(jacobi_theta4m1tau_imp(static_cast(z), static_cast(tau), forwarding_policy()), function); + return policies::checked_narrowing_cast(jacobi_theta4m1tau_imp(static_cast(z), static_cast(tau), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4m1tau(T z, U tau) { return jacobi_theta4m1tau(z, tau, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4tau(T z, U tau, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -750,12 +1163,12 @@ inline typename tools::promote_args::type jacobi_theta4tau(T z, U tau, con return policies::checked_narrowing_cast(jacobi_theta4tau_imp(static_cast(z), static_cast(tau), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4tau(T z, U tau) { return jacobi_theta4tau(z, tau, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4m1(T z, U q, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -771,12 +1184,12 @@ inline typename tools::promote_args::type jacobi_theta4m1(T z, U q, const return policies::checked_narrowing_cast(jacobi_theta4m1_imp(static_cast(z), static_cast(q), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4m1(T z, U q) { return jacobi_theta4m1(z, q, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4(T z, U q, const Policy&) { BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args::type result_type; @@ -792,11 +1205,11 @@ inline typename tools::promote_args::type jacobi_theta4(T z, U q, const Po return policies::checked_narrowing_cast(jacobi_theta4_imp(static_cast(z), static_cast(q), forwarding_policy(), function), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type jacobi_theta4(T z, U q) { return jacobi_theta4(z, q, policies::policy<>()); } -}} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/jacobi_zeta.hpp b/include/boost/math/special_functions/jacobi_zeta.hpp index 8b6f80912d..8497286d59 100644 --- a/include/boost/math/special_functions/jacobi_zeta.hpp +++ b/include/boost/math/special_functions/jacobi_zeta.hpp @@ -23,7 +23,7 @@ // Elliptic integral the Jacobi Zeta function. -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -32,8 +32,8 @@ template BOOST_MATH_GPU_ENABLED T jacobi_zeta_imp(T phi, T k, const Policy& pol, T kp) { BOOST_MATH_STD_USING - using namespace boost::math::tools; - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::tools; + using namespace BOOST_MATH_NAMESPACE::constants; bool invert = false; if(phi < 0) @@ -49,7 +49,7 @@ BOOST_MATH_GPU_ENABLED T jacobi_zeta_imp(T phi, T k, const Policy& pol, T kp) T one_minus_ks2 = kp + c2 - kp * c2; T k2 = k * k; if(k == 1) - result = sinp * (boost::math::sign)(cosp); // We get here by simplifying JacobiZeta[w, 1] in Mathematica, and the fact that 0 <= phi. + result = sinp * (BOOST_MATH_NAMESPACE::sign)(cosp); // We get here by simplifying JacobiZeta[w, 1] in Mathematica, and the fact that 0 <= phi. else { result = k2 * sinp * cosp * sqrt(one_minus_ks2) * ellint_rj_imp(T(0), kp, T(1), one_minus_ks2, pol) / (3 * ellint_k_imp(k, pol, kp)); @@ -63,7 +63,7 @@ BOOST_MATH_GPU_ENABLED inline T jacobi_zeta_imp(T phi, T k, const Policy& pol) } } // detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type jacobi_zeta(T1 k, T2 phi, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -71,13 +71,13 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type jacobi_ return policies::checked_narrowing_cast(detail::jacobi_zeta_imp(static_cast(phi), static_cast(k), pol), "boost::math::jacobi_zeta<%1%>(%1%,%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type jacobi_zeta(T1 k, T2 phi) { - return boost::math::jacobi_zeta(k, phi, policies::policy<>()); + return BOOST_MATH_NAMESPACE::jacobi_zeta(k, phi, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ELLINT_D_HPP diff --git a/include/boost/math/special_functions/laguerre.hpp b/include/boost/math/special_functions/laguerre.hpp index d747274536..19db853d41 100644 --- a/include/boost/math/special_functions/laguerre.hpp +++ b/include/boost/math/special_functions/laguerre.hpp @@ -14,12 +14,12 @@ #include #include #include +#include -namespace boost{ -namespace math{ +BOOST_MATH_NAMESPACE_BEGIN // Recurrence relation for Laguerre polynomials: -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type laguerre_next(unsigned n, T1 x, T2 Ln, T3 Lnm1) { @@ -29,7 +29,12 @@ inline typename tools::promote_args::type namespace detail{ -// Implement Laguerre polynomials via recurrence: +// +// Implement Laguerre polynomials via recurrence. On its own the recurrence loses up to n^1.5 epsilon or so +// where L_n oscillates, as both of its solutions are of similar size there and the rounding errors of each step +// accumulate. So we find the rounding error of each step almost exactly, and carry it forward with the same +// recurrence: the result is then within the conditioning of L_n. +// template T laguerre_imp(unsigned n, T x) { @@ -39,15 +44,35 @@ T laguerre_imp(unsigned n, T x) if(n == 0) return p0; - unsigned c = 1; + // Errors in p0 and p1, starting with that of 1 - x: + T e0 = 0; + T e1 = two_sum_error(T(1), T(-x), p1); + detail::two_product product; - while(c < n) + for(unsigned c = 1; c < n; ++c) { - std::swap(p0, p1); - p1 = laguerre_next(c, x, p0, p1); - ++c; + // a + ea = 2c + 1 - x exactly: + T a = (2 * c + 1) - x; + T ea = two_sum_error(T(2 * c + 1), T(-x), a); + // s1 + r1 = a p1 and s2 + r2 = c p0 exactly: + T s1, r1, s2, r2; + product(a, p1, s1, r1); + product(T(c), p0, s2, r2); + // d + ed = s1 - s2 exactly: + T d = s1 - s2; + T ed = two_sum_error(s1, T(-s2), d); + T p2 = d / (c + 1); + // d - (c + 1) p2, where d - q is exact as q is so close to d: + T q, rq; + product(T(c + 1), p2, q, rq); + T rd = (d - q) - rq; + T e2 = (a * e1 - c * e0 + rd + ed + r1 - r2 + ea * p1) / (c + 1); + p0 = p1; + p1 = p2; + e0 = e1; + e1 = e2; } - return p1; + return p1 + e1; } template @@ -63,12 +88,12 @@ template inline typename tools::promote_args::type laguerre(unsigned n, unsigned m, T x, const std::false_type&) { - return boost::math::laguerre(n, m, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::laguerre(n, m, x, policies::policy<>()); } } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type laguerre(unsigned n, T x) { @@ -76,7 +101,7 @@ inline typename tools::promote_args::type } // Recurrence for associated polynomials: -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type laguerre_next(unsigned n, unsigned l, T1 x, T2 Pl, T3 Plm1) { @@ -91,7 +116,7 @@ T laguerre_imp(unsigned n, unsigned m, T x, const Policy& pol) { // Special cases: if(m == 0) - return boost::math::laguerre(n, x, pol); + return BOOST_MATH_NAMESPACE::laguerre(n, x, pol); T p0 = 1; @@ -113,7 +138,7 @@ T laguerre_imp(unsigned n, unsigned m, T x, const Policy& pol) } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type laguerre(unsigned n, unsigned m, T x, const Policy& pol) { @@ -122,7 +147,7 @@ inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::laguerre_imp(n, m, static_cast(x), pol), "boost::math::laguerre<%1%>(unsigned, unsigned, %1%)"); } -template +BOOST_MATH_EXPORT template inline typename laguerre_result::type laguerre(unsigned n, T1 m, T2 x) { @@ -130,8 +155,7 @@ inline typename laguerre_result::type return detail::laguerre(n, m, x, tag_type()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_LAGUERRE_HPP diff --git a/include/boost/math/special_functions/lambert_w.hpp b/include/boost/math/special_functions/lambert_w.hpp index 671432c679..b73f94f85f 100644 --- a/include/boost/math/special_functions/lambert_w.hpp +++ b/include/boost/math/special_functions/lambert_w.hpp @@ -68,10 +68,12 @@ BOOST_MATH_INSTRUMENT_LAMBERT_W_SMALL_Z_SERIES_ITERATIONS // Show evaluation of #include #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif // Needed for testing and diagnostics only. //#include @@ -94,8 +96,7 @@ using lookup_t = double; // Type for lookup table (double or float, or even long #pragma GCC system_header #endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace lambert_w_detail { //! \brief Applies a single Halley step to make a better estimate of Lambert W. @@ -129,7 +130,7 @@ template inline T lambert_w_halley_iterate(T w_est, const T z) { BOOST_MATH_STD_USING - static const T max_diff = boost::math::tools::root_epsilon() * fabs(w_est); + static const T max_diff = BOOST_MATH_NAMESPACE::tools::root_epsilon() * fabs(w_est); T w_new = lambert_w_halley_step(w_est, z); T diff = fabs(w_est - w_new); @@ -204,6 +205,7 @@ inline double must_reduce_to_double(const T& z, const std::false_type&) #endif #else + static_cast(z); static_assert(sizeof(T) == 0, "Unsupported in standalone mode: don't know how to cast your number type to a double."); return 0.0; #endif @@ -234,7 +236,7 @@ inline T schroeder_update(const T w, const T y) BOOST_MATH_STD_USING // Aid argument dependent lookup of abs. #ifdef BOOST_MATH_INSTRUMENT_LAMBERT_W_SCHROEDER std::streamsize saved_precision = std::cout.precision(std::numeric_limits::max_digits10); - using boost::math::float_distance; + using BOOST_MATH_NAMESPACE::float_distance; T fd = float_distance(w, y); std::cout << "Schroder "; if (abs(fd) < 214748000.) @@ -494,19 +496,11 @@ template T lambert_w0_small_z(T x, const Policy& pol) { //std::numeric_limits::max_digits10 == 36 ? 3 : // 128-bit long double. using tag_type = std::integral_constant::is_specialized == 0 ? 5 : -#ifndef BOOST_NO_CXX11_NUMERIC_LIMITS + std::numeric_limits::is_specialized == 0 ? 5 : std::numeric_limits::max_digits10 <= 9 ? 0 : // for float 32-bit. std::numeric_limits::max_digits10 <= 17 ? 1 : // for double 64-bit. std::numeric_limits::max_digits10 <= 22 ? 2 : // for 80-bit double extended. std::numeric_limits::max_digits10 < 37 ? 4 // for both 128-bit long double (3) and 128-bit quad suffix Q type (4). -#else - std::numeric_limits::radix != 2 ? 5 : - std::numeric_limits::digits <= 24 ? 0 : // for float 32-bit. - std::numeric_limits::digits <= 53 ? 1 : // for double 64-bit. - std::numeric_limits::digits <= 64 ? 2 : // for 80-bit double extended. - std::numeric_limits::digits <= 113 ? 4 // for both 128-bit long double (3) and 128-bit quad suffix Q type (4). -#endif : 5>; // All Generic multiprecision types. // std::cout << "\ntag type = " << tag_type << std::endl; // error C2275: 'tag_type': illegal use of this type as an expression. return lambert_w0_small_z(x, pol, tag_type()); @@ -778,7 +772,7 @@ struct lambert_w0_small_z_series_term { using result_type = T; //! \param _z Lambert W argument z. - //! \param -term -pow<18>(z) / 6402373705728000uLL + //! \param _term -pow<18>(z) / 6402373705728000uLL //! \param _k number of terms == initially 18 // Note *after* evaluating N terms, its internal state has k = N and term = (-1)^N z^N. @@ -880,9 +874,9 @@ inline T lambert_w0_small_z(T z, const Policy& pol, std::integral_constant::max_digits10); @@ -973,7 +967,7 @@ template inline T do_get_near_singularity_param(T z) { BOOST_MATH_STD_USING - const T p2 = 2 * (boost::math::constants::e() * z + 1); + const T p2 = 2 * (BOOST_MATH_NAMESPACE::constants::e() * z + 1); const T p = sqrt(p2); return p; } @@ -1019,7 +1013,7 @@ T lambert_w_positive_rational_float(T z) 1.690949264e+00f, }; // LCOV_EXCL_STOP - return z * (Y + boost::math::tools::evaluate_polynomial(P, z) / boost::math::tools::evaluate_polynomial(Q, z)); + return z * (Y + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, z) / BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, z)); } else { // 0.5 < z < 2 @@ -1039,7 +1033,7 @@ T lambert_w_positive_rational_float(T z) 2.407221031e-01f, }; // LCOV_EXCL_STOP - return z * (Y + boost::math::tools::evaluate_rational(P, Q, z)); + return z * (Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, z)); } } else if (z < 6) @@ -1061,7 +1055,7 @@ T lambert_w_positive_rational_float(T z) 5.477869455e-03f, }; // LCOV_EXCL_STOP - return Y + boost::math::tools::evaluate_rational(P, Q, z); + return Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, z); } else if (z < 18) { @@ -1082,7 +1076,7 @@ T lambert_w_positive_rational_float(T z) 4.076716763e-04f, }; // LCOV_EXCL_STOP - return Y + boost::math::tools::evaluate_rational(P, Q, z); + return Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, z); } else if (z < T(9897.12905874)) // 2.8 < log(z) < 9.2 { @@ -1104,7 +1098,7 @@ T lambert_w_positive_rational_float(T z) }; // LCOV_EXCL_STOP T log_w = log(z); - return log_w + Y + boost::math::tools::evaluate_polynomial(P, log_w) / boost::math::tools::evaluate_polynomial(Q, log_w); + return log_w + Y + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, log_w) / BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, log_w); } else if (z < T(7.896296e+13)) // 9.2 < log(z) <= 32 { @@ -1126,7 +1120,7 @@ T lambert_w_positive_rational_float(T z) }; // LCOV_EXCL_STOP T log_w = log(z); - return log_w + Y + boost::math::tools::evaluate_polynomial(P, log_w) / boost::math::tools::evaluate_polynomial(Q, log_w); + return log_w + Y + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, log_w) / BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, log_w); } // Max error in interpolated form: 1.491e-08 @@ -1147,7 +1141,7 @@ T lambert_w_positive_rational_float(T z) }; // LCOV_EXCL_STOP T log_w = log(z); - return log_w + Y + boost::math::tools::evaluate_polynomial(P, log_w) / boost::math::tools::evaluate_polynomial(Q, log_w); + return log_w + Y + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, log_w) / BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, log_w); } @@ -1176,7 +1170,7 @@ T lambert_w_negative_rational_float(T z, const Policy& pol) 3.501498501e+00f, }; // LCOV_EXCL_STOP - return z * (Y + boost::math::tools::evaluate_rational(P, Q, z)); + return z * (Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, z)); } else { @@ -1204,7 +1198,7 @@ T lambert_w_negative_rational_float(T z, const Policy& pol) }; // LCOV_EXCL_STOP T d = z + 0.367879441171442321595523770161460867445811f; - return -d / (Y + boost::math::tools::evaluate_polynomial(P, d) / boost::math::tools::evaluate_polynomial(Q, d)); + return -d / (Y + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, d) / BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, d)); } return lambert_w_singularity_series(get_near_singularity_param(z, pol)); @@ -1217,13 +1211,13 @@ inline T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant(function, "Expected a value > -e^-1 (-0.367879...) but got %1%.", z, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Expected a value > -e^-1 (-0.367879...) but got %1%.", z, pol); } - if ((boost::math::isinf)(z)) + if ((BOOST_MATH_NAMESPACE::isinf)(z)) { - return boost::math::policies::raise_overflow_error(function, "Expected a finite value but got %1%.", z, pol); + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, "Expected a finite value but got %1%.", z, pol); } if (z >= T(0.05)) // Fukushima switch point. @@ -1234,7 +1228,7 @@ inline T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant(function, "Expected z >= -e^-1 (-0.367879...) but got %1%.", z, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Expected z >= -e^-1 (-0.367879...) but got %1%.", z, pol); return -1; } @@ -1271,7 +1265,7 @@ T lambert_w_positive_rational_double(T z) 2.91327346750475362e-01 }; // LCOV_EXCL_STOP - return z * (offset + boost::math::tools::evaluate_polynomial(P, z) / boost::math::tools::evaluate_polynomial(Q, z)); + return z * (offset + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, z) / BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, z)); } else { @@ -1298,7 +1292,7 @@ T lambert_w_positive_rational_double(T z) 2.21610620995418981e-01, 5.70597669908194213e-03 };// LCOV_EXCL_STOP - return z * (offset + boost::math::tools::evaluate_rational(P, Q, z)); + return z * (offset + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, z)); } } else if (z < 6) @@ -1328,7 +1322,7 @@ T lambert_w_positive_rational_double(T z) 4.43611344705509378e-06, }; // LCOV_EXCL_STOP - return Y + boost::math::tools::evaluate_rational(P, Q, z); + return Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, z); } else if (z < 18) { @@ -1360,7 +1354,7 @@ T lambert_w_positive_rational_double(T z) 8.17517283816615732e-10 }; // LCOV_EXCL_STOP - return offset + boost::math::tools::evaluate_rational(P, Q, z); + return offset + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, z); } else if (z < 9897.12905874) // 2.8 < log(z) < 9.2 { @@ -1391,7 +1385,7 @@ T lambert_w_positive_rational_double(T z) }; // LCOV_EXCL_STOP T log_w = log(z); - return log_w + Y + boost::math::tools::evaluate_rational(P, Q, log_w); + return log_w + Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, log_w); } else if (z < 7.896296e+13) // 9.2 < log(z) <= 32 { @@ -1422,7 +1416,7 @@ T lambert_w_positive_rational_double(T z) }; // LCOV_EXCL_STOP T log_w = log(z); - return log_w + Y + boost::math::tools::evaluate_rational(P, Q, log_w); + return log_w + Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, log_w); } else if (z < 2.6881171e+43) // 32 < log(z) < 100 { @@ -1453,7 +1447,7 @@ T lambert_w_positive_rational_double(T z) }; // LCOV_EXCL_STOP T log_w = log(z); - return log_w + Y + boost::math::tools::evaluate_rational(P, Q, log_w); + return log_w + Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, log_w); } else // 100 < log(z) < 710 { @@ -1488,7 +1482,7 @@ T lambert_w_positive_rational_double(T z) }; // LCOV_EXCL_STOP T log_w = log(z); - return log_w + Y + boost::math::tools::evaluate_rational(P, Q, log_w); + return log_w + Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, log_w); } } @@ -1523,7 +1517,7 @@ T lambert_w_negative_rational_double(T z, const Policy& pol) 2.11640324843601588e+00, }; // LCOV_EXCL_STOP - return z * (Y + boost::math::tools::evaluate_rational(P, Q, z)); + return z * (Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, z)); } else { @@ -1558,7 +1552,7 @@ T lambert_w_negative_rational_double(T z, const Policy& pol) 4.10677610657724330e+00, }; // LCOV_EXCL_STOP - return z * (Y + boost::math::tools::evaluate_rational(P, Q, z)); + return z * (Y + BOOST_MATH_NAMESPACE::tools::evaluate_rational(P, Q, z)); } else if (z > -0.3178794411714423215955237) { @@ -1588,7 +1582,7 @@ T lambert_w_negative_rational_double(T z, const Policy& pol) }; // LCOV_EXCL_STOP T d = z + 0.367879441171442321595523770161460867445811; - return -d / (Y + boost::math::tools::evaluate_polynomial(P, d) / boost::math::tools::evaluate_polynomial(Q, d)); + return -d / (Y + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, d) / BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, d)); } else if (z > -0.3578794411714423215955237701) { @@ -1619,12 +1613,12 @@ T lambert_w_negative_rational_double(T z, const Policy& pol) }; // LCOV_EXCL_STOP T d = z + 0.36787944117144232159552377016146086744581113103176804; - return -d / (Y + boost::math::tools::evaluate_polynomial(P, d) / boost::math::tools::evaluate_polynomial(Q, d)); + return -d / (Y + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P, d) / BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(Q, d)); } else { // z is very close (within 0.01) of the singularity at -e^-1, // so use a series expansion from R. M. Corless et al. - const T p2 = 2 * (boost::math::constants::e() * z + 1); + const T p2 = 2 * (BOOST_MATH_NAMESPACE::constants::e() * z + 1); const T p = sqrt(p2); return lambert_w_detail::lambert_w_singularity_series(p); } @@ -1644,13 +1638,13 @@ inline T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant(function, "Expected a value > -e^-1 (-0.367879...) but got %1%.", z, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Expected a value > -e^-1 (-0.367879...) but got %1%.", z, pol); } - if ((boost::math::isinf)(z)) + if ((BOOST_MATH_NAMESPACE::isinf)(z)) { - return boost::math::policies::raise_overflow_error(function, "Expected a finite value but got %1%.", z, pol); + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, "Expected a finite value but got %1%.", z, pol); } if (z >= 0.05) @@ -1661,7 +1655,7 @@ inline T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant(function, "Expected z >= -e^-1 (-0.367879...) but got %1%.", z, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Expected z >= -e^-1 (-0.367879...) but got %1%.", z, pol); } return -1; } @@ -1682,9 +1676,9 @@ inline T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant(function, "Expected z >= -e^-1 (-0.367879...) but got %1%.", z, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Expected z >= -e^-1 (-0.367879...) but got %1%.", z, pol); } if (fabs(z) <= 0.05f) { @@ -1693,7 +1687,7 @@ inline T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant (std::numeric_limits::max)()) { - if ((boost::math::isinf)(z)) + if ((BOOST_MATH_NAMESPACE::isinf)(z)) { return policies::raise_overflow_error(function, nullptr, pol); // Or might return infinity if available else max_value, @@ -1710,17 +1704,17 @@ inline T lambert_w0_imp(T z, const Policy& pol, const std::integral_constant()) + if (z <= -BOOST_MATH_NAMESPACE::constants::exp_minus_one()) { - if (z == -boost::math::constants::exp_minus_one()) + if (z == -BOOST_MATH_NAMESPACE::constants::exp_minus_one()) { // Exactly at the branch point singularity. return -1; } - return boost::math::policies::raise_domain_error(function, "Expected z >= -e^-1 (-0.367879...) but got %1%.", z, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Expected z >= -e^-1 (-0.367879...) but got %1%.", z, pol); } // z is very close (within 0.01) of the branch singularity at -e^-1 // so use a series approximation proposed by Corless et al. - const T p2 = 2 * (boost::math::constants::e() * z + 1); + const T p2 = 2 * (BOOST_MATH_NAMESPACE::constants::e() * z + 1); const T p = sqrt(p2); T w = lambert_w_detail::lambert_w_singularity_series(p); return lambert_w_halley_iterate(w, z); @@ -1770,12 +1764,12 @@ T lambert_wm1_imp(const T z, const Policy& pol) const char* function = "boost::math::lambert_wm1()"; // Used for error messages. // Check for edge and corner cases first: - if ((boost::math::isnan)(z)) + if ((BOOST_MATH_NAMESPACE::isnan)(z)) { return policies::raise_domain_error(function, "Argument z is NaN!", z, pol); } // isnan - if ((boost::math::isinf)(z)) + if ((BOOST_MATH_NAMESPACE::isinf)(z)) { return policies::raise_domain_error(function, "Argument z is infinite!", z, pol); } // isinf @@ -1784,9 +1778,9 @@ T lambert_wm1_imp(const T z, const Policy& pol) { // z is exactly zero so return -std::numeric_limits::infinity(); return -policies::raise_overflow_error(function, nullptr, z, pol); } - if (boost::math::detail::has_denorm_now()) + if (BOOST_MATH_NAMESPACE::detail::has_denorm_now()) { // All real types except arbitrary precision. - if (!(boost::math::isnormal)(z)) + if (!(BOOST_MATH_NAMESPACE::isnormal)(z)) { // Almost zero - might also just return infinity like z == 0 or max_value? return -policies::raise_overflow_error(function, "Argument z = %1% is denormalized! (must be z > (std::numeric_limits::min)() or z == 0)", z, pol); } @@ -1796,18 +1790,18 @@ T lambert_wm1_imp(const T z, const Policy& pol) { // return policies::raise_domain_error(function, "Argument z = %1% is out of range (z <= 0) for Lambert W-1 branch! (Try Lambert W0 branch?)", z, pol); } - if (z == -boost::math::constants::exp_minus_one()) // == singularity/branch point z = -exp(-1) = -0.36787944. + if (z == -BOOST_MATH_NAMESPACE::constants::exp_minus_one()) // == singularity/branch point z = -exp(-1) = -0.36787944. { // At singularity, so return exactly -1. return -static_cast(1); } // z is too negative for the W-1 (or W0) branch. - if (z < -boost::math::constants::exp_minus_one()) // > singularity/branch point z = -exp(-1) = -0.36787944. + if (z < -BOOST_MATH_NAMESPACE::constants::exp_minus_one()) // > singularity/branch point z = -exp(-1) = -0.36787944. { return policies::raise_domain_error(function, "Argument z = %1% is out of range (require -exp(-1) = -0.36787944... < z <= 0) for Lambert W-1 (or W0) branch!", z, pol); } if (z < static_cast(-0.35)) { // Close to singularity/branch point z = -0.3678794411714423215955237701614608727 but on W-1 branch. - const T p2 = 2 * (boost::math::constants::e() * z + 1); + const T p2 = 2 * (BOOST_MATH_NAMESPACE::constants::e() * z + 1); // Commented out, requires z = -1 / 2e which is greater than -0.35 so this whole branch is not taken. //if (p2 == 0) //{ // At the singularity at branch point. @@ -1815,7 +1809,7 @@ T lambert_wm1_imp(const T z, const Policy& pol) // } BOOST_MATH_ASSERT(p2 > 0); T w_series = lambert_w_singularity_series(T(-sqrt(p2))); - if (boost::math::tools::digits() > 53) + if (BOOST_MATH_NAMESPACE::tools::digits() > 53) { // Multiprecision, so try a Halley refinement. w_series = lambert_w_detail::lambert_w_halley_iterate(w_series, z); #ifdef BOOST_MATH_INSTRUMENT_LAMBERT_WM1_NOT_BUILTIN @@ -1888,15 +1882,15 @@ T lambert_wm1_imp(const T z, const Policy& pol) } // Z too small so use approximation and Halley. // Else Use a lookup table to find the nearest integer part of Lambert W-1 as starting point for Bisection. - if (boost::math::tools::digits() > 53) + if (BOOST_MATH_NAMESPACE::tools::digits() > 53) { // T is more precise than 64-bit double (or long double, or ?), // so compute an approximate value using only one Schroeder refinement, // (avoiding any double-precision Halley refinement from policy double_digits2<50> 53 - 3 = 50 // because are next going to use Halley refinement at full/high precision using this as an approximation). - using boost::math::policies::precision; - using boost::math::policies::digits10; - using boost::math::policies::digits2; - using boost::math::policies::policy; + using BOOST_MATH_NAMESPACE::policies::precision; + using BOOST_MATH_NAMESPACE::policies::digits10; + using BOOST_MATH_NAMESPACE::policies::digits2; + using BOOST_MATH_NAMESPACE::policies::policy; // Compute a 50-bit precision approximate W0 in a double (no Halley refinement). T double_approx(static_cast(lambert_wm1_imp(must_reduce_to_double(z, std::is_constructible()), policy>()))); #ifdef BOOST_MATH_INSTRUMENT_LAMBERT_WM1_NOT_BUILTIN @@ -1916,7 +1910,7 @@ T lambert_wm1_imp(const T z, const Policy& pol) } // digits > 53 - higher precision than double. else // T is double or less precision. { // Use a lookup table to find the nearest integer part of Lambert W as starting point for Bisection. - using namespace boost::math::lambert_w_detail::lambert_w_lookup; + using namespace BOOST_MATH_NAMESPACE::lambert_w_detail::lambert_w_lookup; // Bracketing sequence n = (2, 4, 8, 16, 32, 64) for W-1 branch. (0 is -infinity) // Since z is probably quite small, start with lowest n (=2). int n = 2; @@ -2022,9 +2016,9 @@ T lambert_wm1_imp(const T z, const Policy& pol) ///////////////////////////// User Lambert w functions. ////////////////////////////// //! Lambert W0 using User-defined policy. - template + BOOST_MATH_EXPORT template inline - typename boost::math::tools::promote_args::type + typename BOOST_MATH_NAMESPACE::tools::promote_args::type lambert_w0(T z, const Policy& pol) { // Promote integer or expression template arguments to double, @@ -2046,7 +2040,7 @@ T lambert_wm1_imp(const T z, const Policy& pol) } // lambert_w0(T z, const Policy& pol) //! Lambert W0 using default policy. - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type lambert_w0(T z) @@ -2071,7 +2065,7 @@ T lambert_wm1_imp(const T z, const Policy& pol) //! W-1 branch (-max(z) < z <= -1/e). //! Lambert W-1 using User-defined policy. - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type lambert_wm1(T z, const Policy& pol) @@ -2083,7 +2077,7 @@ T lambert_wm1_imp(const T z, const Policy& pol) } //! Lambert W-1 using default policy. - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type lambert_wm1(T z) @@ -2106,9 +2100,9 @@ T lambert_wm1_imp(const T z, const Policy& pol) } // This is the sensible choice if we regard the Lambert-W function as complex analytic. // Of course on the real line, it's just undefined. - if (z == -boost::math::constants::exp_minus_one()) + if (z == -BOOST_MATH_NAMESPACE::constants::exp_minus_one()) { - return boost::math::policies::raise_overflow_error("lambert_w0_prime", nullptr, z, pol); + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error("lambert_w0_prime", nullptr, z, pol); } // if z < -1/e, we'll let lambert_w0 do the error handling: result_type w = lambert_w0(result_type(z), pol); @@ -2123,7 +2117,7 @@ T lambert_wm1_imp(const T z, const Policy& pol) } // lambert_w0_prime(T z) } // First derivative of Lambert W0 and W-1. - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type lambert_w0_prime(T z, const Policy& pol) { @@ -2131,14 +2125,14 @@ T lambert_wm1_imp(const T z, const Policy& pol) return lambert_w_detail::lambert_w0_prime(static_cast(z), pol); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type lambert_w0_prime(T z) { return lambert_w0_prime(z, policies::policy<>()); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type lambert_wm1_prime(T z, const Policy& pol) { @@ -2149,23 +2143,23 @@ T lambert_wm1_imp(const T z, const Policy& pol) // return static_cast(1); //} //if (z == - boost::math::constants::exp_minus_one()) - if (z == 0 || z == - boost::math::constants::exp_minus_one()) + if (z == 0 || z == - BOOST_MATH_NAMESPACE::constants::exp_minus_one()) { - return -boost::math::policies::raise_overflow_error("lambert_wm1_prime", nullptr, z, pol); + return -BOOST_MATH_NAMESPACE::policies::raise_overflow_error("lambert_wm1_prime", nullptr, z, pol); } result_type w = lambert_wm1(z, pol); return w/(z*(1+w)); } // lambert_wm1_prime(T z) - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type lambert_wm1_prime(T z) { return lambert_wm1_prime(z, policies::policy<>()); } -}} //boost::math namespaces +BOOST_MATH_NAMESPACE_END #endif // #ifdef BOOST_MATH_SF_LAMBERT_W_HPP diff --git a/include/boost/math/special_functions/lanczos.hpp b/include/boost/math/special_functions/lanczos.hpp index 409e14c5e1..03f96348f9 100644 --- a/include/boost/math/special_functions/lanczos.hpp +++ b/include/boost/math/special_functions/lanczos.hpp @@ -19,8 +19,10 @@ #ifndef BOOST_MATH_HAS_NVRTC #include +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif #if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128) // @@ -32,7 +34,7 @@ #pragma GCC system_header #endif -namespace boost{ namespace math{ namespace lanczos{ +BOOST_MATH_NAMESPACE_BEGIN namespace lanczos{ // // Individual lanczos approximations start here. @@ -63,7 +65,7 @@ BOOST_MATH_GPU_ENABLED inline double lanczos_g_near_1_and_2(const L&) // Max experimental error (with arbitrary precision arithmetic) 9.516e-12 // Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006 // -struct lanczos6 : public boost::math::integral_constant +struct lanczos6 : public BOOST_MATH_NAMESPACE::integral_constant { // // Produces slightly better than float precision when evaluated at @@ -81,16 +83,16 @@ struct lanczos6 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 35, 63.99951844938187085666201263218840287667)), static_cast(BOOST_MATH_BIG_CONSTANT(T, 35, 2.506628274631006311133031631822390264407)) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint16_t) denom[6] = { - static_cast(0u), - static_cast(24u), - static_cast(50u), - static_cast(35u), - static_cast(10u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint16_t) denom[6] = { + static_cast(0u), + static_cast(24u), + static_cast(50u), + static_cast(35u), + static_cast(10u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -105,16 +107,16 @@ struct lanczos6 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 35, 0.2412010548258800231126240760264822486599)), static_cast(BOOST_MATH_BIG_CONSTANT(T, 35, 0.009446967704539249494420221613134244048319)) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint16_t) denom[6] = { - static_cast(0u), - static_cast(24u), - static_cast(50u), - static_cast(35u), - static_cast(10u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint16_t) denom[6] = { + static_cast(0u), + static_cast(24u), + static_cast(50u), + static_cast(35u), + static_cast(10u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -167,7 +169,7 @@ struct lanczos6 : public boost::math::integral_constant // Max experimental error (with arbitrary precision arithmetic) 2.16676e-19 // Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006 // -struct lanczos11 : public boost::math::integral_constant +struct lanczos11 : public BOOST_MATH_NAMESPACE::integral_constant { // // Produces slightly better than double precision when evaluated at @@ -190,21 +192,21 @@ struct lanczos11 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 60, 261.6140441641668190791708576058805625502)), static_cast(BOOST_MATH_BIG_CONSTANT(T, 60, 2.506628274631000502415573855452633787834)) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint32_t) denom[11] = { - static_cast(0u), - static_cast(362880u), - static_cast(1026576u), - static_cast(1172700u), - static_cast(723680u), - static_cast(269325u), - static_cast(63273u), - static_cast(9450u), - static_cast(870u), - static_cast(45u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint32_t) denom[11] = { + static_cast(0u), + static_cast(362880u), + static_cast(1026576u), + static_cast(1172700u), + static_cast(723680u), + static_cast(269325u), + static_cast(63273u), + static_cast(9450u), + static_cast(870u), + static_cast(45u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -224,21 +226,21 @@ struct lanczos11 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 60, 0.004826466289237661857584712046231435101741)), static_cast(BOOST_MATH_BIG_CONSTANT(T, 60, 0.4624429436045378766270459638520555557321e-4)) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint32_t) denom[11] = { - static_cast(0u), - static_cast(362880u), - static_cast(1026576u), - static_cast(1172700u), - static_cast(723680u), - static_cast(269325u), - static_cast(63273u), - static_cast(9450u), - static_cast(870u), - static_cast(45u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint32_t) denom[11] = { + static_cast(0u), + static_cast(362880u), + static_cast(1026576u), + static_cast(1172700u), + static_cast(723680u), + static_cast(269325u), + static_cast(63273u), + static_cast(9450u), + static_cast(870u), + static_cast(45u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -301,7 +303,7 @@ struct lanczos11 : public boost::math::integral_constant // Max experimental error (with arbitrary precision arithmetic) 9.2213e-23 // Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006 // -struct lanczos13 : public boost::math::integral_constant +struct lanczos13 : public BOOST_MATH_NAMESPACE::integral_constant { // // Produces slightly better than extended-double precision when evaluated at @@ -326,23 +328,23 @@ struct lanczos13 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 72, 381.8801248632926870394389468349331394196)), static_cast(BOOST_MATH_BIG_CONSTANT(T, 72, 2.506628274631000502415763426076722427007)) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint32_t) denom[13] = { - static_cast(0u), - static_cast(39916800u), - static_cast(120543840u), - static_cast(150917976u), - static_cast(105258076u), - static_cast(45995730u), - static_cast(13339535u), - static_cast(2637558u), - static_cast(357423u), - static_cast(32670u), - static_cast(1925u), - static_cast(66u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint32_t) denom[13] = { + static_cast(0u), + static_cast(39916800u), + static_cast(120543840u), + static_cast(150917976u), + static_cast(105258076u), + static_cast(45995730u), + static_cast(13339535u), + static_cast(2637558u), + static_cast(357423u), + static_cast(32670u), + static_cast(1925u), + static_cast(66u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -364,23 +366,23 @@ struct lanczos13 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 72, 0.0007469903808915448316510079585999893674101)), static_cast(BOOST_MATH_BIG_CONSTANT(T, 72, 0.4903180573459871862552197089738373164184e-5)) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint32_t) denom[13] = { - static_cast(0u), - static_cast(39916800u), - static_cast(120543840u), - static_cast(150917976u), - static_cast(105258076u), - static_cast(45995730u), - static_cast(13339535u), - static_cast(2637558u), - static_cast(357423u), - static_cast(32670u), - static_cast(1925u), - static_cast(66u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint32_t) denom[13] = { + static_cast(0u), + static_cast(39916800u), + static_cast(120543840u), + static_cast(150917976u), + static_cast(105258076u), + static_cast(45995730u), + static_cast(13339535u), + static_cast(2637558u), + static_cast(357423u), + static_cast(32670u), + static_cast(1925u), + static_cast(66u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -447,7 +449,7 @@ struct lanczos13 : public boost::math::integral_constant // Max experimental error (with arbitrary precision arithmetic) 8.111667e-8 // Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006 // -struct lanczos6m24 : public boost::math::integral_constant +struct lanczos6m24 : public BOOST_MATH_NAMESPACE::integral_constant { // // Use for float precision, when evaluated as a float: @@ -464,16 +466,16 @@ struct lanczos6m24 : public boost::math::integral_constant static_cast(27.5192015197455403062503721613097825345L), static_cast(2.50662858515256974113978724717473206342L) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint16_t) denom[6] = { - static_cast(0u), - static_cast(24u), - static_cast(50u), - static_cast(35u), - static_cast(10u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint16_t) denom[6] = { + static_cast(0u), + static_cast(24u), + static_cast(50u), + static_cast(35u), + static_cast(10u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -488,16 +490,16 @@ struct lanczos6m24 : public boost::math::integral_constant static_cast(6.595765571169314946316366571954421695196L), static_cast(0.6007854010515290065101128585795542383721L) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint16_t) denom[6] = { - static_cast(0u), - static_cast(24u), - static_cast(50u), - static_cast(35u), - static_cast(10u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint16_t) denom[6] = { + static_cast(0u), + static_cast(24u), + static_cast(50u), + static_cast(35u), + static_cast(10u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -550,7 +552,7 @@ struct lanczos6m24 : public boost::math::integral_constant // Max experimental error (with arbitrary precision arithmetic) 1.196214e-17 // Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006 // -struct lanczos13m53 : public boost::math::integral_constant +struct lanczos13m53 : public BOOST_MATH_NAMESPACE::integral_constant { // // Use for double precision, when evaluated as a double: @@ -574,23 +576,23 @@ struct lanczos13m53 : public boost::math::integral_constant static_cast(210.8242777515793458725097339207133627117L), static_cast(2.506628274631000270164908177133837338626L) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint32_t) denom[13] = { - static_cast(0u), - static_cast(39916800u), - static_cast(120543840u), - static_cast(150917976u), - static_cast(105258076u), - static_cast(45995730u), - static_cast(13339535u), - static_cast(2637558u), - static_cast(357423u), - static_cast(32670u), - static_cast(1925u), - static_cast(66u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint32_t) denom[13] = { + static_cast(0u), + static_cast(39916800u), + static_cast(120543840u), + static_cast(150917976u), + static_cast(105258076u), + static_cast(45995730u), + static_cast(13339535u), + static_cast(2637558u), + static_cast(357423u), + static_cast(32670u), + static_cast(1925u), + static_cast(66u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -612,23 +614,23 @@ struct lanczos13m53 : public boost::math::integral_constant static_cast(0.5098416655656676188125178644804694509993L), static_cast(0.006061842346248906525783753964555936883222L) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint32_t) denom[13] = { - static_cast(0u), - static_cast(39916800u), - static_cast(120543840u), - static_cast(150917976u), - static_cast(105258076u), - static_cast(45995730u), - static_cast(13339535u), - static_cast(2637558u), - static_cast(357423u), - static_cast(32670u), - static_cast(1925u), - static_cast(66u), - static_cast(1u) + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint32_t) denom[13] = { + static_cast(0u), + static_cast(39916800u), + static_cast(120543840u), + static_cast(150917976u), + static_cast(105258076u), + static_cast(45995730u), + static_cast(13339535u), + static_cast(2637558u), + static_cast(357423u), + static_cast(32670u), + static_cast(1925u), + static_cast(66u), + static_cast(1u) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -695,7 +697,7 @@ struct lanczos13m53 : public boost::math::integral_constant // Max experimental error (with arbitrary precision arithmetic) 2.7699e-26 // Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006 // -struct lanczos17m64 : public boost::math::integral_constant +struct lanczos17m64 : public BOOST_MATH_NAMESPACE::integral_constant { // // Use for extended-double precision, when evaluated as an extended-double: @@ -723,7 +725,7 @@ struct lanczos17m64 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 64, 488.0063567520005730476791712814838113252)), static_cast(BOOST_MATH_BIG_CONSTANT(T, 64, 2.50662827463100050241576877135758834683)) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint64_t) denom[17] = { + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint64_t) denom[17] = { BOOST_MATH_INT_VALUE_SUFFIX(0, uLL), BOOST_MATH_INT_VALUE_SUFFIX(1307674368000, uLL), BOOST_MATH_INT_VALUE_SUFFIX(4339163001600, uLL), @@ -743,7 +745,7 @@ struct lanczos17m64 : public boost::math::integral_constant BOOST_MATH_INT_VALUE_SUFFIX(1, uLL) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -769,7 +771,7 @@ struct lanczos17m64 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 64, 0.002393749522058449186690627996063983095463)), static_cast(BOOST_MATH_BIG_CONSTANT(T, 64, 0.1229541408909435212800785616808830746135e-4)) }; - BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, boost::math::uint64_t) denom[17] = { + BOOST_MATH_STATIC const BOOST_MATH_INT_TABLE_TYPE(T, BOOST_MATH_NAMESPACE::uint64_t) denom[17] = { BOOST_MATH_INT_VALUE_SUFFIX(0, uLL), BOOST_MATH_INT_VALUE_SUFFIX(1307674368000, uLL), BOOST_MATH_INT_VALUE_SUFFIX(4339163001600, uLL), @@ -789,7 +791,7 @@ struct lanczos17m64 : public boost::math::integral_constant BOOST_MATH_INT_VALUE_SUFFIX(1, uLL) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -864,7 +866,7 @@ struct lanczos17m64 : public boost::math::integral_constant // Max experimental error (with arbitrary precision arithmetic) 1.0541e-38 // Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006 // -struct lanczos24m113 : public boost::math::integral_constant +struct lanczos24m113 : public BOOST_MATH_NAMESPACE::integral_constant { // // Use for long-double precision, when evaluated as an long-double: @@ -926,7 +928,7 @@ struct lanczos24m113 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 113, 1.0)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -986,7 +988,7 @@ struct lanczos24m113 : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 113, 1.0)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -1076,7 +1078,7 @@ struct lanczos24m113 : public boost::math::integral_constant // Generated with compiler: Microsoft Visual C++ version 14.2 on Win32 at May 23 2021 // Type precision was 134 bits or 42 max_digits10 // -struct lanczos27MP : public boost::math::integral_constant +struct lanczos27MP : public BOOST_MATH_NAMESPACE::integral_constant { template BOOST_MATH_GPU_ENABLED static T lanczos_sum(const T& z) @@ -1141,7 +1143,7 @@ struct lanczos27MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 134, 1.000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -1207,7 +1209,7 @@ struct lanczos27MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 134, 1.000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -1324,7 +1326,7 @@ BOOST_MATH_GPU_ENABLED inline double lanczos_g_near_1_and_2(const lanczos27MP&) // Generated with compiler: Microsoft Visual C++ version 14.2 on Win32 at Oct 14 2019 // Type precision was 168 bits or 53 max_digits10 // -struct lanczos35MP : public boost::math::integral_constant +struct lanczos35MP : public BOOST_MATH_NAMESPACE::integral_constant { template BOOST_MATH_GPU_ENABLED static T lanczos_sum(const T& z) @@ -1405,7 +1407,7 @@ struct lanczos35MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 168, 1.00000000000000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -1487,7 +1489,7 @@ struct lanczos35MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 168, 1.00000000000000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -1619,7 +1621,7 @@ BOOST_MATH_GPU_ENABLED inline double lanczos_g_near_1_and_2(const lanczos35MP&) // Generated with compiler: Microsoft Visual C++ version 14.2 on Win32 at Oct 14 2019 // Type precision was 201 bits or 63 max_digits10 // -struct lanczos48MP : public boost::math::integral_constant +struct lanczos48MP : public BOOST_MATH_NAMESPACE::integral_constant { template BOOST_MATH_GPU_ENABLED static T lanczos_sum(const T& z) @@ -1726,7 +1728,7 @@ struct lanczos48MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 201, 1.000000000000000000000000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -1834,7 +1836,7 @@ struct lanczos48MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 201, 1.000000000000000000000000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -1971,7 +1973,7 @@ struct lanczos48MP : public boost::math::integral_constant // Generated with compiler: Microsoft Visual C++ version 14.2 on Win32 at May 23 2021 // Type precision was 234 bits or 72 max_digits10 // -struct lanczos49MP : public boost::math::integral_constant +struct lanczos49MP : public BOOST_MATH_NAMESPACE::integral_constant { template BOOST_MATH_GPU_ENABLED static T lanczos_sum(const T& z) @@ -2080,7 +2082,7 @@ struct lanczos49MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 234, 1.000000000000000000000000000000000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -2190,7 +2192,7 @@ struct lanczos49MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 234, 1.000000000000000000000000000000000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -2335,7 +2337,7 @@ BOOST_MATH_GPU_ENABLED inline double lanczos_g_near_1_and_2(const lanczos49MP&) // Generated with compiler: Microsoft Visual C++ version 14.2 on Win32 at May 22 2021 // Type precision was 267 bits or 82 max_digits10 // -struct lanczos52MP : public boost::math::integral_constant +struct lanczos52MP : public BOOST_MATH_NAMESPACE::integral_constant { template BOOST_MATH_GPU_ENABLED static T lanczos_sum(const T& z) @@ -2450,7 +2452,7 @@ struct lanczos52MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 267, 1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } template @@ -2566,7 +2568,7 @@ struct lanczos52MP : public boost::math::integral_constant static_cast(BOOST_MATH_BIG_CONSTANT(T, 267, 1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000e+00)) }; // LCOV_EXCL_STOP - return boost::math::tools::evaluate_rational(num, denom, z); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z); } @@ -2725,31 +2727,30 @@ BOOST_MATH_GPU_ENABLED inline double lanczos_g_near_1_and_2(const lanczos52MP&) // // placeholder for no lanczos info available: // -struct undefined_lanczos : public boost::math::integral_constant::max)() - 1> { }; +struct undefined_lanczos : public BOOST_MATH_NAMESPACE::integral_constant::max)() - 1> { }; template struct lanczos { - BOOST_MATH_STATIC constexpr auto target_precision = policies::precision::type::value <= 0 ? (boost::math::numeric_limits::max)()-2 : + BOOST_MATH_STATIC constexpr auto target_precision = policies::precision::type::value <= 0 ? (BOOST_MATH_NAMESPACE::numeric_limits::max)()-2 : policies::precision::type::value; - using type = typename boost::math::conditional<(target_precision <= lanczos6m24::value), lanczos6m24, - typename boost::math::conditional<(target_precision <= lanczos13m53::value), lanczos13m53, - typename boost::math::conditional<(target_precision <= lanczos11::value), lanczos11, - typename boost::math::conditional<(target_precision <= lanczos17m64::value), lanczos17m64, - typename boost::math::conditional<(target_precision <= lanczos24m113::value), lanczos24m113, - typename boost::math::conditional<(target_precision <= lanczos27MP::value), lanczos27MP, - typename boost::math::conditional<(target_precision <= lanczos35MP::value), lanczos35MP, - typename boost::math::conditional<(target_precision <= lanczos48MP::value), lanczos48MP, - typename boost::math::conditional<(target_precision <= lanczos49MP::value), lanczos49MP, - typename boost::math::conditional<(target_precision <= lanczos52MP::value), lanczos52MP, undefined_lanczos>::type + using type = typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos6m24::value), lanczos6m24, + typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos13m53::value), lanczos13m53, + typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos11::value), lanczos11, + typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos17m64::value), lanczos17m64, + typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos24m113::value), lanczos24m113, + typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos27MP::value), lanczos27MP, + typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos35MP::value), lanczos35MP, + typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos48MP::value), lanczos48MP, + typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos49MP::value), lanczos49MP, + typename BOOST_MATH_NAMESPACE::conditional<(target_precision <= lanczos52MP::value), lanczos52MP, undefined_lanczos>::type >::type>::type>::type>::type>::type>::type>::type>::type >::type; }; } // namespace lanczos -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #if !defined(_CRAYC) && !defined(BOOST_MATH_ENABLE_CUDA) && (!defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 3))) #if ((defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64)) && !defined(_MANAGED) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) diff --git a/include/boost/math/special_functions/legendre.hpp b/include/boost/math/special_functions/legendre.hpp index 992953e231..254af932c1 100644 --- a/include/boost/math/special_functions/legendre.hpp +++ b/include/boost/math/special_functions/legendre.hpp @@ -10,20 +10,21 @@ #pragma once #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include #include #include -namespace boost{ -namespace math{ +BOOST_MATH_NAMESPACE_BEGIN // Recurrence relation for legendre P and Q polynomials: -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type legendre_next(unsigned l, T1 x, T2 Pl, T3 Plm1) { @@ -46,7 +47,7 @@ T legendre_imp(unsigned l, T x, const Policy& pol, bool second = false) if(second) { // A solution of the second kind (Q): - p0 = (boost::math::log1p(x, pol) - boost::math::log1p(-x, pol)) / 2; + p0 = (BOOST_MATH_NAMESPACE::log1p(x, pol) - BOOST_MATH_NAMESPACE::log1p(-x, pol)) / 2; p1 = x * p0 - 1; } else @@ -63,20 +64,14 @@ T legendre_imp(unsigned l, T x, const Policy& pol, bool second = false) while(n < l) { std::swap(p0, p1); - p1 = static_cast(boost::math::legendre_next(n, x, p0, p1)); + p1 = static_cast(BOOST_MATH_NAMESPACE::legendre_next(n, x, p0, p1)); ++n; } return p1; } template -T legendre_p_prime_imp(unsigned l, T x, const Policy& pol, T* Pn -#ifdef BOOST_NO_CXX11_NULLPTR - = 0 -#else - = nullptr -#endif -) +T legendre_p_prime_imp(unsigned l, T x, const Policy& pol, T* Pn = nullptr) { static const char* function = "boost::math::legrendre_p_prime<%1%>(unsigned, %1%)"; // Error handling: @@ -106,7 +101,7 @@ T legendre_p_prime_imp(unsigned l, T x, const Policy& pol, T* Pn while(n < l - 1) { std::swap(p0, p1); - p1 = static_cast(boost::math::legendre_next(n, x, p0, p1)); + p1 = static_cast(BOOST_MATH_NAMESPACE::legendre_next(n, x, p0, p1)); ++n; if (odd) { @@ -122,7 +117,7 @@ T legendre_p_prime_imp(unsigned l, T x, const Policy& pol, T* Pn if (Pn) { std::swap(p0, p1); - *Pn = static_cast(boost::math::legendre_next(n, x, p0, p1)); + *Pn = static_cast(BOOST_MATH_NAMESPACE::legendre_next(n, x, p0, p1)); } return p_prime; } @@ -150,9 +145,9 @@ std::vector legendre_p_zeros_imp(int n, const Policy& pol) using std::sin; using std::ceil; using std::sqrt; - using boost::math::constants::pi; - using boost::math::constants::half; - using boost::math::tools::newton_raphson_iterate; + using BOOST_MATH_NAMESPACE::constants::pi; + using BOOST_MATH_NAMESPACE::constants::half; + using BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate; BOOST_MATH_ASSERT(n >= 0); std::vector zeros; @@ -213,7 +208,7 @@ std::vector legendre_p_zeros_imp(int n, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template inline typename std::enable_if::value, typename tools::promote_args::type>::type legendre_p(int l, T x, const Policy& pol) { @@ -226,7 +221,7 @@ inline typename std::enable_if::value, typename tool } -template +BOOST_MATH_EXPORT template inline typename std::enable_if::value, typename tools::promote_args::type>::type legendre_p_prime(int l, T x, const Policy& pol) { @@ -238,21 +233,21 @@ inline typename std::enable_if::value, typename tool return policies::checked_narrowing_cast(detail::legendre_p_prime_imp(l, static_cast(x), pol), function); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type legendre_p(int l, T x) { - return boost::math::legendre_p(l, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::legendre_p(l, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type legendre_p_prime(int l, T x) { - return boost::math::legendre_p_prime(l, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::legendre_p_prime(l, x, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline std::vector legendre_p_zeros(int l, const Policy& pol) { if(l < 0) @@ -262,13 +257,13 @@ inline std::vector legendre_p_zeros(int l, const Policy& pol) } -template +BOOST_MATH_EXPORT template inline std::vector legendre_p_zeros(int l) { - return boost::math::legendre_p_zeros(l, policies::policy<>()); + return BOOST_MATH_NAMESPACE::legendre_p_zeros(l, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename std::enable_if::value, typename tools::promote_args::type>::type legendre_q(unsigned l, T x, const Policy& pol) { @@ -277,15 +272,15 @@ inline typename std::enable_if::value, typename tool return policies::checked_narrowing_cast(detail::legendre_imp(l, static_cast(x), pol, true), "boost::math::legendre_q<%1%>(unsigned, %1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type legendre_q(unsigned l, T x) { - return boost::math::legendre_q(l, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::legendre_q(l, x, policies::policy<>()); } // Recurrence for associated polynomials: -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1) { @@ -315,20 +310,20 @@ T legendre_p_imp(int l, int m, T x, T sin_theta_power, const Policy& pol) } if (-m == l) { - return pow((1 - x * x) / 4, T(l) / 2) / boost::math::tgamma(l + 1, pol); + return pow((1 - x * x) / 4, T(l) / 2) / BOOST_MATH_NAMESPACE::tgamma(l + 1, pol); } if(m < 0) { int sign = (m&1) ? -1 : 1; - return sign * boost::math::tgamma_ratio(static_cast(l+m+1), static_cast(l+1-m), pol) * legendre_p_imp(l, -m, x, sin_theta_power, pol); + return sign * BOOST_MATH_NAMESPACE::tgamma_ratio(static_cast(l+m+1), static_cast(l+1-m), pol) * legendre_p_imp(l, -m, x, sin_theta_power, pol); } // Special cases: if(m > l) return 0; if(m == 0) - return boost::math::legendre_p(l, x, pol); + return BOOST_MATH_NAMESPACE::legendre_p(l, x, pol); - T p0 = boost::math::double_factorial(2 * m - 1, pol) * sin_theta_power; + T p0 = BOOST_MATH_NAMESPACE::double_factorial(2 * m - 1, pol) * sin_theta_power; if(m&1) p0 *= -1; @@ -342,7 +337,7 @@ T legendre_p_imp(int l, int m, T x, T sin_theta_power, const Policy& pol) while(n < l) { std::swap(p0, p1); - p1 = boost::math::legendre_next(n, m, x, p0, p1); + p1 = BOOST_MATH_NAMESPACE::legendre_next(n, m, x, p0, p1); ++n; } return p1; @@ -358,7 +353,7 @@ inline T legendre_p_imp(int l, int m, T x, const Policy& pol) } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type legendre_p(int l, int m, T x, const Policy& pol) { @@ -367,14 +362,13 @@ inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::legendre_p_imp(l, m, static_cast(x), pol), "boost::math::legendre_p<%1%>(int, int, %1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type legendre_p(int l, int m, T x) { - return boost::math::legendre_p(l, m, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::legendre_p(l, m, x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_LEGENDRE_HPP diff --git a/include/boost/math/special_functions/legendre_stieltjes.hpp b/include/boost/math/special_functions/legendre_stieltjes.hpp index 44eafea2d5..e9338de8ab 100644 --- a/include/boost/math/special_functions/legendre_stieltjes.hpp +++ b/include/boost/math/special_functions/legendre_stieltjes.hpp @@ -16,15 +16,18 @@ * Patterson, TNL. "The optimum addition of points to quadrature formulae." Mathematics of Computation 22.104 (1968): 847-856. */ +#ifndef BOOST_MATH_BUILD_MODULE #include +#include #include +#endif #include +#include #include -namespace boost{ -namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template class legendre_stieltjes { public: @@ -32,7 +35,7 @@ class legendre_stieltjes { if (m == 0) { - throw std::domain_error("The Legendre-Stieltjes polynomial is defined for order m > 0.\n"); + BOOST_MATH_THROW_EXCEPTION(std::domain_error("The Legendre-Stieltjes polynomial is defined for order m > 0.\n")); } m_m = static_cast(m); std::ptrdiff_t n = m - 1; @@ -114,14 +117,14 @@ class legendre_stieltjes for (size_t i = 2; i <= r; ++i) { std::swap(p0, p1); - p1 = boost::math::legendre_next(n, x, p0, p1); + p1 = BOOST_MATH_NAMESPACE::legendre_next(n, x, p0, p1); ++n; if (!odd) { Em += m_a[i]*p1; } std::swap(p0, p1); - p1 = boost::math::legendre_next(n, x, p0, p1); + p1 = BOOST_MATH_NAMESPACE::legendre_next(n, x, p0, p1); ++n; if(odd) { @@ -152,7 +155,7 @@ class legendre_stieltjes std::vector zeros() const { - using boost::math::constants::half; + using BOOST_MATH_NAMESPACE::constants::half; std::vector stieltjes_zeros; std::vector legendre_zeros = legendre_p_zeros(m_m - 1); @@ -200,9 +203,9 @@ class legendre_stieltjes // The root bracketing is not very tight; to keep weird stuff from happening // in the Newton's method, let's tighten up the tolerance using a few bisections. - boost::math::tools::eps_tolerance tol(6); + BOOST_MATH_NAMESPACE::tools::eps_tolerance tol(6); auto g = [&](Real t) { return this->operator()(t); }; - auto p = boost::math::tools::bisect(g, lower_bound, upper_bound, tol); + auto p = BOOST_MATH_NAMESPACE::tools::bisect(g, lower_bound, upper_bound, tol); Real x_nk_guess = p.first + (p.second - p.first)*half(); std::uintmax_t number_of_iterations = 500; @@ -211,7 +214,7 @@ class legendre_stieltjes Real Pn_prime = this->prime(x); return std::pair(Pn, Pn_prime); }; - const Real x_nk = boost::math::tools::newton_raphson_iterate(f, x_nk_guess, + const Real x_nk = BOOST_MATH_NAMESPACE::tools::newton_raphson_iterate(f, x_nk_guess, p.first, p.second, tools::digits(), number_of_iterations); @@ -230,5 +233,5 @@ class legendre_stieltjes int m_m; }; -}} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/log1p.hpp b/include/boost/math/special_functions/log1p.hpp index 3851fb3a4b..9ab459ef9a 100644 --- a/include/boost/math/special_functions/log1p.hpp +++ b/include/boost/math/special_functions/log1p.hpp @@ -15,7 +15,9 @@ #if defined __has_include # if ((__cplusplus > 202002L) || (defined(_MSVC_LANG) && (_MSVC_LANG > 202002L))) # if __has_include () +#ifndef BOOST_MATH_BUILD_MODULE # include +#endif # endif # endif #endif @@ -43,7 +45,7 @@ #pragma GCC system_header #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -88,14 +90,14 @@ namespace detail // it performs no better than log(1+x): which is to say not very well at all. // template -BOOST_MATH_GPU_ENABLED T log1p_imp(T const & x, const Policy& pol, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T log1p_imp(T const & x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&) { // The function returns the natural logarithm of 1 + x. typedef typename tools::promote_args::type result_type; BOOST_MATH_STD_USING constexpr auto function = "boost::math::log1p<%1%>(%1%)"; - if((x < -1) || (boost::math::isnan)(x)) + if((x < -1) || (BOOST_MATH_NAMESPACE::isnan)(x)) return policies::raise_domain_error(function, "log1p(x) requires x > -1, but got x = %1%.", x, pol); if(x == -1) return -policies::raise_overflow_error(function, nullptr, pol); @@ -108,7 +110,7 @@ BOOST_MATH_GPU_ENABLED T log1p_imp(T const & x, const Policy& pol, const boost:: if(a < tools::epsilon()) return x; detail::log1p_series s(x); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); result_type result = tools::sum_series(s, policies::get_epsilon(), max_iter); @@ -117,7 +119,7 @@ BOOST_MATH_GPU_ENABLED T log1p_imp(T const & x, const Policy& pol, const boost:: } template -BOOST_MATH_GPU_ENABLED T log1p_imp(T const& x, const Policy& pol, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T log1p_imp(T const& x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&) { // The function returns the natural logarithm of 1 + x. BOOST_MATH_STD_USING @@ -168,7 +170,7 @@ BOOST_MATH_GPU_ENABLED T log1p_imp(T const& x, const Policy& pol, const boost::m } template -BOOST_MATH_GPU_ENABLED T log1p_imp(T const& x, const Policy& pol, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T log1p_imp(T const& x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&) { // The function returns the natural logarithm of 1 + x. BOOST_MATH_STD_USING @@ -221,7 +223,7 @@ BOOST_MATH_GPU_ENABLED T log1p_imp(T const& x, const Policy& pol, const boost::m } template -BOOST_MATH_GPU_ENABLED T log1p_imp(T const& x, const Policy& pol, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T log1p_imp(T const& x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&) { // The function returns the natural logarithm of 1 + x. BOOST_MATH_STD_USING @@ -268,7 +270,7 @@ BOOST_MATH_GPU_ENABLED T log1p_imp(T const& x, const Policy& pol, const boost::m } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type log1p(T x, const Policy&) { typedef typename tools::promote_args::type result_type; @@ -281,7 +283,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type log1p(T x, c policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; - typedef boost::math::integral_constant::type log1p(T x, c detail::log1p_imp(static_cast(x), forwarding_policy(), tag_type()), "boost::math::log1p<%1%>(%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline float log1p(float x, const Policy& pol) { if(x < -1) @@ -305,7 +307,7 @@ BOOST_MATH_GPU_ENABLED inline float log1p(float x, const Policy& pol) #endif } #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline long double log1p(long double x, const Policy& pol) { if(x < -1) @@ -315,7 +317,7 @@ BOOST_MATH_GPU_ENABLED inline long double log1p(long double x, const Policy& pol return std::log1p(x); } #endif -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline double log1p(double x, const Policy& pol) { if(x < -1) @@ -329,15 +331,15 @@ BOOST_MATH_GPU_ENABLED inline double log1p(double x, const Policy& pol) #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type log1p(T x) { - return boost::math::log1p(x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::log1p(x, policies::policy<>()); } // // Compute log(1+x)-x: // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type log1pmx(T x, const Policy& pol) { @@ -357,17 +359,17 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type // epsilon just returns zero, and our "optimisation" will always fail: if(a < tools::epsilon()) return -x * x / 2; - boost::math::detail::log1p_series s(x); + BOOST_MATH_NAMESPACE::detail::log1p_series s(x); s(); - boost::math::uintmax_t max_iter = policies::get_max_series_iterations(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = policies::get_max_series_iterations(); - T result = boost::math::tools::sum_series(s, policies::get_epsilon(), max_iter); + T result = BOOST_MATH_NAMESPACE::tools::sum_series(s, policies::get_epsilon(), max_iter); policies::check_series_iterations(function, max_iter, pol); return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type log1pmx(T x) { return log1pmx(x, policies::policy<>()); @@ -377,35 +379,34 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type log1pmx(T x) // Specific width floating point types: // #ifdef __STDCPP_FLOAT32_T__ -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline std::float32_t log1p(std::float32_t x, const Policy& pol) { - return boost::math::log1p(static_cast(x), pol); + return BOOST_MATH_NAMESPACE::log1p(static_cast(x), pol); } #endif #ifdef __STDCPP_FLOAT64_T__ -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline std::float64_t log1p(std::float64_t x, const Policy& pol) { - return boost::math::log1p(static_cast(x), pol); + return BOOST_MATH_NAMESPACE::log1p(static_cast(x), pol); } #endif #ifdef __STDCPP_FLOAT128_T__ -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline std::float128_t log1p(std::float128_t x, const Policy& pol) { if constexpr (std::numeric_limits::digits == std::numeric_limits::digits) { - return boost::math::log1p(static_cast(x), pol); + return BOOST_MATH_NAMESPACE::log1p(static_cast(x), pol); } else { - return boost::math::detail::log1p_imp(x, pol, boost::math::integral_constant()); + return BOOST_MATH_NAMESPACE::detail::log1p_imp(x, pol, BOOST_MATH_NAMESPACE::integral_constant()); } } #endif -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/logaddexp.hpp b/include/boost/math/special_functions/logaddexp.hpp index 8949496f6e..27c71e6c92 100644 --- a/include/boost/math/special_functions/logaddexp.hpp +++ b/include/boost/math/special_functions/logaddexp.hpp @@ -3,15 +3,17 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN // Calculates log(exp(x1) + exp(x2)) -template +BOOST_MATH_EXPORT template Real logaddexp(Real x1, Real x2) noexcept { using std::log1p; @@ -19,11 +21,11 @@ Real logaddexp(Real x1, Real x2) noexcept using std::abs; // Validate inputs first - if (!(boost::math::isfinite)(x1)) + if (!(BOOST_MATH_NAMESPACE::isfinite)(x1)) { return x1; } - else if (!(boost::math::isfinite)(x2)) + else if (!(BOOST_MATH_NAMESPACE::isfinite)(x2)) { return x2; } @@ -38,4 +40,4 @@ Real logaddexp(Real x1, Real x2) noexcept return x2 + log1p(exp(temp)); } -}} // Namespace boost::math +BOOST_MATH_NAMESPACE_END diff --git a/include/boost/math/special_functions/logistic_sigmoid.hpp b/include/boost/math/special_functions/logistic_sigmoid.hpp index 7279b17e6c..5ffd61990e 100644 --- a/include/boost/math/special_functions/logistic_sigmoid.hpp +++ b/include/boost/math/special_functions/logistic_sigmoid.hpp @@ -9,12 +9,13 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType logistic_sigmoid(RealType x, const Policy&) { BOOST_MATH_STD_USING @@ -34,13 +35,12 @@ BOOST_MATH_GPU_ENABLED RealType logistic_sigmoid(RealType x, const Policy&) return res; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType logistic_sigmoid(RealType x) { return logistic_sigmoid(x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SF_EXPIT_HPP diff --git a/include/boost/math/special_functions/logit.hpp b/include/boost/math/special_functions/logit.hpp index e9da275e70..c5e8e60235 100644 --- a/include/boost/math/special_functions/logit.hpp +++ b/include/boost/math/special_functions/logit.hpp @@ -10,13 +10,14 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType logit(RealType p, const Policy&) { BOOST_MATH_STD_USING @@ -44,13 +45,12 @@ BOOST_MATH_GPU_ENABLED RealType logit(RealType p, const Policy&) return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RealType logit(RealType p) { return logit(p, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SF_LOGIT_HPP diff --git a/include/boost/math/special_functions/logsumexp.hpp b/include/boost/math/special_functions/logsumexp.hpp index 8aa1d4bffd..319993ac05 100644 --- a/include/boost/math/special_functions/logsumexp.hpp +++ b/include/boost/math/special_functions/logsumexp.hpp @@ -3,19 +3,21 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include +#endif #include -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN // https://nhigham.com/2021/01/05/what-is-the-log-sum-exp-function/ // See equation (#) -template ::value_type> +BOOST_MATH_EXPORT template ::value_type> Real logsumexp(ForwardIterator first, ForwardIterator last) { using std::exp; @@ -38,13 +40,13 @@ Real logsumexp(ForwardIterator first, ForwardIterator last) return max_val + log1p(arg); } -template +BOOST_MATH_EXPORT template inline Real logsumexp(const Container& c) { return logsumexp(std::begin(c), std::end(c)); } -template ::type, +BOOST_MATH_EXPORT template ::type, typename std::enable_if::value, bool>::type = true> inline Real logsumexp(Args&& ...args) { @@ -57,4 +59,4 @@ inline Real logsumexp(Args&& ...args) return logsumexp(list.begin(), list.end()); } -}} // Namespace boost::math +BOOST_MATH_NAMESPACE_END diff --git a/include/boost/math/special_functions/math_fwd.hpp b/include/boost/math/special_functions/math_fwd.hpp index 6c8394ddf9..0c22410f67 100644 --- a/include/boost/math/special_functions/math_fwd.hpp +++ b/include/boost/math/special_functions/math_fwd.hpp @@ -32,10 +32,9 @@ #ifdef BOOST_MATH_HAS_NVRTC -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type beta(RT1 a, RT2 b, A arg); @@ -44,7 +43,7 @@ namespace detail{ template struct ellint_3_result { - using type = typename boost::math::conditional< + using type = typename BOOST_MATH_NAMESPACE::conditional< policies::is_policy::value, tools::promote_args_t, tools::promote_args_t @@ -54,43 +53,43 @@ namespace detail{ template struct expint_result { - using type = typename boost::math::conditional< + using type = typename BOOST_MATH_NAMESPACE::conditional< policies::is_policy::value, tools::promote_args_t, typename tools::promote_args::type >::type; }; - typedef boost::math::integral_constant bessel_no_int_tag; // No integer optimisation possible. - typedef boost::math::integral_constant bessel_maybe_int_tag; // Maybe integer optimisation. - typedef boost::math::integral_constant bessel_int_tag; // Definite integer optimisation. + typedef BOOST_MATH_NAMESPACE::integral_constant bessel_no_int_tag; // No integer optimisation possible. + typedef BOOST_MATH_NAMESPACE::integral_constant bessel_maybe_int_tag; // Maybe integer optimisation. + typedef BOOST_MATH_NAMESPACE::integral_constant bessel_int_tag; // Definite integer optimisation. template struct bessel_traits { - using result_type = typename boost::math::conditional< - boost::math::is_integral::value, + using result_type = typename BOOST_MATH_NAMESPACE::conditional< + BOOST_MATH_NAMESPACE::is_integral::value, typename tools::promote_args::type, tools::promote_args_t >::type; typedef typename policies::precision::type precision_type; - using optimisation_tag = typename boost::math::conditional< + using optimisation_tag = typename BOOST_MATH_NAMESPACE::conditional< (precision_type::value <= 0 || precision_type::value > 64), bessel_no_int_tag, - typename boost::math::conditional< - boost::math::is_integral::value, + typename BOOST_MATH_NAMESPACE::conditional< + BOOST_MATH_NAMESPACE::is_integral::value, bessel_int_tag, bessel_maybe_int_tag >::type >::type; - using optimisation_tag128 = typename boost::math::conditional< + using optimisation_tag128 = typename BOOST_MATH_NAMESPACE::conditional< (precision_type::value <= 0 || precision_type::value > 113), bessel_no_int_tag, - typename boost::math::conditional< - boost::math::is_integral::value, + typename BOOST_MATH_NAMESPACE::conditional< + BOOST_MATH_NAMESPACE::is_integral::value, bessel_int_tag, bessel_maybe_int_tag >::type @@ -99,220 +98,242 @@ namespace detail{ } // namespace detail -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include #define BOOST_NO_MACRO_EXPAND /**/ -namespace boost -{ - namespace math - { // Math functions (in roughly alphabetic order). +BOOST_MATH_NAMESPACE_BEGIN // Math functions (in roughly alphabetic order). // Beta functions. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t beta(RT1 a, RT2 b); // Beta function (2 arguments). - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t beta(RT1 a, RT2 b, A x); // Beta function (3 arguments). - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t beta(RT1 a, RT2 b, RT3 x, const Policy& pol); // Beta function (3 arguments). - template + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t + lbeta(RT1 a, RT2 b); // Log of the beta function. + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t + lbeta(RT1 a, RT2 b, const Policy& pol); // Log of the beta function. + + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t betac(RT1 a, RT2 b, RT3 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t betac(RT1 a, RT2 b, RT3 x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta(RT1 a, RT2 b, RT3 x); // Incomplete beta function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta(RT1 a, RT2 b, RT3 x, const Policy& pol); // Incomplete beta function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac(RT1 a, RT2 b, RT3 x); // Incomplete beta complement function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac(RT1 a, RT2 b, RT3 x, const Policy& pol); // Incomplete beta complement function. - template + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t + libeta(RT1 a, RT2 b, RT3 x); // Log of the incomplete beta function. + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t + libeta(RT1 a, RT2 b, RT3 x, const Policy& pol); // Log of the incomplete beta function. + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t + libetac(RT1 a, RT2 b, RT3 x); // Log of the incomplete beta complement function. + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t + libetac(RT1 a, RT2 b, RT3 x, const Policy& pol); // Log of the incomplete beta complement function. + + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_inv(T1 a, T2 b, T3 p, T4* py); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_inv(T1 a, T2 b, T3 p, T4* py, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_inv(RT1 a, RT2 b, RT3 p); // Incomplete beta inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_inv(RT1 a, RT2 b, RT3 p, const Policy&); // Incomplete beta inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_inva(RT1 a, RT2 b, RT3 p); // Incomplete beta inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_inva(RT1 a, RT2 b, RT3 p, const Policy&); // Incomplete beta inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_invb(RT1 a, RT2 b, RT3 p); // Incomplete beta inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_invb(RT1 a, RT2 b, RT3 p, const Policy&); // Incomplete beta inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac_inv(T1 a, T2 b, T3 q, T4* py); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac_inv(T1 a, T2 b, T3 q, T4* py, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac_inv(RT1 a, RT2 b, RT3 q); // Incomplete beta complement inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac_inv(RT1 a, RT2 b, RT3 q, const Policy&); // Incomplete beta complement inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac_inva(RT1 a, RT2 b, RT3 q); // Incomplete beta complement inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac_inva(RT1 a, RT2 b, RT3 q, const Policy&); // Incomplete beta complement inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac_invb(RT1 a, RT2 b, RT3 q); // Incomplete beta complement inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibetac_invb(RT1 a, RT2 b, RT3 q, const Policy&); // Incomplete beta complement inverse function. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_derivative(RT1 a, RT2 b, RT3 x); // derivative of incomplete beta - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ibeta_derivative(RT1 a, RT2 b, RT3 x, const Policy& pol); // derivative of incomplete beta // Binomial: - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T binomial_coefficient(unsigned n, unsigned k, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T binomial_coefficient(unsigned n, unsigned k); // erf & erfc error functions. - template // Error function. + BOOST_MATH_EXPORT template // Error function. BOOST_MATH_GPU_ENABLED tools::promote_args_t erf(RT z); - template // Error function. + BOOST_MATH_EXPORT template // Error function. BOOST_MATH_GPU_ENABLED tools::promote_args_t erf(RT z, const Policy&); - template // Error function complement. + BOOST_MATH_EXPORT template // Error function complement. BOOST_MATH_GPU_ENABLED tools::promote_args_t erfc(RT z); - template // Error function complement. + BOOST_MATH_EXPORT template // Error function complement. BOOST_MATH_GPU_ENABLED tools::promote_args_t erfc(RT z, const Policy&); - template // Error function inverse. + BOOST_MATH_EXPORT template // Error function inverse. BOOST_MATH_GPU_ENABLED tools::promote_args_t erf_inv(RT z); - template // Error function inverse. + BOOST_MATH_EXPORT template // Error function inverse. BOOST_MATH_GPU_ENABLED tools::promote_args_t erf_inv(RT z, const Policy& pol); - template // Error function complement inverse. + BOOST_MATH_EXPORT template // Error function complement inverse. BOOST_MATH_GPU_ENABLED tools::promote_args_t erfc_inv(RT z); - template // Error function complement inverse. + BOOST_MATH_EXPORT template // Error function complement inverse. BOOST_MATH_GPU_ENABLED tools::promote_args_t erfc_inv(RT z, const Policy& pol); // Polynomials: - template + BOOST_MATH_EXPORT template tools::promote_args_t legendre_next(unsigned l, T1 x, T2 Pl, T3 Plm1); - template + BOOST_MATH_EXPORT template tools::promote_args_t legendre_p(int l, T x); - template + BOOST_MATH_EXPORT template tools::promote_args_t legendre_p_prime(int l, T x); - template + BOOST_MATH_EXPORT template inline std::vector legendre_p_zeros(int l, const Policy& pol); - template + BOOST_MATH_EXPORT template inline std::vector legendre_p_zeros(int l); - template + BOOST_MATH_EXPORT template typename std::enable_if::value, tools::promote_args_t>::type legendre_p(int l, T x, const Policy& pol); - template + BOOST_MATH_EXPORT template inline typename std::enable_if::value, tools::promote_args_t>::type legendre_p_prime(int l, T x, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t legendre_q(unsigned l, T x); - template + BOOST_MATH_EXPORT template typename std::enable_if::value, tools::promote_args_t>::type legendre_q(unsigned l, T x, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1); - template + BOOST_MATH_EXPORT template tools::promote_args_t legendre_p(int l, int m, T x); - template + BOOST_MATH_EXPORT template tools::promote_args_t legendre_p(int l, int m, T x, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t laguerre_next(unsigned n, T1 x, T2 Ln, T3 Lnm1); - template + BOOST_MATH_EXPORT template tools::promote_args_t laguerre_next(unsigned n, unsigned l, T1 x, T2 Pl, T3 Plm1); - template + BOOST_MATH_EXPORT template tools::promote_args_t laguerre(unsigned n, T x); - template + BOOST_MATH_EXPORT template tools::promote_args_t laguerre(unsigned n, unsigned m, T x, const Policy& pol); @@ -326,148 +347,148 @@ namespace boost >::type; }; - template + BOOST_MATH_EXPORT template typename laguerre_result::type laguerre(unsigned n, T1 m, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t hermite(unsigned n, T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t hermite(unsigned n, T x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t hermite_next(unsigned n, T1 x, T2 Hn, T3 Hnm1); - template + BOOST_MATH_EXPORT template tools::promote_args_t chebyshev_next(T1 const & x, T2 const & Tn, T3 const & Tn_1); - template + BOOST_MATH_EXPORT template tools::promote_args_t chebyshev_t(unsigned n, Real const & x, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t chebyshev_t(unsigned n, Real const & x); - template + BOOST_MATH_EXPORT template tools::promote_args_t chebyshev_u(unsigned n, Real const & x, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t chebyshev_u(unsigned n, Real const & x); - template + BOOST_MATH_EXPORT template tools::promote_args_t chebyshev_t_prime(unsigned n, Real const & x, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t chebyshev_t_prime(unsigned n, Real const & x); - template + BOOST_MATH_EXPORT template Real chebyshev_clenshaw_recurrence(const Real* const c, size_t length, const T2& x); - template + BOOST_MATH_EXPORT template std::complex> spherical_harmonic(unsigned n, int m, T1 theta, T2 phi); - template + BOOST_MATH_EXPORT template std::complex> spherical_harmonic(unsigned n, int m, T1 theta, T2 phi, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi); - template + BOOST_MATH_EXPORT template tools::promote_args_t spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi); - template + BOOST_MATH_EXPORT template tools::promote_args_t spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi, const Policy& pol); // Elliptic integrals: - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rf(T1 x, T2 y, T3 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rf(T1 x, T2 y, T3 z, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rd(T1 x, T2 y, T3 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rd(T1 x, T2 y, T3 z, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rc(T1 x, T2 y); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rc(T1 x, T2 y, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rj(T1 x, T2 y, T3 z, T4 p); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rj(T1 x, T2 y, T3 z, T4 p, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rg(T1 x, T2 y, T3 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_rg(T1 x, T2 y, T3 z, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_2(T k); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_2(T1 k, T2 phi); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_2(T1 k, T2 phi, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_1(T k); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_1(T1 k, T2 phi); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_1(T1 k, T2 phi, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_d(T k); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_d(T1 k, T2 phi); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_d(T1 k, T2 phi, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t jacobi_zeta(T1 k, T2 phi); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t jacobi_zeta(T1 k, T2 phi, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t heuman_lambda(T1 k, T2 phi); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t heuman_lambda(T1 k, T2 phi, const Policy& pol); namespace detail{ @@ -475,7 +496,7 @@ namespace boost template struct ellint_3_result { - using type = typename boost::math::conditional< + using type = typename BOOST_MATH_NAMESPACE::conditional< policies::is_policy::value, tools::promote_args_t, tools::promote_args_t @@ -485,289 +506,301 @@ namespace boost } // namespace detail - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::ellint_3_result::type ellint_3(T1 k, T2 v, T3 phi); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_3(T1 k, T2 v, T3 phi, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t ellint_3(T1 k, T2 v); // Factorial functions. // Note: not for integral types, at present. - template + BOOST_MATH_EXPORT template struct max_factorial; - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RT factorial(unsigned int); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RT factorial(unsigned int, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RT unchecked_factorial(unsigned int BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(RT)); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RT double_factorial(unsigned i); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED RT double_factorial(unsigned i, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t falling_factorial(RT x, unsigned n); - template + BOOST_MATH_EXPORT template tools::promote_args_t falling_factorial(RT x, unsigned n, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t rising_factorial(RT x, int n); - template + BOOST_MATH_EXPORT template tools::promote_args_t rising_factorial(RT x, int n, const Policy& pol); // Gamma functions. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma(RT z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma1pm1(RT z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma1pm1(RT z, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma(RT1 a, RT2 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma(RT1 a, RT2 z, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t lgamma(RT z, int* sign); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t lgamma(RT z, int* sign, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t lgamma(RT x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t lgamma(RT x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma_lower(RT1 a, RT2 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma_lower(RT1 a, RT2 z, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_q(RT1 a, RT2 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_q(RT1 a, RT2 z, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t lgamma_q(RT1 a, RT2 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t lgamma_q(RT1 a, RT2 z, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t lgamma_p(RT1 a, RT2 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t lgamma_p(RT1 a, RT2 z, const Policy&); - template + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t ligamma(RT1 a, RT2 z); + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t ligamma(RT1 a, RT2 z, const Policy&); + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t ligamma_lower(RT1 a, RT2 z); + + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED tools::promote_args_t ligamma_lower(RT1 a, RT2 z, const Policy&); + + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_p(RT1 a, RT2 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_p(RT1 a, RT2 z, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma_ratio(T1 a, T2 b); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t tgamma_ratio(T1 a, T2 b, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_p_derivative(T1 a, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_p_derivative(T1 a, T2 x, const Policy&); // gamma inverse. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_p_inv(T1 a, T2 p); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_p_inva(T1 a, T2 p, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_p_inva(T1 a, T2 p); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_p_inv(T1 a, T2 p, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_q_inv(T1 a, T2 q); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_q_inv(T1 a, T2 q, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_q_inva(T1 a, T2 q); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t gamma_q_inva(T1 a, T2 q, const Policy&); // digamma: - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t digamma(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t digamma(T x, const Policy&); // trigamma: - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t trigamma(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t trigamma(T x, const Policy&); // polygamma: - template + BOOST_MATH_EXPORT template tools::promote_args_t polygamma(int n, T x); - template + BOOST_MATH_EXPORT template tools::promote_args_t polygamma(int n, T x, const Policy&); // Hypotenuse function sqrt(x ^ 2 + y ^ 2). - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t hypot(T1 x, T2 y); - template , bool> = true> + BOOST_MATH_EXPORT template , bool> = true> BOOST_MATH_GPU_ENABLED tools::promote_args_t hypot(T1 x, T2 y, const Policy&); - template , bool> = true> + BOOST_MATH_EXPORT template , bool> = true> BOOST_MATH_GPU_ENABLED tools::promote_args_t hypot(T1 x, T2 y, T3 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t hypot(T1 x, T2 y, T3 z, const Policy& pol); // cbrt - cube root. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t cbrt(RT z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t cbrt(RT z, const Policy&); // log1p is log(x + 1) - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t log1p(T); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t log1p(T, const Policy&); // log1pmx is log(x + 1) - x - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t log1pmx(T); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t log1pmx(T, const Policy&); // Exp (x) minus 1 functions. - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t expm1(T); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t expm1(T, const Policy&); // Power - 1 - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t powm1(const T1 a, const T2 z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t powm1(const T1 a, const T2 z, const Policy&); // sqrt(1+x) - 1 - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t sqrt1pm1(const T& val); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t sqrt1pm1(const T& val, const Policy&); // sinus cardinals: - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t sinc_pi(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t sinc_pi(T x, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t sinhc_pi(T x); - template + BOOST_MATH_EXPORT template tools::promote_args_t sinhc_pi(T x, const Policy&); // inverse hyperbolics: - template + BOOST_MATH_EXPORT template tools::promote_args_t asinh(T x); - template + BOOST_MATH_EXPORT template tools::promote_args_t asinh(T x, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t acosh(T x); - template + BOOST_MATH_EXPORT template tools::promote_args_t acosh(T x, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t atanh(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t atanh(T x, const Policy&); namespace detail{ - typedef boost::math::integral_constant bessel_no_int_tag; // No integer optimisation possible. - typedef boost::math::integral_constant bessel_maybe_int_tag; // Maybe integer optimisation. - typedef boost::math::integral_constant bessel_int_tag; // Definite integer optimisation. + typedef BOOST_MATH_NAMESPACE::integral_constant bessel_no_int_tag; // No integer optimisation possible. + typedef BOOST_MATH_NAMESPACE::integral_constant bessel_maybe_int_tag; // Maybe integer optimisation. + typedef BOOST_MATH_NAMESPACE::integral_constant bessel_int_tag; // Definite integer optimisation. template struct bessel_traits { - using result_type = typename boost::math::conditional< - boost::math::is_integral::value, + using result_type = typename BOOST_MATH_NAMESPACE::conditional< + BOOST_MATH_NAMESPACE::is_integral::value, typename tools::promote_args::type, tools::promote_args_t >::type; typedef typename policies::precision::type precision_type; - using optimisation_tag = typename boost::math::conditional< + using optimisation_tag = typename BOOST_MATH_NAMESPACE::conditional< (precision_type::value <= 0 || precision_type::value > 64), bessel_no_int_tag, - typename boost::math::conditional< - boost::math::is_integral::value, + typename BOOST_MATH_NAMESPACE::conditional< + BOOST_MATH_NAMESPACE::is_integral::value, bessel_int_tag, bessel_maybe_int_tag >::type >::type; - using optimisation_tag128 = typename boost::math::conditional< + using optimisation_tag128 = typename BOOST_MATH_NAMESPACE::conditional< (precision_type::value <= 0 || precision_type::value > 113), bessel_no_int_tag, - typename boost::math::conditional< - boost::math::is_integral::value, + typename BOOST_MATH_NAMESPACE::conditional< + BOOST_MATH_NAMESPACE::is_integral::value, bessel_int_tag, bessel_maybe_int_tag >::type @@ -776,224 +809,224 @@ namespace boost } // detail // Bessel functions: - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_bessel_j(T1 v, T2 x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_bessel_j_prime(T1 v, T2 x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_bessel_j(T1 v, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_bessel_j_prime(T1 v, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type sph_bessel(unsigned v, T x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type sph_bessel_prime(unsigned v, T x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type sph_bessel(unsigned v, T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type sph_bessel_prime(unsigned v, T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_bessel_i(T1 v, T2 x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_bessel_i_prime(T1 v, T2 x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_bessel_i(T1 v, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_bessel_i_prime(T1 v, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_bessel_k(T1 v, T2 x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_bessel_k_prime(T1 v, T2 x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_bessel_k(T1 v, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_bessel_k_prime(T1 v, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_neumann(T1 v, T2 x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_neumann_prime(T1 v, T2 x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_neumann(T1 v, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_neumann_prime(T1 v, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type sph_neumann(unsigned v, T x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type sph_neumann_prime(unsigned v, T x, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type sph_neumann(unsigned v, T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type sph_neumann_prime(unsigned v, T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_bessel_j_zero(T v, int m, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_bessel_j_zero(T v, int m); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED OutputIterator cyl_bessel_j_zero(T v, int start_index, unsigned number_of_zeros, OutputIterator out_it); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED OutputIterator cyl_bessel_j_zero(T v, int start_index, unsigned number_of_zeros, OutputIterator out_it, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits::result_type cyl_neumann_zero(T v, int m, const Policy& pol); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::bessel_traits >::result_type cyl_neumann_zero(T v, int m); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED OutputIterator cyl_neumann_zero(T v, int start_index, unsigned number_of_zeros, OutputIterator out_it); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED OutputIterator cyl_neumann_zero(T v, int start_index, unsigned number_of_zeros, OutputIterator out_it, const Policy&); - template - BOOST_MATH_GPU_ENABLED boost::math::complex >::result_type> cyl_hankel_1(T1 v, T2 x); + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex >::result_type> cyl_hankel_1(T1 v, T2 x); - template - BOOST_MATH_GPU_ENABLED boost::math::complex::result_type> cyl_hankel_1(T1 v, T2 x, const Policy& pol); + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex::result_type> cyl_hankel_1(T1 v, T2 x, const Policy& pol); - template - BOOST_MATH_GPU_ENABLED boost::math::complex::result_type> cyl_hankel_2(T1 v, T2 x, const Policy& pol); + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex::result_type> cyl_hankel_2(T1 v, T2 x, const Policy& pol); - template - BOOST_MATH_GPU_ENABLED boost::math::complex >::result_type> cyl_hankel_2(T1 v, T2 x); + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex >::result_type> cyl_hankel_2(T1 v, T2 x); - template - BOOST_MATH_GPU_ENABLED boost::math::complex::result_type> sph_hankel_1(T1 v, T2 x, const Policy& pol); + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex::result_type> sph_hankel_1(T1 v, T2 x, const Policy& pol); - template - BOOST_MATH_GPU_ENABLED boost::math::complex >::result_type> sph_hankel_1(T1 v, T2 x); + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex >::result_type> sph_hankel_1(T1 v, T2 x); - template - BOOST_MATH_GPU_ENABLED boost::math::complex::result_type> sph_hankel_2(T1 v, T2 x, const Policy& pol); + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex::result_type> sph_hankel_2(T1 v, T2 x, const Policy& pol); - template - BOOST_MATH_GPU_ENABLED boost::math::complex >::result_type> sph_hankel_2(T1 v, T2 x); + BOOST_MATH_EXPORT template + BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::complex >::result_type> sph_hankel_2(T1 v, T2 x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t airy_ai(T x, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t airy_ai(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t airy_bi(T x, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t airy_bi(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t airy_ai_prime(T x, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t airy_ai_prime(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t airy_bi_prime(T x, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t airy_bi_prime(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T airy_ai_zero(int m); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T airy_ai_zero(int m, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED OutputIterator airy_ai_zero( int start_index, unsigned number_of_zeros, OutputIterator out_it); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED OutputIterator airy_ai_zero( int start_index, unsigned number_of_zeros, OutputIterator out_it, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T airy_bi_zero(int m); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T airy_bi_zero(int m, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED OutputIterator airy_bi_zero( int start_index, unsigned number_of_zeros, OutputIterator out_it); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED OutputIterator airy_bi_zero( int start_index, unsigned number_of_zeros, OutputIterator out_it, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t sin_pi(T x, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t sin_pi(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t cos_pi(T x, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t cos_pi(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int fpclassify BOOST_NO_MACRO_EXPAND(T t); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED bool isfinite BOOST_NO_MACRO_EXPAND(T z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED bool isinf BOOST_NO_MACRO_EXPAND(T t); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED bool isnan BOOST_NO_MACRO_EXPAND(T t); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED bool isnormal BOOST_NO_MACRO_EXPAND(T t); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int signbit BOOST_NO_MACRO_EXPAND(T x); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int sign BOOST_NO_MACRO_EXPAND(const T& z); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args_permissive::type copysign BOOST_NO_MACRO_EXPAND(const T& x, const U& y); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename tools::promote_args_permissive::type changesign BOOST_NO_MACRO_EXPAND(const T& z); @@ -1003,7 +1036,7 @@ namespace boost template struct expint_result { - typedef typename boost::math::conditional< + typedef typename BOOST_MATH_NAMESPACE::conditional< policies::is_policy::value, tools::promote_args_t, typename tools::promote_args::type @@ -1012,13 +1045,13 @@ namespace boost } // namespace detail - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t expint(unsigned n, T z, const Policy&); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED typename detail::expint_result::type expint(T const z, U const u); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED tools::promote_args_t expint(T z); // Zeta: @@ -1026,162 +1059,162 @@ namespace boost tools::promote_args_t zeta(T s, const Policy&); // Owen's T function: - template + BOOST_MATH_EXPORT template tools::promote_args_t owens_t(T1 h, T2 a, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t owens_t(T1 h, T2 a); // Jacobi Functions: - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_elliptic(T k, U theta, V* pcn, V* pdn, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_elliptic(T k, U theta, V* pcn = 0, V* pdn = 0); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_sn(U k, T theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_sn(U k, T theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_cn(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_cn(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_dn(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_dn(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_cd(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_cd(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_dc(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_dc(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_ns(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_ns(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_sd(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_sd(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_ds(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_ds(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_nc(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_nc(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_nd(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_nd(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_sc(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_sc(T k, U theta); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_cs(T k, U theta, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_cs(T k, U theta); // Jacobi Theta Functions: - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta1(T z, U q, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta1(T z, U q); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta2(T z, U q, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta2(T z, U q); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta3(T z, U q, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta3(T z, U q); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta4(T z, U q, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta4(T z, U q); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta1tau(T z, U tau, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta1tau(T z, U tau); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta2tau(T z, U tau, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta2tau(T z, U tau); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta3tau(T z, U tau, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta3tau(T z, U tau); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta4tau(T z, U tau, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta4tau(T z, U tau); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta3m1(T z, U q, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta3m1(T z, U q); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta4m1(T z, U q, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta4m1(T z, U q); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta3m1tau(T z, U tau, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta3m1tau(T z, U tau); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta4m1tau(T z, U tau, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t jacobi_theta4m1tau(T z, U tau); @@ -1189,123 +1222,122 @@ namespace boost tools::promote_args_t zeta(T s); // pow: - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED BOOST_MATH_CXX14_CONSTEXPR tools::promote_args_t pow(T base, const Policy& policy); - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED BOOST_MATH_CXX14_CONSTEXPR tools::promote_args_t pow(T base); // next: - template + BOOST_MATH_EXPORT template tools::promote_args_t nextafter(const T&, const U&, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t nextafter(const T&, const U&); - template + BOOST_MATH_EXPORT template tools::promote_args_t float_next(const T&, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t float_next(const T&); - template + BOOST_MATH_EXPORT template tools::promote_args_t float_prior(const T&, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t float_prior(const T&); - template + BOOST_MATH_EXPORT template tools::promote_args_t float_distance(const T&, const U&, const Policy&); - template + BOOST_MATH_EXPORT template tools::promote_args_t float_distance(const T&, const U&); - template + BOOST_MATH_EXPORT template tools::promote_args_t float_advance(T val, int distance, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t float_advance(const T& val, int distance); - template + BOOST_MATH_EXPORT template tools::promote_args_t ulp(const T& val, const Policy& pol); - template + BOOST_MATH_EXPORT template tools::promote_args_t ulp(const T& val); - template + BOOST_MATH_EXPORT template tools::promote_args_t relative_difference(const T&, const U&); - template + BOOST_MATH_EXPORT template tools::promote_args_t epsilon_difference(const T&, const U&); - template + BOOST_MATH_EXPORT template BOOST_MATH_CONSTEXPR_TABLE_FUNCTION T unchecked_bernoulli_b2n(const std::size_t n); - template + BOOST_MATH_EXPORT template T bernoulli_b2n(const int i, const Policy &pol); - template + BOOST_MATH_EXPORT template T bernoulli_b2n(const int i); - template + BOOST_MATH_EXPORT template OutputIterator bernoulli_b2n(const int start_index, const unsigned number_of_bernoullis_b2n, OutputIterator out_it, const Policy& pol); - template + BOOST_MATH_EXPORT template OutputIterator bernoulli_b2n(const int start_index, const unsigned number_of_bernoullis_b2n, OutputIterator out_it); - template + BOOST_MATH_EXPORT template T tangent_t2n(const int i, const Policy &pol); - template + BOOST_MATH_EXPORT template T tangent_t2n(const int i); - template + BOOST_MATH_EXPORT template OutputIterator tangent_t2n(const int start_index, const unsigned number_of_bernoullis_b2n, OutputIterator out_it, const Policy& pol); - template + BOOST_MATH_EXPORT template OutputIterator tangent_t2n(const int start_index, const unsigned number_of_bernoullis_b2n, OutputIterator out_it); // Lambert W: - template - boost::math::tools::promote_args_t lambert_w0(T z, const Policy& pol); - template - boost::math::tools::promote_args_t lambert_w0(T z); - template - boost::math::tools::promote_args_t lambert_wm1(T z, const Policy& pol); - template - boost::math::tools::promote_args_t lambert_wm1(T z); - template - boost::math::tools::promote_args_t lambert_w0_prime(T z, const Policy& pol); - template - boost::math::tools::promote_args_t lambert_w0_prime(T z); - template - boost::math::tools::promote_args_t lambert_wm1_prime(T z, const Policy& pol); - template - boost::math::tools::promote_args_t lambert_wm1_prime(T z); + BOOST_MATH_EXPORT template + BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_w0(T z, const Policy& pol); + BOOST_MATH_EXPORT template + BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_w0(T z); + BOOST_MATH_EXPORT template + BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_wm1(T z, const Policy& pol); + BOOST_MATH_EXPORT template + BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_wm1(T z); + BOOST_MATH_EXPORT template + BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_w0_prime(T z, const Policy& pol); + BOOST_MATH_EXPORT template + BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_w0_prime(T z); + BOOST_MATH_EXPORT template + BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_wm1_prime(T z, const Policy& pol); + BOOST_MATH_EXPORT template + BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_wm1_prime(T z); // Hypergeometrics: - template tools::promote_args_t hypergeometric_1F0(T1 a, T2 z); - template tools::promote_args_t hypergeometric_1F0(T1 a, T2 z, const Policy&); + BOOST_MATH_EXPORT template tools::promote_args_t hypergeometric_1F0(T1 a, T2 z); + BOOST_MATH_EXPORT template tools::promote_args_t hypergeometric_1F0(T1 a, T2 z, const Policy&); - template tools::promote_args_t hypergeometric_0F1(T1 b, T2 z); - template tools::promote_args_t hypergeometric_0F1(T1 b, T2 z, const Policy&); + BOOST_MATH_EXPORT template tools::promote_args_t hypergeometric_0F1(T1 b, T2 z); + BOOST_MATH_EXPORT template tools::promote_args_t hypergeometric_0F1(T1 b, T2 z, const Policy&); - template tools::promote_args_t hypergeometric_2F0(T1 a1, T2 a2, T3 z); - template tools::promote_args_t hypergeometric_2F0(T1 a1, T2 a2, T3 z, const Policy&); + BOOST_MATH_EXPORT template tools::promote_args_t hypergeometric_2F0(T1 a1, T2 a2, T3 z); + BOOST_MATH_EXPORT template tools::promote_args_t hypergeometric_2F0(T1 a1, T2 a2, T3 z, const Policy&); - template tools::promote_args_t hypergeometric_1F1(T1 a, T2 b, T3 z); - template tools::promote_args_t hypergeometric_1F1(T1 a, T2 b, T3 z, const Policy&); + BOOST_MATH_EXPORT template tools::promote_args_t hypergeometric_1F1(T1 a, T2 b, T3 z); + BOOST_MATH_EXPORT template tools::promote_args_t hypergeometric_1F1(T1 a, T2 b, T3 z, const Policy&); - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END #define BOOST_MATH_DETAIL_LL_FUNC(Policy)\ \ template \ - BOOST_MATH_GPU_ENABLED inline T modf(const T& v, long long* ipart){ using boost::math::modf; return modf(v, ipart, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline T modf(const T& v, long long* ipart){ using BOOST_MATH_NAMESPACE::modf; return modf(v, ipart, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v){ using boost::math::lltrunc; return lltrunc(v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v){ using BOOST_MATH_NAMESPACE::lltrunc; return lltrunc(v, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline long long llround(const T& v){ using boost::math::llround; return llround(v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline long long llround(const T& v){ using BOOST_MATH_NAMESPACE::llround; return llround(v, Policy()); }\ # define BOOST_MATH_DETAIL_11_FUNC(Policy)\ template \ - inline boost::math::tools::promote_args_t hypergeometric_1F1(const T& a, const U& b, const V& z)\ - { return boost::math::hypergeometric_1F1(a, b, z, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t hypergeometric_1F1(const T& a, const U& b, const V& z)\ + { return BOOST_MATH_NAMESPACE::hypergeometric_1F1(a, b, z, Policy()); }\ #define BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(Policy)\ \ @@ -1313,610 +1345,628 @@ namespace boost BOOST_MATH_DETAIL_11_FUNC(Policy)\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - beta(RT1 a, RT2 b) { return ::boost::math::beta(a, b, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + beta(RT1 a, RT2 b) { return ::BOOST_MATH_NAMESPACE::beta(a, b, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - beta(RT1 a, RT2 b, A x){ return ::boost::math::beta(a, b, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + beta(RT1 a, RT2 b, A x){ return ::BOOST_MATH_NAMESPACE::beta(a, b, x, Policy()); }\ +\ + template \ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + lbeta(RT1 a, RT2 b) { return ::BOOST_MATH_NAMESPACE::lbeta(a, b, Policy()); }\ +\ + template \ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + betac(RT1 a, RT2 b, RT3 x) { return ::BOOST_MATH_NAMESPACE::betac(a, b, x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - betac(RT1 a, RT2 b, RT3 x) { return ::boost::math::betac(a, b, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibeta(RT1 a, RT2 b, RT3 x){ return ::BOOST_MATH_NAMESPACE::ibeta(a, b, x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibeta(RT1 a, RT2 b, RT3 x){ return ::boost::math::ibeta(a, b, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibetac(RT1 a, RT2 b, RT3 x){ return ::BOOST_MATH_NAMESPACE::ibetac(a, b, x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibetac(RT1 a, RT2 b, RT3 x){ return ::boost::math::ibetac(a, b, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + libeta(RT1 a, RT2 b, RT3 x){ return ::BOOST_MATH_NAMESPACE::libeta(a, b, x, Policy()); }\ +\ + template \ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + libetac(RT1 a, RT2 b, RT3 x){ return ::BOOST_MATH_NAMESPACE::libetac(a, b, x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibeta_inv(T1 a, T2 b, T3 p, T4* py){ return ::boost::math::ibeta_inv(a, b, p, py, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibeta_inv(T1 a, T2 b, T3 p, T4* py){ return ::BOOST_MATH_NAMESPACE::ibeta_inv(a, b, p, py, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibeta_inv(RT1 a, RT2 b, RT3 p){ return ::boost::math::ibeta_inv(a, b, p, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibeta_inv(RT1 a, RT2 b, RT3 p){ return ::BOOST_MATH_NAMESPACE::ibeta_inv(a, b, p, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibetac_inv(T1 a, T2 b, T3 q, T4* py){ return ::boost::math::ibetac_inv(a, b, q, py, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibetac_inv(T1 a, T2 b, T3 q, T4* py){ return ::BOOST_MATH_NAMESPACE::ibetac_inv(a, b, q, py, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibeta_inva(RT1 a, RT2 b, RT3 p){ return ::boost::math::ibeta_inva(a, b, p, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibeta_inva(RT1 a, RT2 b, RT3 p){ return ::BOOST_MATH_NAMESPACE::ibeta_inva(a, b, p, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibetac_inva(T1 a, T2 b, T3 q){ return ::boost::math::ibetac_inva(a, b, q, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibetac_inva(T1 a, T2 b, T3 q){ return ::BOOST_MATH_NAMESPACE::ibetac_inva(a, b, q, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibeta_invb(RT1 a, RT2 b, RT3 p){ return ::boost::math::ibeta_invb(a, b, p, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibeta_invb(RT1 a, RT2 b, RT3 p){ return ::BOOST_MATH_NAMESPACE::ibeta_invb(a, b, p, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibetac_invb(T1 a, T2 b, T3 q){ return ::boost::math::ibetac_invb(a, b, q, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibetac_invb(T1 a, T2 b, T3 q){ return ::BOOST_MATH_NAMESPACE::ibetac_invb(a, b, q, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibetac_inv(RT1 a, RT2 b, RT3 q){ return ::boost::math::ibetac_inv(a, b, q, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibetac_inv(RT1 a, RT2 b, RT3 q){ return ::BOOST_MATH_NAMESPACE::ibetac_inv(a, b, q, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ibeta_derivative(RT1 a, RT2 b, RT3 x){ return ::boost::math::ibeta_derivative(a, b, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ibeta_derivative(RT1 a, RT2 b, RT3 x){ return ::BOOST_MATH_NAMESPACE::ibeta_derivative(a, b, x, Policy()); }\ \ - template BOOST_MATH_GPU_ENABLED T binomial_coefficient(unsigned n, unsigned k){ return ::boost::math::binomial_coefficient(n, k, Policy()); }\ + template BOOST_MATH_GPU_ENABLED T binomial_coefficient(unsigned n, unsigned k){ return ::BOOST_MATH_NAMESPACE::binomial_coefficient(n, k, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t erf(RT z) { return ::boost::math::erf(z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t erf(RT z) { return ::BOOST_MATH_NAMESPACE::erf(z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t erfc(RT z){ return ::boost::math::erfc(z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t erfc(RT z){ return ::BOOST_MATH_NAMESPACE::erfc(z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t erf_inv(RT z) { return ::boost::math::erf_inv(z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t erf_inv(RT z) { return ::BOOST_MATH_NAMESPACE::erf_inv(z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t erfc_inv(RT z){ return ::boost::math::erfc_inv(z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t erfc_inv(RT z){ return ::BOOST_MATH_NAMESPACE::erfc_inv(z, Policy()); }\ \ - using boost::math::legendre_next;\ + using BOOST_MATH_NAMESPACE::legendre_next;\ \ template \ - inline boost::math::tools::promote_args_t \ - legendre_p(int l, T x){ return ::boost::math::legendre_p(l, x, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + legendre_p(int l, T x){ return ::BOOST_MATH_NAMESPACE::legendre_p(l, x, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t \ - legendre_p_prime(int l, T x){ return ::boost::math::legendre_p(l, x, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + legendre_p_prime(int l, T x){ return ::BOOST_MATH_NAMESPACE::legendre_p(l, x, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t \ - legendre_q(unsigned l, T x){ return ::boost::math::legendre_q(l, x, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + legendre_q(unsigned l, T x){ return ::BOOST_MATH_NAMESPACE::legendre_q(l, x, Policy()); }\ \ - using ::boost::math::legendre_next;\ + using ::BOOST_MATH_NAMESPACE::legendre_next;\ \ template \ - inline boost::math::tools::promote_args_t \ - legendre_p(int l, int m, T x){ return ::boost::math::legendre_p(l, m, x, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + legendre_p(int l, int m, T x){ return ::BOOST_MATH_NAMESPACE::legendre_p(l, m, x, Policy()); }\ \ - using ::boost::math::laguerre_next;\ + using ::BOOST_MATH_NAMESPACE::laguerre_next;\ \ template \ - inline boost::math::tools::promote_args_t \ - laguerre(unsigned n, T x){ return ::boost::math::laguerre(n, x, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + laguerre(unsigned n, T x){ return ::BOOST_MATH_NAMESPACE::laguerre(n, x, Policy()); }\ \ template \ - inline typename boost::math::laguerre_result::type \ - laguerre(unsigned n, T1 m, T2 x) { return ::boost::math::laguerre(n, m, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::laguerre_result::type \ + laguerre(unsigned n, T1 m, T2 x) { return ::BOOST_MATH_NAMESPACE::laguerre(n, m, x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - hermite(unsigned n, T x){ return ::boost::math::hermite(n, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + hermite(unsigned n, T x){ return ::BOOST_MATH_NAMESPACE::hermite(n, x, Policy()); }\ \ - using boost::math::hermite_next;\ + using BOOST_MATH_NAMESPACE::hermite_next;\ \ - using boost::math::chebyshev_next;\ + using BOOST_MATH_NAMESPACE::chebyshev_next;\ \ template\ - Real chebyshev_t(unsigned n, Real const & x){ return ::boost::math::chebyshev_t(n, x, Policy()); }\ + Real chebyshev_t(unsigned n, Real const & x){ return ::BOOST_MATH_NAMESPACE::chebyshev_t(n, x, Policy()); }\ \ template\ - Real chebyshev_u(unsigned n, Real const & x){ return ::boost::math::chebyshev_u(n, x, Policy()); }\ + Real chebyshev_u(unsigned n, Real const & x){ return ::BOOST_MATH_NAMESPACE::chebyshev_u(n, x, Policy()); }\ \ template\ - Real chebyshev_t_prime(unsigned n, Real const & x){ return ::boost::math::chebyshev_t_prime(n, x, Policy()); }\ + Real chebyshev_t_prime(unsigned n, Real const & x){ return ::BOOST_MATH_NAMESPACE::chebyshev_t_prime(n, x, Policy()); }\ \ - using ::boost::math::chebyshev_clenshaw_recurrence;\ + using ::BOOST_MATH_NAMESPACE::chebyshev_clenshaw_recurrence;\ \ template \ - inline std::complex> \ - spherical_harmonic(unsigned n, int m, T1 theta, T2 phi){ return boost::math::spherical_harmonic(n, m, theta, phi, Policy()); }\ + inline std::complex> \ + spherical_harmonic(unsigned n, int m, T1 theta, T2 phi){ return BOOST_MATH_NAMESPACE::spherical_harmonic(n, m, theta, phi, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t \ - spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi){ return ::boost::math::spherical_harmonic_r(n, m, theta, phi, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi){ return ::BOOST_MATH_NAMESPACE::spherical_harmonic_r(n, m, theta, phi, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t \ - spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi){ return boost::math::spherical_harmonic_i(n, m, theta, phi, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi){ return BOOST_MATH_NAMESPACE::spherical_harmonic_i(n, m, theta, phi, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t \ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi, const Policy& pol);\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ellint_rf(T1 x, T2 y, T3 z){ return ::boost::math::ellint_rf(x, y, z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ellint_rf(T1 x, T2 y, T3 z){ return ::BOOST_MATH_NAMESPACE::ellint_rf(x, y, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ellint_rd(T1 x, T2 y, T3 z){ return ::boost::math::ellint_rd(x, y, z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ellint_rd(T1 x, T2 y, T3 z){ return ::BOOST_MATH_NAMESPACE::ellint_rd(x, y, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ellint_rc(T1 x, T2 y){ return ::boost::math::ellint_rc(x, y, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ellint_rc(T1 x, T2 y){ return ::BOOST_MATH_NAMESPACE::ellint_rc(x, y, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ellint_rj(T1 x, T2 y, T3 z, T4 p){ return boost::math::ellint_rj(x, y, z, p, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ellint_rj(T1 x, T2 y, T3 z, T4 p){ return BOOST_MATH_NAMESPACE::ellint_rj(x, y, z, p, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t \ - ellint_rg(T1 x, T2 y, T3 z){ return ::boost::math::ellint_rg(x, y, z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + ellint_rg(T1 x, T2 y, T3 z){ return ::BOOST_MATH_NAMESPACE::ellint_rg(x, y, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t ellint_2(T k){ return boost::math::ellint_2(k, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ellint_2(T k){ return BOOST_MATH_NAMESPACE::ellint_2(k, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t ellint_2(T1 k, T2 phi){ return boost::math::ellint_2(k, phi, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ellint_2(T1 k, T2 phi){ return BOOST_MATH_NAMESPACE::ellint_2(k, phi, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t ellint_d(T k){ return boost::math::ellint_d(k, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ellint_d(T k){ return BOOST_MATH_NAMESPACE::ellint_d(k, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t ellint_d(T1 k, T2 phi){ return boost::math::ellint_d(k, phi, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ellint_d(T1 k, T2 phi){ return BOOST_MATH_NAMESPACE::ellint_d(k, phi, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t jacobi_zeta(T1 k, T2 phi){ return boost::math::jacobi_zeta(k, phi, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_zeta(T1 k, T2 phi){ return BOOST_MATH_NAMESPACE::jacobi_zeta(k, phi, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t heuman_lambda(T1 k, T2 phi){ return boost::math::heuman_lambda(k, phi, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t heuman_lambda(T1 k, T2 phi){ return BOOST_MATH_NAMESPACE::heuman_lambda(k, phi, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t ellint_1(T k){ return boost::math::ellint_1(k, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ellint_1(T k){ return BOOST_MATH_NAMESPACE::ellint_1(k, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t ellint_1(T1 k, T2 phi){ return boost::math::ellint_1(k, phi, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ellint_1(T1 k, T2 phi){ return BOOST_MATH_NAMESPACE::ellint_1(k, phi, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t ellint_3(T1 k, T2 v, T3 phi){ return boost::math::ellint_3(k, v, phi, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ellint_3(T1 k, T2 v, T3 phi){ return BOOST_MATH_NAMESPACE::ellint_3(k, v, phi, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t ellint_3(T1 k, T2 v){ return boost::math::ellint_3(k, v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ellint_3(T1 k, T2 v){ return BOOST_MATH_NAMESPACE::ellint_3(k, v, Policy()); }\ \ - using boost::math::max_factorial;\ + using BOOST_MATH_NAMESPACE::max_factorial;\ template \ - BOOST_MATH_GPU_ENABLED inline RT factorial(unsigned int i) { return boost::math::factorial(i, Policy()); }\ - using boost::math::unchecked_factorial;\ + BOOST_MATH_GPU_ENABLED inline RT factorial(unsigned int i) { return BOOST_MATH_NAMESPACE::factorial(i, Policy()); }\ + using BOOST_MATH_NAMESPACE::unchecked_factorial;\ template \ - BOOST_MATH_GPU_ENABLED inline RT double_factorial(unsigned i){ return boost::math::double_factorial(i, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline RT double_factorial(unsigned i){ return BOOST_MATH_NAMESPACE::double_factorial(i, Policy()); }\ template \ - inline boost::math::tools::promote_args_t falling_factorial(RT x, unsigned n){ return boost::math::falling_factorial(x, n, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t falling_factorial(RT x, unsigned n){ return BOOST_MATH_NAMESPACE::falling_factorial(x, n, Policy()); }\ template \ - inline boost::math::tools::promote_args_t rising_factorial(RT x, unsigned n){ return boost::math::rising_factorial(x, n, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t rising_factorial(RT x, unsigned n){ return BOOST_MATH_NAMESPACE::rising_factorial(x, n, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t tgamma(RT z){ return boost::math::tgamma(z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t tgamma(RT z){ return BOOST_MATH_NAMESPACE::tgamma(z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t tgamma1pm1(RT z){ return boost::math::tgamma1pm1(z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t tgamma1pm1(RT z){ return BOOST_MATH_NAMESPACE::tgamma1pm1(z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t tgamma(RT1 a, RT2 z){ return boost::math::tgamma(a, z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t tgamma(RT1 a, RT2 z){ return BOOST_MATH_NAMESPACE::tgamma(a, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t lgamma(RT z, int* sign){ return boost::math::lgamma(z, sign, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t lgamma(RT z, int* sign){ return BOOST_MATH_NAMESPACE::lgamma(z, sign, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t lgamma(RT x){ return boost::math::lgamma(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t lgamma(RT x){ return BOOST_MATH_NAMESPACE::lgamma(x, Policy()); }\ +\ + template \ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t tgamma_lower(RT1 a, RT2 z){ return BOOST_MATH_NAMESPACE::tgamma_lower(a, z, Policy()); }\ +\ + template \ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t gamma_q(RT1 a, RT2 z){ return BOOST_MATH_NAMESPACE::gamma_q(a, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t tgamma_lower(RT1 a, RT2 z){ return boost::math::tgamma_lower(a, z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t lgamma_q(RT1 a, RT2 z){ return BOOST_MATH_NAMESPACE::lgamma_q(a, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t gamma_q(RT1 a, RT2 z){ return boost::math::gamma_q(a, z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t lgamma_p(RT1 a, RT2 z){ return BOOST_MATH_NAMESPACE::lgamma_p(a, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t lgamma_q(RT1 a, RT2 z){ return boost::math::lgamma_q(a, z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ligamma(RT1 a, RT2 z){ return BOOST_MATH_NAMESPACE::ligamma(a, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t lgamma_p(RT1 a, RT2 z){ return boost::math::lgamma_p(a, z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t ligamma_lower(RT1 a, RT2 z){ return BOOST_MATH_NAMESPACE::ligamma_lower(a, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t gamma_p(RT1 a, RT2 z){ return boost::math::gamma_p(a, z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t gamma_p(RT1 a, RT2 z){ return BOOST_MATH_NAMESPACE::gamma_p(a, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta){ return boost::math::tgamma_delta_ratio(z, delta, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t tgamma_delta_ratio(T1 z, T2 delta){ return BOOST_MATH_NAMESPACE::tgamma_delta_ratio(z, delta, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t tgamma_ratio(T1 a, T2 b) { return boost::math::tgamma_ratio(a, b, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t tgamma_ratio(T1 a, T2 b) { return BOOST_MATH_NAMESPACE::tgamma_ratio(a, b, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t gamma_p_derivative(T1 a, T2 x){ return boost::math::gamma_p_derivative(a, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t gamma_p_derivative(T1 a, T2 x){ return BOOST_MATH_NAMESPACE::gamma_p_derivative(a, x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t gamma_p_inv(T1 a, T2 p){ return boost::math::gamma_p_inv(a, p, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t gamma_p_inv(T1 a, T2 p){ return BOOST_MATH_NAMESPACE::gamma_p_inv(a, p, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t gamma_p_inva(T1 a, T2 p){ return boost::math::gamma_p_inva(a, p, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t gamma_p_inva(T1 a, T2 p){ return BOOST_MATH_NAMESPACE::gamma_p_inva(a, p, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t gamma_q_inv(T1 a, T2 q){ return boost::math::gamma_q_inv(a, q, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t gamma_q_inv(T1 a, T2 q){ return BOOST_MATH_NAMESPACE::gamma_q_inv(a, q, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t gamma_q_inva(T1 a, T2 q){ return boost::math::gamma_q_inva(a, q, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t gamma_q_inva(T1 a, T2 q){ return BOOST_MATH_NAMESPACE::gamma_q_inva(a, q, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t digamma(T x){ return boost::math::digamma(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t digamma(T x){ return BOOST_MATH_NAMESPACE::digamma(x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t trigamma(T x){ return boost::math::trigamma(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t trigamma(T x){ return BOOST_MATH_NAMESPACE::trigamma(x, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t polygamma(int n, T x){ return boost::math::polygamma(n, x, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t polygamma(int n, T x){ return BOOST_MATH_NAMESPACE::polygamma(n, x, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t \ - BOOST_MATH_GPU_ENABLED hypot(T1 x, T2 y){ return boost::math::hypot(x, y, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + BOOST_MATH_GPU_ENABLED hypot(T1 x, T2 y){ return BOOST_MATH_NAMESPACE::hypot(x, y, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t cbrt(RT z){ return boost::math::cbrt(z, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t cbrt(RT z){ return BOOST_MATH_NAMESPACE::cbrt(z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t log1p(T x){ return boost::math::log1p(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t log1p(T x){ return BOOST_MATH_NAMESPACE::log1p(x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t log1pmx(T x){ return boost::math::log1pmx(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t log1pmx(T x){ return BOOST_MATH_NAMESPACE::log1pmx(x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t expm1(T x){ return boost::math::expm1(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t expm1(T x){ return BOOST_MATH_NAMESPACE::expm1(x, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t \ - BOOST_MATH_GPU_ENABLED powm1(const T1 a, const T2 z){ return boost::math::powm1(a, z, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t \ + BOOST_MATH_GPU_ENABLED powm1(const T1 a, const T2 z){ return BOOST_MATH_NAMESPACE::powm1(a, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t sqrt1pm1(const T& val){ return boost::math::sqrt1pm1(val, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t sqrt1pm1(const T& val){ return BOOST_MATH_NAMESPACE::sqrt1pm1(val, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t sinc_pi(T x){ return boost::math::sinc_pi(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t sinc_pi(T x){ return BOOST_MATH_NAMESPACE::sinc_pi(x, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t sinhc_pi(T x){ return boost::math::sinhc_pi(x, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t sinhc_pi(T x){ return BOOST_MATH_NAMESPACE::sinhc_pi(x, Policy()); }\ \ template\ - inline boost::math::tools::promote_args_t asinh(const T x){ return boost::math::asinh(x, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t asinh(const T x){ return BOOST_MATH_NAMESPACE::asinh(x, Policy()); }\ \ template\ - inline boost::math::tools::promote_args_t acosh(const T x){ return boost::math::acosh(x, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t acosh(const T x){ return BOOST_MATH_NAMESPACE::acosh(x, Policy()); }\ \ template\ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t atanh(const T x){ return boost::math::atanh(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t atanh(const T x){ return BOOST_MATH_NAMESPACE::atanh(x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type cyl_bessel_j(T1 v, T2 x)\ - { return boost::math::cyl_bessel_j(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type cyl_bessel_j(T1 v, T2 x)\ + { return BOOST_MATH_NAMESPACE::cyl_bessel_j(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type cyl_bessel_j_prime(T1 v, T2 x)\ - { return boost::math::cyl_bessel_j_prime(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type cyl_bessel_j_prime(T1 v, T2 x)\ + { return BOOST_MATH_NAMESPACE::cyl_bessel_j_prime(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type sph_bessel(unsigned v, T x)\ - { return boost::math::sph_bessel(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type sph_bessel(unsigned v, T x)\ + { return BOOST_MATH_NAMESPACE::sph_bessel(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type sph_bessel_prime(unsigned v, T x)\ - { return boost::math::sph_bessel_prime(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type sph_bessel_prime(unsigned v, T x)\ + { return BOOST_MATH_NAMESPACE::sph_bessel_prime(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type \ - cyl_bessel_i(T1 v, T2 x) { return boost::math::cyl_bessel_i(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type \ + cyl_bessel_i(T1 v, T2 x) { return BOOST_MATH_NAMESPACE::cyl_bessel_i(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type \ - cyl_bessel_i_prime(T1 v, T2 x) { return boost::math::cyl_bessel_i_prime(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type \ + cyl_bessel_i_prime(T1 v, T2 x) { return BOOST_MATH_NAMESPACE::cyl_bessel_i_prime(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type \ - cyl_bessel_k(T1 v, T2 x) { return boost::math::cyl_bessel_k(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type \ + cyl_bessel_k(T1 v, T2 x) { return BOOST_MATH_NAMESPACE::cyl_bessel_k(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type \ - cyl_bessel_k_prime(T1 v, T2 x) { return boost::math::cyl_bessel_k_prime(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type \ + cyl_bessel_k_prime(T1 v, T2 x) { return BOOST_MATH_NAMESPACE::cyl_bessel_k_prime(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type \ - cyl_neumann(T1 v, T2 x){ return boost::math::cyl_neumann(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type \ + cyl_neumann(T1 v, T2 x){ return BOOST_MATH_NAMESPACE::cyl_neumann(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type \ - cyl_neumann_prime(T1 v, T2 x){ return boost::math::cyl_neumann_prime(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type \ + cyl_neumann_prime(T1 v, T2 x){ return BOOST_MATH_NAMESPACE::cyl_neumann_prime(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type \ - sph_neumann(unsigned v, T x){ return boost::math::sph_neumann(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type \ + sph_neumann(unsigned v, T x){ return BOOST_MATH_NAMESPACE::sph_neumann(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type \ - sph_neumann_prime(unsigned v, T x){ return boost::math::sph_neumann_prime(v, x, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type \ + sph_neumann_prime(unsigned v, T x){ return BOOST_MATH_NAMESPACE::sph_neumann_prime(v, x, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type cyl_bessel_j_zero(T v, int m)\ - { return boost::math::cyl_bessel_j_zero(v, m, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type cyl_bessel_j_zero(T v, int m)\ + { return BOOST_MATH_NAMESPACE::cyl_bessel_j_zero(v, m, Policy()); }\ \ template \ inline void cyl_bessel_j_zero(T v,\ int start_index,\ unsigned number_of_zeros,\ OutputIterator out_it)\ - { boost::math::cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, Policy()); }\ + { BOOST_MATH_NAMESPACE::cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, Policy()); }\ \ template \ - inline typename boost::math::detail::bessel_traits::result_type cyl_neumann_zero(T v, int m)\ - { return boost::math::cyl_neumann_zero(v, m, Policy()); }\ + inline typename BOOST_MATH_NAMESPACE::detail::bessel_traits::result_type cyl_neumann_zero(T v, int m)\ + { return BOOST_MATH_NAMESPACE::cyl_neumann_zero(v, m, Policy()); }\ \ template \ inline void cyl_neumann_zero(T v,\ int start_index,\ unsigned number_of_zeros,\ OutputIterator out_it)\ - { boost::math::cyl_neumann_zero(v, start_index, number_of_zeros, out_it, Policy()); }\ + { BOOST_MATH_NAMESPACE::cyl_neumann_zero(v, start_index, number_of_zeros, out_it, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t sin_pi(T x){ return boost::math::sin_pi(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t sin_pi(T x){ return BOOST_MATH_NAMESPACE::sin_pi(x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t cos_pi(T x){ return boost::math::cos_pi(x, Policy()); }\ -\ - using boost::math::fpclassify;\ - using boost::math::isfinite;\ - using boost::math::isinf;\ - using boost::math::isnan;\ - using boost::math::isnormal;\ - using boost::math::signbit;\ - using boost::math::sign;\ - using boost::math::copysign;\ - using boost::math::changesign;\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t cos_pi(T x){ return BOOST_MATH_NAMESPACE::cos_pi(x, Policy()); }\ +\ + using BOOST_MATH_NAMESPACE::fpclassify;\ + using BOOST_MATH_NAMESPACE::isfinite;\ + using BOOST_MATH_NAMESPACE::isinf;\ + using BOOST_MATH_NAMESPACE::isnan;\ + using BOOST_MATH_NAMESPACE::isnormal;\ + using BOOST_MATH_NAMESPACE::signbit;\ + using BOOST_MATH_NAMESPACE::sign;\ + using BOOST_MATH_NAMESPACE::copysign;\ + using BOOST_MATH_NAMESPACE::changesign;\ \ template \ - BOOST_MATH_GPU_ENABLED inline typename boost::math::tools::promote_args_t expint(T const& z, U const& u)\ - { return boost::math::expint(z, u, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline typename BOOST_MATH_NAMESPACE::tools::promote_args_t expint(T const& z, U const& u)\ + { return BOOST_MATH_NAMESPACE::expint(z, u, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t expint(T z){ return boost::math::expint(z, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t expint(T z){ return BOOST_MATH_NAMESPACE::expint(z, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t zeta(T s){ return boost::math::zeta(s, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t zeta(T s){ return BOOST_MATH_NAMESPACE::zeta(s, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline T round(const T& v){ using boost::math::round; return round(v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline T round(const T& v){ using BOOST_MATH_NAMESPACE::round; return round(v, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline int iround(const T& v){ using boost::math::iround; return iround(v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline int iround(const T& v){ using BOOST_MATH_NAMESPACE::iround; return iround(v, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline long lround(const T& v){ using boost::math::lround; return lround(v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline long lround(const T& v){ using BOOST_MATH_NAMESPACE::lround; return lround(v, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline T trunc(const T& v){ using boost::math::trunc; return trunc(v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline T trunc(const T& v){ using BOOST_MATH_NAMESPACE::trunc; return trunc(v, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v){ using boost::math::itrunc; return itrunc(v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v){ using BOOST_MATH_NAMESPACE::itrunc; return itrunc(v, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v){ using boost::math::ltrunc; return ltrunc(v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v){ using BOOST_MATH_NAMESPACE::ltrunc; return ltrunc(v, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline T modf(const T& v, T* ipart){ using boost::math::modf; return modf(v, ipart, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline T modf(const T& v, T* ipart){ using BOOST_MATH_NAMESPACE::modf; return modf(v, ipart, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline T modf(const T& v, int* ipart){ using boost::math::modf; return modf(v, ipart, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline T modf(const T& v, int* ipart){ using BOOST_MATH_NAMESPACE::modf; return modf(v, ipart, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline T modf(const T& v, long* ipart){ using boost::math::modf; return modf(v, ipart, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline T modf(const T& v, long* ipart){ using BOOST_MATH_NAMESPACE::modf; return modf(v, ipart, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t pow(T v){ return boost::math::pow(v, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t pow(T v){ return BOOST_MATH_NAMESPACE::pow(v, Policy()); }\ \ - template T nextafter(const T& a, const T& b){ return static_cast(boost::math::nextafter(a, b, Policy())); }\ - template T float_next(const T& a){ return static_cast(boost::math::float_next(a, Policy())); }\ - template T float_prior(const T& a){ return static_cast(boost::math::float_prior(a, Policy())); }\ - template T float_distance(const T& a, const T& b){ return static_cast(boost::math::float_distance(a, b, Policy())); }\ - template T ulp(const T& a){ return static_cast(boost::math::ulp(a, Policy())); }\ + template T nextafter(const T& a, const T& b){ return static_cast(BOOST_MATH_NAMESPACE::nextafter(a, b, Policy())); }\ + template T float_next(const T& a){ return static_cast(BOOST_MATH_NAMESPACE::float_next(a, Policy())); }\ + template T float_prior(const T& a){ return static_cast(BOOST_MATH_NAMESPACE::float_prior(a, Policy())); }\ + template T float_distance(const T& a, const T& b){ return static_cast(BOOST_MATH_NAMESPACE::float_distance(a, b, Policy())); }\ + template T ulp(const T& a){ return static_cast(BOOST_MATH_NAMESPACE::ulp(a, Policy())); }\ \ template \ - inline boost::math::tools::promote_args_t owens_t(RT1 a, RT2 z){ return boost::math::owens_t(a, z, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t owens_t(RT1 a, RT2 z){ return BOOST_MATH_NAMESPACE::owens_t(a, z, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::complex::result_type> cyl_hankel_1(T1 v, T2 x)\ - { return boost::math::cyl_hankel_1(v, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex::result_type> cyl_hankel_1(T1 v, T2 x)\ + { return BOOST_MATH_NAMESPACE::cyl_hankel_1(v, x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::complex::result_type> cyl_hankel_2(T1 v, T2 x)\ - { return boost::math::cyl_hankel_2(v, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex::result_type> cyl_hankel_2(T1 v, T2 x)\ + { return BOOST_MATH_NAMESPACE::cyl_hankel_2(v, x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::complex::result_type> sph_hankel_1(T1 v, T2 x)\ - { return boost::math::sph_hankel_1(v, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex::result_type> sph_hankel_1(T1 v, T2 x)\ + { return BOOST_MATH_NAMESPACE::sph_hankel_1(v, x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::complex::result_type> sph_hankel_2(T1 v, T2 x)\ - { return boost::math::sph_hankel_2(v, x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::complex::result_type> sph_hankel_2(T1 v, T2 x)\ + { return BOOST_MATH_NAMESPACE::sph_hankel_2(v, x, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_elliptic(T k, T theta, T* pcn, T* pdn)\ - { return static_cast>(boost::math::jacobi_elliptic(k, theta, pcn, pdn, Policy())); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_elliptic(T k, T theta, T* pcn, T* pdn)\ + { return static_cast>(BOOST_MATH_NAMESPACE::jacobi_elliptic(k, theta, pcn, pdn, Policy())); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_sn(U k, T theta)\ - { return boost::math::jacobi_sn(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_sn(U k, T theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_sn(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_cn(T k, U theta)\ - { return boost::math::jacobi_cn(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_cn(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_cn(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_dn(T k, U theta)\ - { return boost::math::jacobi_dn(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_dn(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_dn(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_cd(T k, U theta)\ - { return boost::math::jacobi_cd(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_cd(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_cd(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_dc(T k, U theta)\ - { return boost::math::jacobi_dc(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_dc(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_dc(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_ns(T k, U theta)\ - { return boost::math::jacobi_ns(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_ns(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_ns(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_sd(T k, U theta)\ - { return boost::math::jacobi_sd(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_sd(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_sd(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_ds(T k, U theta)\ - { return boost::math::jacobi_ds(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_ds(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_ds(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_nc(T k, U theta)\ - { return boost::math::jacobi_nc(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_nc(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_nc(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_nd(T k, U theta)\ - { return boost::math::jacobi_nd(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_nd(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_nd(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_sc(T k, U theta)\ - { return boost::math::jacobi_sc(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_sc(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_sc(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_cs(T k, U theta)\ - { return boost::math::jacobi_cs(k, theta, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_cs(T k, U theta)\ + { return BOOST_MATH_NAMESPACE::jacobi_cs(k, theta, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta1(T z, U q)\ - { return boost::math::jacobi_theta1(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta1(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta1(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta2(T z, U q)\ - { return boost::math::jacobi_theta2(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta2(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta2(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta3(T z, U q)\ - { return boost::math::jacobi_theta3(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta3(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta3(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta4(T z, U q)\ - { return boost::math::jacobi_theta4(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta4(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta4(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta1tau(T z, U q)\ - { return boost::math::jacobi_theta1tau(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta1tau(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta1tau(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta2tau(T z, U q)\ - { return boost::math::jacobi_theta2tau(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta2tau(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta2tau(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta3tau(T z, U q)\ - { return boost::math::jacobi_theta3tau(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta3tau(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta3tau(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta4tau(T z, U q)\ - { return boost::math::jacobi_theta4tau(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta4tau(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta4tau(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta3m1(T z, U q)\ - { return boost::math::jacobi_theta3m1(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta3m1(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta3m1(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta4m1(T z, U q)\ - { return boost::math::jacobi_theta4m1(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta4m1(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta4m1(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta3m1tau(T z, U q)\ - { return boost::math::jacobi_theta3m1tau(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta3m1tau(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta3m1tau(z, q, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t jacobi_theta4m1tau(T z, U q)\ - { return boost::math::jacobi_theta4m1tau(z, q, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t jacobi_theta4m1tau(T z, U q)\ + { return BOOST_MATH_NAMESPACE::jacobi_theta4m1tau(z, q, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t airy_ai(T x)\ - { return boost::math::airy_ai(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t airy_ai(T x)\ + { return BOOST_MATH_NAMESPACE::airy_ai(x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t airy_bi(T x)\ - { return boost::math::airy_bi(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t airy_bi(T x)\ + { return BOOST_MATH_NAMESPACE::airy_bi(x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t airy_ai_prime(T x)\ - { return boost::math::airy_ai_prime(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t airy_ai_prime(T x)\ + { return BOOST_MATH_NAMESPACE::airy_ai_prime(x, Policy()); }\ \ template \ - BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t airy_bi_prime(T x)\ - { return boost::math::airy_bi_prime(x, Policy()); }\ + BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::tools::promote_args_t airy_bi_prime(T x)\ + { return BOOST_MATH_NAMESPACE::airy_bi_prime(x, Policy()); }\ \ template \ BOOST_MATH_GPU_ENABLED inline T airy_ai_zero(int m)\ - { return boost::math::airy_ai_zero(m, Policy()); }\ + { return BOOST_MATH_NAMESPACE::airy_ai_zero(m, Policy()); }\ template \ BOOST_MATH_GPU_ENABLED OutputIterator airy_ai_zero(int start_index, unsigned number_of_zeros, OutputIterator out_it)\ - { return boost::math::airy_ai_zero(start_index, number_of_zeros, out_it, Policy()); }\ + { return BOOST_MATH_NAMESPACE::airy_ai_zero(start_index, number_of_zeros, out_it, Policy()); }\ \ template \ BOOST_MATH_GPU_ENABLED inline T airy_bi_zero(int m)\ - { return boost::math::airy_bi_zero(m, Policy()); }\ + { return BOOST_MATH_NAMESPACE::airy_bi_zero(m, Policy()); }\ template \ BOOST_MATH_GPU_ENABLED OutputIterator airy_bi_zero(int start_index, unsigned number_of_zeros, OutputIterator out_it)\ - { return boost::math::airy_bi_zero(start_index, number_of_zeros, out_it, Policy()); }\ + { return BOOST_MATH_NAMESPACE::airy_bi_zero(start_index, number_of_zeros, out_it, Policy()); }\ \ template \ T bernoulli_b2n(const int i)\ - { return boost::math::bernoulli_b2n(i, Policy()); }\ + { return BOOST_MATH_NAMESPACE::bernoulli_b2n(i, Policy()); }\ template \ OutputIterator bernoulli_b2n(int start_index, unsigned number_of_bernoullis_b2n, OutputIterator out_it)\ - { return boost::math::bernoulli_b2n(start_index, number_of_bernoullis_b2n, out_it, Policy()); }\ + { return BOOST_MATH_NAMESPACE::bernoulli_b2n(start_index, number_of_bernoullis_b2n, out_it, Policy()); }\ \ template \ T tangent_t2n(const int i)\ - { return boost::math::tangent_t2n(i, Policy()); }\ + { return BOOST_MATH_NAMESPACE::tangent_t2n(i, Policy()); }\ template \ OutputIterator tangent_t2n(int start_index, unsigned number_of_bernoullis_b2n, OutputIterator out_it)\ - { return boost::math::tangent_t2n(start_index, number_of_bernoullis_b2n, out_it, Policy()); }\ + { return BOOST_MATH_NAMESPACE::tangent_t2n(start_index, number_of_bernoullis_b2n, out_it, Policy()); }\ \ - template inline boost::math::tools::promote_args_t lambert_w0(T z) { return boost::math::lambert_w0(z, Policy()); }\ - template inline boost::math::tools::promote_args_t lambert_wm1(T z) { return boost::math::lambert_w0(z, Policy()); }\ - template inline boost::math::tools::promote_args_t lambert_w0_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\ - template inline boost::math::tools::promote_args_t lambert_wm1_prime(T z) { return boost::math::lambert_w0(z, Policy()); }\ + template inline BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_w0(T z) { return BOOST_MATH_NAMESPACE::lambert_w0(z, Policy()); }\ + template inline BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_wm1(T z) { return BOOST_MATH_NAMESPACE::lambert_w0(z, Policy()); }\ + template inline BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_w0_prime(T z) { return BOOST_MATH_NAMESPACE::lambert_w0(z, Policy()); }\ + template inline BOOST_MATH_NAMESPACE::tools::promote_args_t lambert_wm1_prime(T z) { return BOOST_MATH_NAMESPACE::lambert_w0(z, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t hypergeometric_1F0(const T& a, const U& z)\ - { return boost::math::hypergeometric_1F0(a, z, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t hypergeometric_1F0(const T& a, const U& z)\ + { return BOOST_MATH_NAMESPACE::hypergeometric_1F0(a, z, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t hypergeometric_0F1(const T& a, const U& z)\ - { return boost::math::hypergeometric_0F1(a, z, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t hypergeometric_0F1(const T& a, const U& z)\ + { return BOOST_MATH_NAMESPACE::hypergeometric_0F1(a, z, Policy()); }\ \ template \ - inline boost::math::tools::promote_args_t hypergeometric_2F0(const T& a1, const U& a2, const V& z)\ - { return boost::math::hypergeometric_2F0(a1, a2, z, Policy()); }\ + inline BOOST_MATH_NAMESPACE::tools::promote_args_t hypergeometric_2F0(const T& a1, const U& a2, const V& z)\ + { return BOOST_MATH_NAMESPACE::hypergeometric_2F0(a1, a2, z, Policy()); }\ \ diff --git a/include/boost/math/special_functions/modf.hpp b/include/boost/math/special_functions/modf.hpp index 6e372ec9a3..598accb3dd 100644 --- a/include/boost/math/special_functions/modf.hpp +++ b/include/boost/math/special_functions/modf.hpp @@ -19,56 +19,56 @@ #include #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T modf(const T& v, T* ipart, const Policy& pol) { *ipart = trunc(v, pol); return v - *ipart; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T modf(const T& v, T* ipart) { return modf(v, ipart, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T modf(const T& v, int* ipart, const Policy& pol) { *ipart = itrunc(v, pol); return v - *ipart; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T modf(const T& v, int* ipart) { return modf(v, ipart, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T modf(const T& v, long* ipart, const Policy& pol) { *ipart = ltrunc(v, pol); return v - *ipart; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T modf(const T& v, long* ipart) { return modf(v, ipart, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T modf(const T& v, long long* ipart, const Policy& pol) { *ipart = lltrunc(v, pol); return v - *ipart; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T modf(const T& v, long long* ipart) { return modf(v, ipart, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_MODF_HPP diff --git a/include/boost/math/special_functions/next.hpp b/include/boost/math/special_functions/next.hpp index f73cb2f6a5..03245a54bc 100644 --- a/include/boost/math/special_functions/next.hpp +++ b/include/boost/math/special_functions/next.hpp @@ -21,8 +21,13 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#include +#include +#include +#endif #if !defined(_CRAYC) && !defined(BOOST_MATH_ENABLE_CUDA) && (!defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 3))) @@ -32,7 +37,7 @@ #endif #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace concepts { @@ -56,9 +61,9 @@ template <> struct has_hidden_guard_digits<__float128> : public std::false_type {}; #endif template <> -struct has_hidden_guard_digits : public std::false_type {}; +struct has_hidden_guard_digits : public std::false_type {}; template <> -struct has_hidden_guard_digits : public std::false_type {}; +struct has_hidden_guard_digits : public std::false_type {}; template struct has_hidden_guard_digits_10 : public std::false_type {}; @@ -149,7 +154,7 @@ inline T get_min_shift_value() return val; } -template ::value> +template ::value> struct exponent_type { typedef int type; @@ -170,7 +175,7 @@ T float_next_imp(const T& val, const std::true_type&, const Policy& pol) exponent_type expon; static const char* function = "float_next<%1%>(%1%)"; - int fpclass = (boost::math::fpclassify)(val); + int fpclass = (BOOST_MATH_NAMESPACE::fpclassify)(val); if (fpclass == (int)FP_INFINITE) { @@ -223,7 +228,7 @@ T float_next_imp(const T& val, const std::false_type&, const Policy& pol) exponent_type expon; static const char* function = "float_next<%1%>(%1%)"; - int fpclass = (boost::math::fpclassify)(val); + int fpclass = (BOOST_MATH_NAMESPACE::fpclassify)(val); if (fpclass == (int)FP_INFINITE) { @@ -265,7 +270,7 @@ T float_next_imp(const T& val, const std::false_type&, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type float_next(const T& val, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -278,12 +283,12 @@ inline typename tools::promote_args::type float_next(const T& val, const Poli // the SSE2 registers if the FTZ or DAZ flags are set, so use our own // - albeit slower - code instead as at least that gives the correct answer. // -template +BOOST_MATH_EXPORT template inline double float_next(const double& val, const Policy& pol) { static const char* function = "float_next<%1%>(%1%)"; - if(!(boost::math::isfinite)(val) && (val > 0)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(val) && (val > 0)) return policies::raise_domain_error( function, "Argument must be finite, but got %1%", val, pol); @@ -295,7 +300,7 @@ inline double float_next(const double& val, const Policy& pol) } #endif -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type float_next(const T& val) { return float_next(val, policies::policy<>()); @@ -312,7 +317,7 @@ T float_prior_imp(const T& val, const std::true_type&, const Policy& pol) exponent_type expon; static const char* function = "float_prior<%1%>(%1%)"; - int fpclass = (boost::math::fpclassify)(val); + int fpclass = (BOOST_MATH_NAMESPACE::fpclassify)(val); if (fpclass == (int)FP_INFINITE) { @@ -366,7 +371,7 @@ T float_prior_imp(const T& val, const std::false_type&, const Policy& pol) exponent_type expon; static const char* function = "float_prior<%1%>(%1%)"; - int fpclass = (boost::math::fpclassify)(val); + int fpclass = (BOOST_MATH_NAMESPACE::fpclassify)(val); if (fpclass == (int)FP_INFINITE) { @@ -409,7 +414,7 @@ T float_prior_imp(const T& val, const std::false_type&, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type float_prior(const T& val, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -422,12 +427,12 @@ inline typename tools::promote_args::type float_prior(const T& val, const Pol // the SSE2 registers if the FTZ or DAZ flags are set, so use our own // - albeit slower - code instead as at least that gives the correct answer. // -template +BOOST_MATH_EXPORT template inline double float_prior(const double& val, const Policy& pol) { static const char* function = "float_prior<%1%>(%1%)"; - if(!(boost::math::isfinite)(val) && (val < 0)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(val) && (val < 0)) return policies::raise_domain_error( function, "Argument must be finite, but got %1%", val, pol); @@ -439,20 +444,20 @@ inline double float_prior(const double& val, const Policy& pol) } #endif -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type float_prior(const T& val) { return float_prior(val, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type nextafter(const T& val, const U& direction, const Policy& pol) { typedef typename tools::promote_args::type result_type; - return val < direction ? boost::math::float_next(val, pol) : val == direction ? val : boost::math::float_prior(val, pol); + return val < direction ? BOOST_MATH_NAMESPACE::float_next(val, pol) : val == direction ? val : BOOST_MATH_NAMESPACE::float_prior(val, pol); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type nextafter(const T& val, const U& direction) { return nextafter(val, direction, policies::policy<>()); @@ -460,6 +465,75 @@ inline typename tools::promote_args::type nextafter(const T& val, const U& namespace detail{ +#ifdef BOOST_MATH_HAS_INT128 +__extension__ typedef unsigned __int128 float_distance_uint128; +#endif + +// +// Unsigned integer type with the same size as T, if T is an IEEE binary32, binary64 +// or binary128 type, otherwise void: +// +template +struct float_distance_bits_type +{ + template + using select = typename std::conditional::is_iec559 && (std::numeric_limits::digits == Digits) && (sizeof(T) == sizeof(U)), U, Otherwise>::type; +#ifdef BOOST_MATH_HAS_INT128 + using type = select<24, std::uint32_t, select<53, std::uint64_t, select<113, float_distance_uint128, void>>>; +#else + using type = select<24, std::uint32_t, select<53, std::uint64_t, void>>; +#endif +}; + +template +inline T float_distance_bits_to_float(std::uint32_t d) { return static_cast(d); } +template +inline T float_distance_bits_to_float(std::uint64_t d) { return static_cast(d); } +#ifdef BOOST_MATH_HAS_INT128 +template +inline T float_distance_bits_to_float(float_distance_uint128 d) +{ + // Both halves are exact in T, so there is only one rounding: + return static_cast(static_cast(d >> 64)) * T(18446744073709551616.0) + static_cast(static_cast(d)); +} +#endif + +// +// For IEEE types, the distance is the difference of the bit patterns once they +// are mapped to unsigned integers in the same order as the values, see +// https://randomascii.wordpress.com/2012/01/23/stupid-float-tricks-2/ +// Returns false if the generic code must be used instead. +// +template +inline bool float_distance_by_bits(const T& a, const T& b, T& result, const std::true_type&) +{ + BOOST_MATH_STD_USING + using U = typename float_distance_bits_type::type; + // + // If denorms are flushed to zero, then the generic code steps straight from zero + // to min_value, which the bit patterns can't do: + // + if (!((fabs(a) >= tools::min_value()) && (fabs(b) >= tools::min_value()) && ((a < 0) == (b < 0))) && !detail::has_denorm_now()) + return false; + U ai, bi; + std::memcpy(&ai, &a, sizeof(T)); + std::memcpy(&bi, &b, sizeof(T)); + // + // Map -x to sign - |x| and x to sign + |x|, so -0 and +0 are the same point: + // + constexpr U sign = U(1) << (sizeof(U) * CHAR_BIT - 1); + ai = (ai & sign) ? U(sign - (ai & ~sign)) : U(sign + ai); + bi = (bi & sign) ? U(sign - (bi & ~sign)) : U(sign + bi); + result = bi >= ai ? float_distance_bits_to_float(U(bi - ai)) : T(-float_distance_bits_to_float(U(ai - bi))); + return true; +} + +template +inline bool float_distance_by_bits(const T&, const T&, T&, const std::false_type&) +{ + return false; +} + template T float_distance_imp(const T& a, const T& b, const std::true_type&, const Policy& pol) { @@ -468,10 +542,13 @@ T float_distance_imp(const T& a, const T& b, const std::true_type&, const Policy // Error handling: // static const char* function = "float_distance<%1%>(%1%, %1%)"; - if(!(boost::math::isfinite)(a)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(a)) return policies::raise_domain_error(function, "Argument a must be finite, but got %1%", a, pol); - if(!(boost::math::isfinite)(b)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(b)) return policies::raise_domain_error(function, "Argument b must be finite, but got %1%", b, pol); + T bits_result; + if(float_distance_by_bits(a, b, bits_result, std::integral_constant::type>::value>())) + return bits_result; // // Special cases: // @@ -483,7 +560,7 @@ T float_distance_imp(const T& a, const T& b, const std::true_type&, const Policy return 1 + fabs(float_distance(static_cast((b < 0) ? T(-detail::get_smallest_value()) : detail::get_smallest_value()), b, pol)); if(b == 0) return 1 + fabs(float_distance(static_cast((a < 0) ? T(-detail::get_smallest_value()) : detail::get_smallest_value()), a, pol)); - if(boost::math::sign(a) != boost::math::sign(b)) + if(BOOST_MATH_NAMESPACE::sign(a) != BOOST_MATH_NAMESPACE::sign(b)) return 2 + fabs(float_distance(static_cast((b < 0) ? T(-detail::get_smallest_value()) : detail::get_smallest_value()), b, pol)) + fabs(float_distance(static_cast((a < 0) ? T(-detail::get_smallest_value()) : detail::get_smallest_value()), a, pol)); // @@ -502,7 +579,7 @@ T float_distance_imp(const T& a, const T& b, const std::true_type&, const Policy // because we actually have fewer than tools::digits() // significant bits in the representation: // - (void)frexp(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value() : a, &expon); + (void)frexp(((BOOST_MATH_NAMESPACE::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value() : a, &expon); T upper = ldexp(T(1), expon); T result = T(0); // @@ -523,7 +600,7 @@ T float_distance_imp(const T& a, const T& b, const std::true_type&, const Policy // expon = tools::digits() - expon; T mb, x, y, z; - if(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value())) + if(((BOOST_MATH_NAMESPACE::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value())) { // // Special case - either one end of the range is a denormal, or else the difference is. @@ -572,9 +649,9 @@ T float_distance_imp(const T& a, const T& b, const std::false_type&, const Polic // Error handling: // static const char* function = "float_distance<%1%>(%1%, %1%)"; - if(!(boost::math::isfinite)(a)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(a)) return policies::raise_domain_error(function, "Argument a must be finite, but got %1%", a, pol); - if(!(boost::math::isfinite)(b)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(b)) return policies::raise_domain_error(function, "Argument b must be finite, but got %1%", b, pol); // // Special cases: @@ -587,7 +664,7 @@ T float_distance_imp(const T& a, const T& b, const std::false_type&, const Polic return 1 + fabs(float_distance(static_cast((b < 0) ? T(-detail::get_smallest_value()) : detail::get_smallest_value()), b, pol)); if(b == 0) return 1 + fabs(float_distance(static_cast((a < 0) ? T(-detail::get_smallest_value()) : detail::get_smallest_value()), a, pol)); - if(boost::math::sign(a) != boost::math::sign(b)) + if(BOOST_MATH_NAMESPACE::sign(a) != BOOST_MATH_NAMESPACE::sign(b)) return 2 + fabs(float_distance(static_cast((b < 0) ? T(-detail::get_smallest_value()) : detail::get_smallest_value()), b, pol)) + fabs(float_distance(static_cast((a < 0) ? T(-detail::get_smallest_value()) : detail::get_smallest_value()), a, pol)); // @@ -606,7 +683,7 @@ T float_distance_imp(const T& a, const T& b, const std::false_type&, const Polic // because we actually have fewer than tools::digits() // significant bits in the representation: // - expon = 1 + ilogb(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value() : a); + expon = 1 + ilogb(((BOOST_MATH_NAMESPACE::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value() : a); T upper = scalbn(T(1), expon); T result = T(0); // @@ -626,7 +703,7 @@ T float_distance_imp(const T& a, const T& b, const std::false_type&, const Polic // expon = std::numeric_limits::digits - expon; T mb, x, y, z; - if(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value())) + if(((BOOST_MATH_NAMESPACE::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value())) { // // Special case - either one end of the range is a denormal, or else the difference is. @@ -664,7 +741,7 @@ T float_distance_imp(const T& a, const T& b, const std::false_type&, const Polic } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type float_distance(const T& a, const U& b, const Policy& pol) { // @@ -698,10 +775,10 @@ inline typename tools::promote_args::type float_distance(const T& a, const } } -template +BOOST_MATH_EXPORT template typename tools::promote_args::type float_distance(const T& a, const U& b) { - return boost::math::float_distance(a, b, policies::policy<>()); + return BOOST_MATH_NAMESPACE::float_distance(a, b, policies::policy<>()); } namespace detail{ @@ -715,7 +792,7 @@ T float_advance_imp(T val, int distance, const std::true_type&, const Policy& po // static const char* function = "float_advance<%1%>(%1%, int)"; - int fpclass = (boost::math::fpclassify)(val); + int fpclass = (BOOST_MATH_NAMESPACE::fpclassify)(val); if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE)) return policies::raise_domain_error(function, "Argument val must be finite, but got %1%", val, pol); @@ -797,7 +874,7 @@ T float_advance_imp(T val, int distance, const std::false_type&, const Policy& p // static const char* function = "float_advance<%1%>(%1%, int)"; - int fpclass = (boost::math::fpclassify)(val); + int fpclass = (BOOST_MATH_NAMESPACE::fpclassify)(val); if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE)) return policies::raise_domain_error(function, "Argument val must be finite, but got %1%", val, pol); @@ -866,20 +943,20 @@ T float_advance_imp(T val, int distance, const std::false_type&, const Policy& p } // namespace detail -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type float_advance(T val, int distance, const Policy& pol) { typedef typename tools::promote_args::type result_type; return detail::float_advance_imp(detail::normalize_value(static_cast(val), typename detail::has_hidden_guard_digits::type()), distance, std::integral_constant::is_specialized || (std::numeric_limits::radix == 2)>(), pol); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type float_advance(const T& val, int distance) { - return boost::math::float_advance(val, distance, policies::policy<>()); + return BOOST_MATH_NAMESPACE::float_advance(val, distance, policies::policy<>()); } -}} // boost math namespaces +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/nonfinite_num_facets.hpp b/include/boost/math/special_functions/nonfinite_num_facets.hpp index 5e08c10d3f..dd19de522a 100644 --- a/include/boost/math/special_functions/nonfinite_num_facets.hpp +++ b/include/boost/math/special_functions/nonfinite_num_facets.hpp @@ -18,10 +18,12 @@ for Floating-Point Infinities and NaNs. */ +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #include #include #include @@ -32,8 +34,7 @@ # pragma warning(disable : 4706) // assignment within conditional expression. #endif -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN // flags (enums can be ORed together) ----------------------------------- @@ -52,7 +53,7 @@ namespace boost { // class nonfinite_num_put ----------------------------------------------------- - template< + BOOST_MATH_EXPORT template< class CharType, class OutputIterator = std::ostreambuf_iterator > @@ -95,7 +96,7 @@ namespace boost { static const CharType body_nan[4] = { 'n', 'a', 'n', '\0' }; static const CharType* null_string = 0; - switch((boost::math::fpclassify)(val)) + switch((BOOST_MATH_NAMESPACE::fpclassify)(val)) { case FP_INFINITE: @@ -103,7 +104,7 @@ namespace boost { { BOOST_MATH_THROW_EXCEPTION(std::ios_base::failure("Infinity")); } - else if((boost::math::signbit)(val)) + else if((BOOST_MATH_NAMESPACE::signbit)(val)) { // negative infinity. put_num_and_fill(it, iosb, prefix_minus, body_inf, fill, val); } @@ -122,7 +123,7 @@ namespace boost { { BOOST_MATH_THROW_EXCEPTION(std::ios_base::failure("NaN")); } - else if((boost::math::signbit)(val)) + else if((BOOST_MATH_NAMESPACE::signbit)(val)) { // negative so "-nan". put_num_and_fill(it, iosb, prefix_minus, body_nan, fill, val); } @@ -137,7 +138,7 @@ namespace boost { break; case FP_ZERO: - if((flags_ & signed_zero) && ((boost::math::signbit)(val))) + if((flags_ & signed_zero) && ((BOOST_MATH_NAMESPACE::signbit)(val))) { // Flag set to distinguish between positive and negative zero. // But string "0" should have stuff after decimal point if setprecision and/or exp format. @@ -229,7 +230,7 @@ namespace boost { // class nonfinite_num_get ------------------------------------------------------ - template< + BOOST_MATH_EXPORT template< class CharType, class InputIterator = std::istreambuf_iterator > @@ -271,7 +272,7 @@ namespace boost { template static ValType positive_nan() { // On some platforms quiet_NaN() may be negative. - return (boost::math::copysign)( + return (BOOST_MATH_NAMESPACE::copysign)( std::numeric_limits::quiet_NaN(), static_cast(1) ); // static_cast(1) added Paul A. Bristow 5 Apr 11 @@ -316,7 +317,7 @@ namespace boost { if(negative) { - val = (boost::math::changesign)(val); + val = (BOOST_MATH_NAMESPACE::changesign)(val); } } // void get_signed @@ -577,8 +578,7 @@ namespace boost { //------------------------------------------------------------------------------ - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER # pragma warning(pop) diff --git a/include/boost/math/special_functions/owens_t.hpp b/include/boost/math/special_functions/owens_t.hpp index 4fa5c6aa7e..1b156a9350 100644 --- a/include/boost/math/special_functions/owens_t.hpp +++ b/include/boost/math/special_functions/owens_t.hpp @@ -24,8 +24,10 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #ifdef _MSC_VER #pragma warning(push) @@ -42,26 +44,23 @@ #pragma GCC system_header #endif -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // owens_t_znorm1(x) = P(-oo inline RealType owens_t_znorm1(const RealType x, const Policy& pol) { - using namespace boost::math::constants; - return boost::math::erf(x*one_div_root_two(), pol)*half(); + using namespace BOOST_MATH_NAMESPACE::constants; + return BOOST_MATH_NAMESPACE::erf(x*one_div_root_two(), pol)*half(); } // RealType owens_t_znorm1(const RealType x) // owens_t_znorm2(x) = P(x<=Z inline RealType owens_t_znorm2(const RealType x, const Policy& pol) { - using namespace boost::math::constants; - return boost::math::erfc(x*one_div_root_two(), pol)*half(); + using namespace BOOST_MATH_NAMESPACE::constants; + return BOOST_MATH_NAMESPACE::erfc(x*one_div_root_two(), pol)*half(); } // RealType owens_t_znorm2(const RealType x) // Auxiliary function, it computes an array key that is used to determine @@ -167,7 +166,7 @@ namespace boost inline RealType owens_t_T1(const RealType h, const RealType a, const unsigned short m, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; const RealType hs = -h*h*half(); const RealType dhs = exp( hs ); @@ -176,7 +175,7 @@ namespace boost unsigned short j=1; RealType jj = 1; RealType aj = a * one_div_two_pi(); - RealType dj = boost::math::expm1( hs, pol); + RealType dj = BOOST_MATH_NAMESPACE::expm1( hs, pol); RealType gj = hs*dhs; RealType val = atan( a ) * one_div_two_pi(); @@ -203,7 +202,7 @@ namespace boost inline RealType owens_t_T2(const RealType h, const RealType a, const unsigned short m, const RealType ah, const Policy& pol, const std::false_type&) { BOOST_MATH_STD_USING - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; const unsigned short maxii = m+m+1; const RealType hs = h*h; @@ -236,7 +235,7 @@ namespace boost inline RealType owens_t_T3_imp(const RealType h, const RealType a, const RealType ah, const std::integral_constant&, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; const unsigned short m = 20; @@ -290,7 +289,7 @@ namespace boost inline RealType owens_t_T3_imp(const RealType h, const RealType a, const RealType ah, const std::integral_constant&, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; const unsigned short m = 30; @@ -376,7 +375,7 @@ namespace boost inline RealType owens_t_T4(const RealType h, const RealType a, const unsigned short m) { BOOST_MATH_STD_USING - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; const unsigned short maxii = m+m+1; const RealType hs = h*h; @@ -434,7 +433,7 @@ namespace boost static_cast(0.38862217010742057883E-02), static_cast(0.16793031084546090448E-02) }; const RealType as = a*a; - const RealType hs = -h*h*boost::math::constants::half(); + const RealType hs = -h*h*BOOST_MATH_NAMESPACE::constants::half(); // LCOV_EXCL_STOP RealType val = 0; @@ -509,7 +508,7 @@ namespace boost // LCOV_EXCL_STOP const RealType as = a*a; - const RealType hs = -h*h*boost::math::constants::half(); + const RealType hs = -h*h*BOOST_MATH_NAMESPACE::constants::half(); RealType val = 0; for(unsigned short i = 0; i < m; ++i) @@ -540,7 +539,7 @@ namespace boost inline RealType owens_t_T6(const RealType h, const RealType a, const Policy& pol) { BOOST_MATH_STD_USING - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; const RealType normh = owens_t_znorm2(h, pol); const RealType y = static_cast(1) - a; @@ -632,14 +631,14 @@ namespace boost abs_err += fabs(c * term); if(sum < 0) // sum must always be positive, if it's negative something really bad has happened: policies::raise_evaluation_error(function, 0, T(0), pol); - return std::pair((sum / d) / boost::math::constants::two_pi(), abs_err / sum); + return std::pair((sum / d) / BOOST_MATH_NAMESPACE::constants::two_pi(), abs_err / sum); } template inline RealType owens_t_T2(const RealType h, const RealType a, const unsigned short m, const RealType ah, const Policy& pol, const std::true_type&) { BOOST_MATH_STD_USING - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; const unsigned short maxii = m+m+1; const RealType hs = h*h; @@ -684,7 +683,7 @@ namespace boost // and/or fail to alternate at a drop of a hat! :-( // BOOST_MATH_STD_USING - using namespace boost::math::constants; + using namespace BOOST_MATH_NAMESPACE::constants; const RealType hs = h*h; const RealType as = -a*a; @@ -693,7 +692,7 @@ namespace boost unsigned short ii = 1; RealType val = 0; RealType vi = a * exp( -ah*ah*half() ) / root_two_pi(); - RealType z = boost::math::detail::owens_t_znorm1(ah, pol)/h; + RealType z = BOOST_MATH_NAMESPACE::detail::owens_t_znorm1(ah, pol)/h; RealType last_z = fabs(z); // @@ -766,7 +765,7 @@ namespace boost RealType yi = 1.0; RealType val = 0.0; - RealType lim = boost::math::policies::get_epsilon(); + RealType lim = BOOST_MATH_NAMESPACE::policies::get_epsilon(); while( true ) { @@ -872,7 +871,7 @@ namespace boost return owens_t_znorm2(RealType(fabs(h)), pol); } // Attempt arbitrary precision code, this will throw if it goes wrong: - typedef typename boost::math::policies::normalise >::type forwarding_policy; + typedef typename BOOST_MATH_NAMESPACE::policies::normalise >::type forwarding_policy; std::pair p1(0, tools::max_value()), p2(0, tools::max_value()); RealType target_precision = policies::get_epsilon() * 1000; bool have_t1(false), have_t2(false); @@ -888,7 +887,7 @@ namespace boost return p1.first; #ifndef BOOST_MATH_NO_EXCEPTIONS } - catch(const boost::math::evaluation_error&){} // T1 may fail and throw, that's OK + catch(const BOOST_MATH_NAMESPACE::evaluation_error&){} // T1 may fail and throw, that's OK #endif } if(ah > 1) @@ -903,7 +902,7 @@ namespace boost return p2.first; #ifndef BOOST_MATH_NO_EXCEPTIONS } - catch(const boost::math::evaluation_error&){} // T2 may fail and throw, that's OK + catch(const BOOST_MATH_NAMESPACE::evaluation_error&){} // T2 may fail and throw, that's OK #endif } // @@ -922,7 +921,7 @@ namespace boost return p1.first; #ifndef BOOST_MATH_NO_EXCEPTIONS } - catch(const boost::math::evaluation_error&){} // T1 may fail and throw, that's OK + catch(const BOOST_MATH_NAMESPACE::evaluation_error&){} // T1 may fail and throw, that's OK #endif } // @@ -941,7 +940,7 @@ namespace boost return p2.first; #ifndef BOOST_MATH_NO_EXCEPTIONS } - catch(const boost::math::evaluation_error&){} // T2 may fail and throw, that's OK + catch(const BOOST_MATH_NAMESPACE::evaluation_error&){} // T2 may fail and throw, that's OK #endif } // @@ -955,7 +954,7 @@ namespace boost return T4_mp(h, a, pol); #ifndef BOOST_MATH_NO_EXCEPTIONS } - catch(const boost::math::evaluation_error&){} // T4 may fail and throw, that's OK + catch(const BOOST_MATH_NAMESPACE::evaluation_error&){} // T4 may fail and throw, that's OK #endif // // Now look back at the results from T1 and T2 and see if either gave better @@ -1040,7 +1039,7 @@ namespace boost } // namespace detail - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type owens_t(T1 h, T2 a, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -1049,15 +1048,14 @@ namespace boost return policies::checked_narrowing_cast(detail::owens_t(static_cast(h), static_cast(a), pol), "boost::math::owens_t<%1%>(%1%,%1%)"); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type owens_t(T1 h, T2 a) { return owens_t(h, a, policies::policy<>()); } - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/polygamma.hpp b/include/boost/math/special_functions/polygamma.hpp index 6b7815d5e0..0e186ccfc4 100644 --- a/include/boost/math/special_functions/polygamma.hpp +++ b/include/boost/math/special_functions/polygamma.hpp @@ -15,19 +15,19 @@ #include #include -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type polygamma(const int n, T x, const Policy& pol) { // // Filter off special cases right at the start: // if(n == 0) - return boost::math::digamma(x, pol); + return BOOST_MATH_NAMESPACE::digamma(x, pol); if(n == 1) - return boost::math::trigamma(x, pol); + return BOOST_MATH_NAMESPACE::trigamma(x, pol); // // We've found some standard library functions to misbehave if any FPU exception flags // are set prior to their call, this code will clear those flags, then reset them @@ -71,13 +71,13 @@ namespace boost { namespace math { "boost::math::polygamma<%1%>(int, %1%)"); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type polygamma(const int n, T x) { - return boost::math::polygamma(n, x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::polygamma(n, x, policies::policy<>()); } -} } // namespace boost::math +BOOST_MATH_NAMESPACE_END #endif // _BOOST_BERNOULLI_2013_05_30_HPP_ diff --git a/include/boost/math/special_functions/pow.hpp b/include/boost/math/special_functions/pow.hpp index 7a1bb14eba..316b8b1a1f 100644 --- a/include/boost/math/special_functions/pow.hpp +++ b/include/boost/math/special_functions/pow.hpp @@ -22,8 +22,7 @@ #include #endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN #ifdef _MSC_VER #pragma warning(push) @@ -122,14 +121,14 @@ struct select_power_if_positive } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr inline typename tools::promote_args::type pow(T base, const Policy& policy) { using result_type = typename tools::promote_args::type; return detail::select_power_if_positive::type::result(static_cast(base), policy); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED constexpr inline typename tools::promote_args::type pow(T base) { return pow(base, policies::policy<>()); } @@ -137,8 +136,7 @@ BOOST_MATH_GPU_ENABLED constexpr inline typename tools::promote_args::type po #pragma warning(pop) #endif -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/pow1p.hpp b/include/boost/math/special_functions/pow1p.hpp new file mode 100644 index 0000000000..93d3013452 --- /dev/null +++ b/include/boost/math/special_functions/pow1p.hpp @@ -0,0 +1,237 @@ +// (C) Copyright Matt Borland 2024. +// (C) Copyrigh Fancidev 2024. +// 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) + +#ifndef BOOST_MATH_SF_POW1P_HPP +#define BOOST_MATH_SF_POW1P_HPP + +#include +#include +#include +#include +#include +#include +#include + +// For cuda we would rather use builtin nextafter than unsupported boost::math::nextafter +#ifndef BOOST_MATH_HAS_GPU_SUPPORT +# include +# include +# include +#endif // BOOST_MATH_ENABLE_CUDA + +BOOST_MATH_NAMESPACE_BEGIN + +namespace detail { + +template +BOOST_MATH_GPU_ENABLED T pow1p_imp(const T x, const T y, const Policy& pol) +{ + BOOST_MATH_STD_USING + #ifndef BOOST_MATH_HAS_GPU_SUPPORT + using std::fma; + #endif + constexpr auto function = "boost::math::pow1p<%1%>(%1%, %1%)"; + + // The special values follow the spec of the pow() function defined in + // IEEE-754, Section 9.2.1. The order of the `if` statements matters. + if (abs(y) == T(0)) + { + // pow(x, +/-0) + return T(1); + } + + if (x == T(-1)) + { + // pow(+/-0, y) + if ((BOOST_MATH_NAMESPACE::isfinite)(y) && y < 0) + { + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Division by 0", x, pol); + } + + // Gets correct special handling + return pow(T(0), y); + } + + if (x == T(-2) && (BOOST_MATH_NAMESPACE::isinf)(y)) + { + // pow(-1, +/-inf) + return T(1); + } + + if (x == T(0)) + { + // pow(+1, y) + return T(1); + } + + if ((BOOST_MATH_NAMESPACE::isinf)(y)) + { + if ((BOOST_MATH_NAMESPACE::isnan)(x)) + { + return x; + } + // pow(x, +/-inf): |1+x| > 1 exactly when x > 0 or x < -2, since + // x = -2, -1 and 0 have been handled above. + const bool base_exceeds_one = (x > 0) || (x < -2); + return (base_exceeds_one == (y > 0)) ? T(abs(y)) : T(0); + } + + if ((BOOST_MATH_NAMESPACE::isinf)(x)) + { + // pow(+/-inf, y) + return pow(x, y); + } + + // Up to this point, (1+x) = {+/-0, +/-1, +/-inf} have been handled, and + // and y = {+/-0, +/-inf} have been handled. Next, we handle `nan` and + // y = {+/-1}. + if ((BOOST_MATH_NAMESPACE::isnan)(x)) + { + return x; + } + else if ((BOOST_MATH_NAMESPACE::isnan)(y)) + { + return y; + } + + if (y == T(1)) + { + return T(1) + x; + } + if (y == T(-1)) + { + return T(1) / (T(1) + x); // guaranteed no overflow + } + + // Handle (1+x) < 0 + if (x < -1) + { + // TODO(fancidev): maybe use (1+x)^y == [(1+x)^2]^(y/2) + return pow(1+x, y); + } + + // Now x, y are finite and not equal to 0 or +/-1, and x > -1. + // To compute (1+x)^y, write (1+x) == (s+t) where s is equal to (1+x) + // rounded toward 1, and t is the (exact) rounding error. + T s, t; + if (x < 0) + { + s = T(1) + x; + t = x - (s - T(1)); + if (t > 0) + { + #ifdef BOOST_MATH_HAS_GPU_SUPPORT + s = ::nextafter(s, T(1)); + #else + s = BOOST_MATH_NAMESPACE::nextafter(s, T(1)); + #endif + + t = x - (s - T(1)); + } + } + else if (x < 1) + { + s = T(1) + x; + t = x - (s - T(1)); + if (t < 0) + { + #ifdef BOOST_MATH_HAS_GPU_SUPPORT + s = ::nextafter(s, T(0)); + #else + s = BOOST_MATH_NAMESPACE::nextafter(s, T(0)); + #endif + + t = x - (s - T(1)); + } + } + else + { + s = x + T(1); + t = T(1) - (s - x); + if (t < 0) + { + #ifdef BOOST_MATH_HAS_GPU_SUPPORT + s = ::nextafter(s, T(0)); + #else + s = BOOST_MATH_NAMESPACE::nextafter(s, T(0)); + #endif + + t = T(1) - (s - x); + } + } + + // Because x > -1 and s is rounded toward 1, s is guaranteed to be > 0. + // Write (1+x)^y == (s+t)^y == (s^y)*((1+t/s)^y) == term1*term2. + // It can be shown that either both terms <= 1 or both >= 1; so + // if the first term over/underflows, then the result over/underflows. + // And of course, term2 == 1 if t == 0. + T term1 = pow(s, y); + if (t == T(0) || term1 == T(0) || (BOOST_MATH_NAMESPACE::isinf)(term1)) + { + return term1; + } + + // (1+t/s)^y == exp(y*log(1+t/s)). The relative error of the result is + // equal to the absolute error of the exponent (plus the relative error + // of 'exp'). Therefore, when the exponent is small, it is accurately + // evaluated to machine epsilon using T arithmetic. In addition, since + // t/s <= epsilon, log(1+t/s) is well approximated by t/s to first order. + T u = t / s; + T w = y * u; + if (abs(w) <= T(0.5)) + { + T term2 = exp(w); + return term1 * term2; + } + + // Now y*log(1+t/s) is large, and its relative error is "magnified" by + // the exponent. To reduce the error, we use double-T arithmetic, and + // expand log(1+t/s) to second order. + + // (u + uu) ~= t/s. + T r1 = fma(T(-u), s, t); + T uu = r1 / s; + + // (u + vv) ~= log(1+(u+uu)) ~= log(1+t/s). + T vv = fma(T(T(-0.5) * u), u, uu); + + // (w + ww) ~= y*(u+vv) ~= y*log(1+t/s). + T r2 = fma(y, u, T(-w)); + T ww = fma(y, vv, r2); + + // |ww| is tiny compared with |w|, so if exp(w) over/underflows so does the + // result (term1 lies on the same side of 1); don't form inf * 0. + T ew = exp(w); + if (ew == 0 || (BOOST_MATH_NAMESPACE::isinf)(ew)) + { + return ew; + } + // TODO: maybe ww is small enough such that exp(ww) ~= 1+ww. + T term2 = ew * exp(ww); + return term1 * term2; +} + +} // Namespace detail + +template +BOOST_MATH_GPU_ENABLED tools::promote_args_t +pow1p(const T1 x, const T2 y, const Policy& pol) +{ + using result_type = tools::promote_args_t; + return detail::pow1p_imp(static_cast(x), static_cast(y), pol); +} + +template +BOOST_MATH_GPU_ENABLED tools::promote_args_t +pow1p(const T1 x, const T2 y) +{ + using result_type = tools::promote_args_t; + return detail::pow1p_imp(static_cast(x), static_cast(y), policies::policy<>()); +} + +BOOST_MATH_NAMESPACE_END + +#endif // BOOST_MATH_SF_POW1P_HPP diff --git a/include/boost/math/special_functions/powm1.hpp b/include/boost/math/special_functions/powm1.hpp index 80d02dc299..fd30dd9f1b 100644 --- a/include/boost/math/special_functions/powm1.hpp +++ b/include/boost/math/special_functions/powm1.hpp @@ -21,7 +21,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED inline T powm1_imp(const T x, const T y, const Policy& pol) @@ -35,17 +35,17 @@ BOOST_MATH_GPU_ENABLED inline T powm1_imp(const T x, const T y, const Policy& po // so just try it and see: T l = y * log(x); if (l < T(0.5)) - return boost::math::expm1(l, pol); - if (l > boost::math::tools::log_max_value()) - return boost::math::policies::raise_overflow_error(function, nullptr, pol); + return BOOST_MATH_NAMESPACE::expm1(l, pol); + if (l > BOOST_MATH_NAMESPACE::tools::log_max_value()) + return BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); // fall through.... } T result = pow(x, y) - 1; - if((boost::math::isinf)(result)) - return result < 0 ? -boost::math::policies::raise_overflow_error(function, nullptr, pol) : boost::math::policies::raise_overflow_error(function, nullptr, pol); - if((boost::math::isnan)(result)) - return boost::math::policies::raise_domain_error(function, "Result of pow is complex or undefined", x, pol); + if((BOOST_MATH_NAMESPACE::isinf)(result)) + return result < 0 ? -BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol) : BOOST_MATH_NAMESPACE::policies::raise_overflow_error(function, nullptr, pol); + if((BOOST_MATH_NAMESPACE::isnan)(result)) + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "Result of pow is complex or undefined", x, pol); return result; } @@ -54,14 +54,14 @@ BOOST_MATH_GPU_ENABLED inline T powm1_imp_dispatch(const T x, const T y, const P { BOOST_MATH_STD_USING - if ((boost::math::signbit)(x)) // Need to error check -0 here as well + if ((BOOST_MATH_NAMESPACE::signbit)(x)) // Need to error check -0 here as well { constexpr auto function = "boost::math::powm1<%1%>(%1%, %1%)"; // y had better be an integer: - if (boost::math::trunc(y) != y) - return boost::math::policies::raise_domain_error(function, "For non-integral exponent, expected base > 0 but got %1%", x, pol); - if (boost::math::trunc(y / 2) == y / 2) + if (BOOST_MATH_NAMESPACE::trunc(y) != y) + return BOOST_MATH_NAMESPACE::policies::raise_domain_error(function, "For non-integral exponent, expected base > 0 but got %1%", x, pol); + if (BOOST_MATH_NAMESPACE::trunc(y / 2) == y / 2) return powm1_imp(T(-x), T(y), pol); } @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline T powm1_imp_dispatch(const T x, const T y, const P } // detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type powm1(const T1 a, const T2 z) { @@ -78,7 +78,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return detail::powm1_imp_dispatch(static_cast(a), static_cast(z), policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type powm1(const T1 a, const T2 z, const Policy& pol) { @@ -86,8 +86,7 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type return detail::powm1_imp_dispatch(static_cast(a), static_cast(z), pol); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/boost/math/special_functions/prime.hpp b/include/boost/math/special_functions/prime.hpp index 35d9c1a470..e232de2900 100644 --- a/include/boost/math/special_functions/prime.hpp +++ b/include/boost/math/special_functions/prime.hpp @@ -10,10 +10,12 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN // // See https://github.com/boostorg/math/issues/923 for the reasons behind using struct's here: @@ -2406,7 +2408,7 @@ constexpr std::array prime_data_imp::a3; using prime_data = prime_data_imp; - template + BOOST_MATH_EXPORT template BOOST_MATH_CONSTEXPR_TABLE_FUNCTION std::uint32_t prime(unsigned n, const Policy& pol) { @@ -2416,18 +2418,18 @@ constexpr std::array prime_data_imp::a3; return prime_data::a2[n - prime_data::b1 - 1]; if(n >= prime_data::b3) { - return boost::math::policies::raise_domain_error("boost::math::prime<%1%>", "Argument n out of range: got %1%", n, pol); + return BOOST_MATH_NAMESPACE::policies::raise_domain_error("boost::math::prime<%1%>", "Argument n out of range: got %1%", n, pol); } return static_cast(prime_data::a3[n - prime_data::b2 - 1]) + 0xFFFFu; } inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION std::uint32_t prime(unsigned n) { - return boost::math::prime(n, boost::math::policies::policy<>()); + return BOOST_MATH_NAMESPACE::prime(n, BOOST_MATH_NAMESPACE::policies::policy<>()); } - static const unsigned max_prime = 9999; + BOOST_MATH_EXPORT BOOST_MATH_INLINE_CONSTEXPR unsigned max_prime = 9999; -}} // namespace boost and math +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SF_PRIME_HPP diff --git a/include/boost/math/special_functions/prime_sieve.hpp b/include/boost/math/special_functions/prime_sieve.hpp new file mode 100644 index 0000000000..1277a7f8ca --- /dev/null +++ b/include/boost/math/special_functions/prime_sieve.hpp @@ -0,0 +1,360 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Segmented sieve of Eratosthenes with wheel factorization. +// +// prime_sieve(policy, upper, out) primes in [2, upper) +// prime_range(policy, lower, upper, out) primes in [lower, upper) +// prime_count(policy, upper) number of primes in [2, upper) +// prime_count(policy, lower, upper) number of primes in [lower, upper) +// +// Integer may be any builtin integer or a Boost.Multiprecision integer. The policy is a +// std::execution policy (seq / unseq sequential, par / par_unseq threaded) or +// boost::math::execution::cuda. Requires C++17. + +#ifndef BOOST_MATH_SPECIAL_FUNCTIONS_PRIME_SIEVE_HPP +#define BOOST_MATH_SPECIAL_FUNCTIONS_PRIME_SIEVE_HPP + +#include + +#ifndef BOOST_MATH_HAS_NVRTC + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN + +namespace detail::prime_sieve { + +template +struct is_std_vector : std::false_type +{ +}; + +template +struct is_std_vector> : std::true_type +{ +}; + +// Runs the 64-bit engine on [first, last] with the backend selected by Mode, feeding +// consume(const std::uint64_t*, std::size_t) in ascending order. +template +void run_mode(std::uint64_t first, std::uint64_t last, const prime_sieve_options& options, Consumer& consume) +{ + if (prefer_test_path(first, last, options)) + { + test_range_u64(first, last, consume); + return; + } +#ifdef BOOST_MATH_HAS_CUDA_PRIME_SIEVE + if constexpr (Mode == exec_mode::cuda) + { + cuda_range(first, last, options, consume); + return; + } +#endif +#ifdef BOOST_MATH_PRIME_SIEVE_HAS_THREADS + if constexpr (Mode != exec_mode::sequential) + { + parallel_range(first, last, options, consume); + return; + } +#endif + extract_sink sink {consume}; + run_u64(first, last, options, sink); +} + +template +std::uint64_t count_mode(std::uint64_t first, std::uint64_t last, const prime_sieve_options& options) +{ + if (prefer_test_path(first, last, options)) + { + struct counter + { + std::uint64_t count {0}; + void operator()(const std::uint64_t*, std::size_t n) noexcept + { + count += n; + } + } consume {}; + test_range_u64(first, last, consume); + return consume.count; + } +#ifdef BOOST_MATH_HAS_CUDA_PRIME_SIEVE + if constexpr (Mode == exec_mode::cuda) + { + return cuda_count(first, last, options); + } +#endif +#ifdef BOOST_MATH_PRIME_SIEVE_HAS_THREADS + if constexpr (Mode != exec_mode::sequential) + { + return parallel_count(first, last, options); + } +#endif + return count_u64(first, last, options); +} + +// Emits 2, 3, 5 as needed and narrows [lower, upper) to the engine's [first, last] (first >= 7). +// Returns false when nothing beyond the small primes remains. +template +bool prepare_bounds(Integer& lower, const Integer& upper, Small&& small, Integer& start, Integer& stop) +{ + lower = clamp_non_negative(lower); + if (lower < Integer(2)) + { + lower = Integer(2); + } + if (!(lower < upper)) + { + return false; + } + for (const unsigned q : {2u, 3u, 5u}) + { + if (lower <= Integer(q) && Integer(q) < upper) + { + small(q); + } + } + start = lower < Integer(7) ? Integer(7) : lower; + stop = upper - Integer(1); + return !(stop < start); +} + +// Appends the primes in [lower, upper) to a vector, converting from 64-bit values in batches. +template +void range_to_vector(Integer lower, Integer upper, std::vector& out, const prime_sieve_options& options) +{ + Integer start {}; + Integer stop {}; + if (!prepare_bounds(lower, upper, [&](unsigned q) { out.push_back(static_cast(q)); }, start, stop)) + { + return; + } + struct appender + { + std::vector& v; + void operator()(const std::uint64_t* primes, std::size_t n) + { + v.insert(v.end(), primes, primes + n); + } + } consume {out}; + if (fits_u64(stop)) + { + run_mode(to_u64(start), to_u64(stop), options, consume); + return; + } + if constexpr (!std::is_integral::value) + { + if (fits_u64(start)) + { + // Head below 2^64 through the engine (2^64 - 1 is composite), tail by the window method + run_mode(to_u64(start), (std::numeric_limits::max)(), options, consume); + start = Integer((std::numeric_limits::max)()) + Integer(1); + } + big_range_impl(start, stop, options, [&](const Integer& p) { out.push_back(static_cast(p)); }); + } +} + +// Writes the primes in [lower, upper) to out and returns the advanced iterator. +template +OutputIterator range_dispatch(Integer lower, Integer upper, OutputIterator out, const prime_sieve_options& options) +{ + Integer start {}; + Integer stop {}; + if (!prepare_bounds(lower, upper, [&](unsigned q) { *out = Integer(q); ++out; }, start, stop)) + { + return out; + } + output_converter consumer {out}; + if (fits_u64(stop)) + { + run_mode(to_u64(start), to_u64(stop), options, consumer); + return consumer.out; + } + if constexpr (std::is_integral::value) + { + return consumer.out; + } + else + { + if (fits_u64(start)) + { + run_mode(to_u64(start), (std::numeric_limits::max)(), options, consumer); + start = Integer((std::numeric_limits::max)()) + Integer(1); + } + return big_range(start, stop, consumer.out, options); + } +} + +// Counts the primes in [lower, upper). +template +std::uint64_t count_dispatch(Integer lower, Integer upper, const prime_sieve_options& options) +{ + std::uint64_t count {0}; + Integer start {}; + Integer stop {}; + if (!prepare_bounds(lower, upper, [&](unsigned) { ++count; }, start, stop)) + { + return count; + } + if (fits_u64(stop)) + { + return count + count_mode(to_u64(start), to_u64(stop), options); + } + if constexpr (std::is_integral::value) + { + return count; + } + else + { + if (fits_u64(start)) + { + count += count_mode(to_u64(start), (std::numeric_limits::max)(), options); + start = Integer((std::numeric_limits::max)()) + Integer(1); + } + return count + big_count(start, stop, options); + } +} + +} // namespace detail::prime_sieve + +BOOST_MATH_EXPORT template > && + !detail::prime_sieve::is_std_vector>::value, bool> = true> +inline OutputIterator prime_sieve(ExecutionPolicy&&, Integer upper_bound, OutputIterator out, const prime_sieve_options& options = {}) +{ + constexpr auto mode = detail::prime_sieve::mode_of>(); + return detail::prime_sieve::range_dispatch(Integer(0), upper_bound, out, options); +} + +BOOST_MATH_EXPORT template && + !detail::prime_sieve::is_std_vector>::value, bool> = true> +inline OutputIterator prime_sieve(Integer upper_bound, OutputIterator out, const prime_sieve_options& options = {}) +{ + return detail::prime_sieve::range_dispatch(Integer(0), upper_bound, out, options); +} + +// Vector overloads append in bulk, which is noticeably faster than a back_insert_iterator. +BOOST_MATH_EXPORT template >, bool> = true> +inline void prime_sieve(ExecutionPolicy&&, Integer upper_bound, std::vector& out, const prime_sieve_options& options = {}) +{ + constexpr auto mode = detail::prime_sieve::mode_of>(); + detail::prime_sieve::range_to_vector(Integer(0), upper_bound, out, options); +} + +BOOST_MATH_EXPORT template , bool> = true> +inline void prime_sieve(Integer upper_bound, std::vector& out, const prime_sieve_options& options = {}) +{ + detail::prime_sieve::range_to_vector(Integer(0), upper_bound, out, options); +} + +// The two bounds may have different integer types (e.g. a std::uint64_t and a literal); +// they are converted to their common type first. +BOOST_MATH_EXPORT template > && + detail::prime_sieve::is_integer_like_v && detail::prime_sieve::is_integer_like_v && + !detail::prime_sieve::is_std_vector>::value, bool> = true> +inline OutputIterator prime_range(ExecutionPolicy&&, Lower lower_bound, Upper upper_bound, OutputIterator out, const prime_sieve_options& options = {}) +{ + using Integer = detail::prime_sieve::common_integer_t; + constexpr auto mode = detail::prime_sieve::mode_of>(); + return detail::prime_sieve::range_dispatch(detail::prime_sieve::to_common(lower_bound), detail::prime_sieve::to_common(upper_bound), out, options); +} + +BOOST_MATH_EXPORT template && detail::prime_sieve::is_integer_like_v && + !detail::prime_sieve::is_std_vector>::value, bool> = true> +inline OutputIterator prime_range(Lower lower_bound, Upper upper_bound, OutputIterator out, const prime_sieve_options& options = {}) +{ + using Integer = detail::prime_sieve::common_integer_t; + return detail::prime_sieve::range_dispatch(detail::prime_sieve::to_common(lower_bound), detail::prime_sieve::to_common(upper_bound), out, options); +} + +BOOST_MATH_EXPORT template > && + detail::prime_sieve::is_integer_like_v && detail::prime_sieve::is_integer_like_v, bool> = true> +inline void prime_range(ExecutionPolicy&&, Lower lower_bound, Upper upper_bound, std::vector& out, const prime_sieve_options& options = {}) +{ + using Integer = detail::prime_sieve::common_integer_t; + constexpr auto mode = detail::prime_sieve::mode_of>(); + detail::prime_sieve::range_to_vector(detail::prime_sieve::to_common(lower_bound), detail::prime_sieve::to_common(upper_bound), out, options); +} + +BOOST_MATH_EXPORT template && detail::prime_sieve::is_integer_like_v, bool> = true> +inline void prime_range(Lower lower_bound, Upper upper_bound, std::vector& out, const prime_sieve_options& options = {}) +{ + using Integer = detail::prime_sieve::common_integer_t; + detail::prime_sieve::range_to_vector(detail::prime_sieve::to_common(lower_bound), detail::prime_sieve::to_common(upper_bound), out, options); +} + +BOOST_MATH_EXPORT template >, bool> = true> +inline std::uint64_t prime_count(ExecutionPolicy&&, Integer upper_bound, const prime_sieve_options& options = {}) +{ + constexpr auto mode = detail::prime_sieve::mode_of>(); + return detail::prime_sieve::count_dispatch(Integer(0), upper_bound, options); +} + +BOOST_MATH_EXPORT template > && + detail::prime_sieve::is_integer_like_v && detail::prime_sieve::is_integer_like_v, bool> = true> +inline std::uint64_t prime_count(ExecutionPolicy&&, Lower lower_bound, Upper upper_bound, const prime_sieve_options& options = {}) +{ + using Integer = detail::prime_sieve::common_integer_t; + constexpr auto mode = detail::prime_sieve::mode_of>(); + return detail::prime_sieve::count_dispatch(detail::prime_sieve::to_common(lower_bound), detail::prime_sieve::to_common(upper_bound), options); +} + +BOOST_MATH_EXPORT template , bool> = true> +inline std::uint64_t prime_count(Integer upper_bound, const prime_sieve_options& options = {}) +{ + return detail::prime_sieve::count_dispatch(Integer(0), upper_bound, options); +} + +BOOST_MATH_EXPORT template && detail::prime_sieve::is_integer_like_v, bool> = true> +inline std::uint64_t prime_count(Lower lower_bound, Upper upper_bound, const prime_sieve_options& options = {}) +{ + using Integer = detail::prime_sieve::common_integer_t; + return detail::prime_sieve::count_dispatch(detail::prime_sieve::to_common(lower_bound), detail::prime_sieve::to_common(upper_bound), options); +} + +// Reserves room for every prime below upper_bound (Dusart's bound on the prime counting function). +BOOST_MATH_EXPORT template +inline void prime_reserve(Integer upper_bound, std::vector& primes) +{ + upper_bound = detail::prime_sieve::clamp_non_negative(upper_bound); + if (detail::prime_sieve::fits_u64(upper_bound)) + { + primes.reserve(static_cast(detail::prime_sieve::prime_count_upper_bound(detail::prime_sieve::to_u64(upper_bound)))); + } +} + +BOOST_MATH_NAMESPACE_END + +#endif // BOOST_MATH_HAS_NVRTC +#endif // BOOST_MATH_SPECIAL_FUNCTIONS_PRIME_SIEVE_HPP diff --git a/include/boost/math/special_functions/relative_difference.hpp b/include/boost/math/special_functions/relative_difference.hpp index f0f02a893c..98271cfeff 100644 --- a/include/boost/math/special_functions/relative_difference.hpp +++ b/include/boost/math/special_functions/relative_difference.hpp @@ -10,13 +10,12 @@ #include #include -namespace boost{ - namespace math{ +BOOST_MATH_NAMESPACE_BEGIN - template - typename boost::math::tools::promote_args::type relative_difference(const T& arg_a, const U& arg_b) + BOOST_MATH_EXPORT template + typename BOOST_MATH_NAMESPACE::tools::promote_args::type relative_difference(const T& arg_a, const U& arg_b) { - typedef typename boost::math::tools::promote_args::type result_type; + typedef typename BOOST_MATH_NAMESPACE::tools::promote_args::type result_type; result_type a = arg_a; result_type b = arg_b; BOOST_MATH_STD_USING @@ -37,7 +36,7 @@ namespace boost{ result_type max_val = tools::max_value(); #endif // Screen out NaN's first, if either value is a NaN then the distance is "infinite": - if((boost::math::isnan)(a) || (boost::math::isnan)(b)) + if((BOOST_MATH_NAMESPACE::isnan)(a) || (BOOST_MATH_NAMESPACE::isnan)(b)) return max_val; // Screen out infinities: if(fabs(b) > max_val) @@ -71,7 +70,7 @@ namespace boost{ #if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && (LDBL_MAX_EXP <= DBL_MAX_EXP) template <> - inline boost::math::tools::promote_args::type relative_difference(const double& arg_a, const double& arg_b) + inline BOOST_MATH_NAMESPACE::tools::promote_args::type relative_difference(const double& arg_a, const double& arg_b) { BOOST_MATH_STD_USING double a = arg_a; @@ -86,7 +85,7 @@ namespace boost{ double max_val = (std::min)((double)tools::max_value(), tools::max_value()); // Screen out NaN's first, if either value is a NaN then the distance is "infinite": - if((boost::math::isnan)(a) || (boost::math::isnan)(b)) + if((BOOST_MATH_NAMESPACE::isnan)(a) || (BOOST_MATH_NAMESPACE::isnan)(b)) return max_val; // Screen out infinities: if(fabs(b) > max_val) @@ -119,16 +118,15 @@ namespace boost{ } #endif - template - inline typename boost::math::tools::promote_args::type epsilon_difference(const T& arg_a, const U& arg_b) + BOOST_MATH_EXPORT template + inline typename BOOST_MATH_NAMESPACE::tools::promote_args::type epsilon_difference(const T& arg_a, const U& arg_b) { - typedef typename boost::math::tools::promote_args::type result_type; + typedef typename BOOST_MATH_NAMESPACE::tools::promote_args::type result_type; result_type r = relative_difference(arg_a, arg_b); - if(tools::max_value() * boost::math::tools::epsilon() < r) + if(tools::max_value() * BOOST_MATH_NAMESPACE::tools::epsilon() < r) return tools::max_value(); - return r / boost::math::tools::epsilon(); + return r / BOOST_MATH_NAMESPACE::tools::epsilon(); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/round.hpp b/include/boost/math/special_functions/round.hpp index bb99da7e31..34cc61bd04 100644 --- a/include/boost/math/special_functions/round.hpp +++ b/include/boost/math/special_functions/round.hpp @@ -19,16 +19,18 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #if !defined(BOOST_MATH_NO_CCMATH) && !defined(BOOST_MATH_NO_CONSTEXPR_DETECTION) #include # define BOOST_MATH_HAS_CONSTEXPR_LDEXP #endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -38,7 +40,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t round(const T& v, const P BOOST_MATH_STD_USING using result_type = tools::promote_args_t; - if(!(boost::math::isfinite)(v)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(v)) { return policies::raise_rounding_error("boost::math::round<%1%>(%1%)", nullptr, static_cast(v), static_cast(v), pol); } @@ -75,12 +77,12 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t round(const T& v, const P } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t round(const T& v, const Policy& pol) { return detail::round(v, pol, std::integral_constant::value>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t round(const T& v) { return round(v, policies::policy<>()); @@ -98,13 +100,13 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t round(const T& v) // is to avoid macro substiution from MSVC // https://stackoverflow.com/questions/27442885/syntax-error-with-stdnumeric-limitsmax // -template +BOOST_MATH_EXPORT template inline int iround(const T& v, const Policy& pol) { BOOST_MATH_STD_USING using result_type = tools::promote_args_t; - result_type r = boost::math::round(v, pol); + result_type r = BOOST_MATH_NAMESPACE::round(v, pol); #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) if constexpr (std::is_arithmetic_v @@ -113,11 +115,11 @@ inline int iround(const T& v, const Policy& pol) #endif ) { - constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); + constexpr result_type max_val = BOOST_MATH_NAMESPACE::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } else @@ -126,7 +128,7 @@ inline int iround(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } #else @@ -134,25 +136,25 @@ inline int iround(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } #endif return static_cast(r); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline int iround(const T& v) { return iround(v, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline long lround(const T& v, const Policy& pol) { BOOST_MATH_STD_USING using result_type = tools::promote_args_t; - result_type r = boost::math::round(v, pol); + result_type r = BOOST_MATH_NAMESPACE::round(v, pol); #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) if constexpr (std::is_arithmetic_v @@ -161,11 +163,11 @@ BOOST_MATH_GPU_ENABLED inline long lround(const T& v, const Policy& pol) #endif ) { - constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); + constexpr result_type max_val = BOOST_MATH_NAMESPACE::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } else @@ -174,7 +176,7 @@ BOOST_MATH_GPU_ENABLED inline long lround(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } #else @@ -182,25 +184,25 @@ BOOST_MATH_GPU_ENABLED inline long lround(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } #endif return static_cast(r); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline long lround(const T& v) { return lround(v, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline long long llround(const T& v, const Policy& pol) { BOOST_MATH_STD_USING - using result_type = boost::math::tools::promote_args_t; + using result_type = BOOST_MATH_NAMESPACE::tools::promote_args_t; - result_type r = boost::math::round(v, pol); + result_type r = BOOST_MATH_NAMESPACE::round(v, pol); #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) if constexpr (std::is_arithmetic_v @@ -209,11 +211,11 @@ BOOST_MATH_GPU_ENABLED inline long long llround(const T& v, const Policy& pol) #endif ) { - constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); + constexpr result_type max_val = BOOST_MATH_NAMESPACE::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } else @@ -222,7 +224,7 @@ BOOST_MATH_GPU_ENABLED inline long long llround(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } #else @@ -230,26 +232,25 @@ BOOST_MATH_GPU_ENABLED inline long long llround(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } #endif return static_cast(r); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline long long llround(const T& v) { return llround(v, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #else // Specialized NVRTC overloads -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T round(T x) { return ::round(x); @@ -261,19 +262,19 @@ BOOST_MATH_GPU_ENABLED float round(float x) return ::roundf(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T round(T x, const Policy&) { return ::round(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED float round(float x, const Policy&) { return ::roundf(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int iround(T x) { return static_cast(::lround(x)); @@ -285,19 +286,19 @@ BOOST_MATH_GPU_ENABLED int iround(float x) return static_cast(::lroundf(x)); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int iround(T x, const Policy&) { return static_cast(::lround(x)); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int iround(float x, const Policy&) { return static_cast(::lroundf(x)); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long lround(T x) { return ::lround(x); @@ -309,19 +310,19 @@ BOOST_MATH_GPU_ENABLED long lround(float x) return ::lroundf(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long lround(T x, const Policy&) { return ::lround(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long lround(float x, const Policy&) { return ::lroundf(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long long llround(T x) { return ::llround(x); @@ -333,20 +334,19 @@ BOOST_MATH_GPU_ENABLED long long llround(float x) return ::llroundf(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long long llround(T x, const Policy&) { return ::llround(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long long llround(float x, const Policy&) { return ::llroundf(x); } -} // Namespace math -} // Namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC diff --git a/include/boost/math/special_functions/rsqrt.hpp b/include/boost/math/special_functions/rsqrt.hpp index b42fa12bc8..376153a68d 100644 --- a/include/boost/math/special_functions/rsqrt.hpp +++ b/include/boost/math/special_functions/rsqrt.hpp @@ -5,10 +5,13 @@ #ifndef BOOST_MATH_SPECIAL_FUNCTIONS_RSQRT_HPP #define BOOST_MATH_SPECIAL_FUNCTIONS_RSQRT_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif +#include #include #ifndef BOOST_MATH_STANDALONE # include @@ -17,9 +20,9 @@ # endif #endif -namespace boost::math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template inline Real rsqrt(Real const & x) { using std::sqrt; @@ -48,5 +51,5 @@ inline Real rsqrt(Real const & x) } -} +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/sign.hpp b/include/boost/math/special_functions/sign.hpp index 5d2dfc2e23..3e02f39586 100644 --- a/include/boost/math/special_functions/sign.hpp +++ b/include/boost/math/special_functions/sign.hpp @@ -20,7 +20,7 @@ #include #include -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -60,11 +60,11 @@ namespace detail { // inline int signbit_impl(long double x, generic_tag const&) { - return (boost::math::signbit)(static_cast(x)); + return (BOOST_MATH_NAMESPACE::signbit)(static_cast(x)); } inline int signbit_impl(long double x, generic_tag const&) { - return (boost::math::signbit)(static_cast(x)); + return (BOOST_MATH_NAMESPACE::signbit)(static_cast(x)); } #endif @@ -114,15 +114,15 @@ namespace detail { inline long double (changesign_impl)(long double x, generic_tag const&) { double* pd = reinterpret_cast(&x); - pd[0] = boost::math::changesign(pd[0]); - pd[1] = boost::math::changesign(pd[1]); + pd[0] = BOOST_MATH_NAMESPACE::changesign(pd[0]); + pd[1] = BOOST_MATH_NAMESPACE::changesign(pd[1]); return x; } inline long double (changesign_impl)(long double x, generic_tag const&) { double* pd = reinterpret_cast(&x); - pd[0] = boost::math::changesign(pd[0]); - pd[1] = boost::math::changesign(pd[1]); + pd[0] = BOOST_MATH_NAMESPACE::changesign(pd[0]); + pd[1] = BOOST_MATH_NAMESPACE::changesign(pd[1]); return x; } #endif @@ -164,10 +164,10 @@ BOOST_MATH_GPU_ENABLED int (signbit)(T x) return detail::signbit_impl(static_cast(x), method()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline int sign BOOST_NO_MACRO_EXPAND(const T& z) { - return (z == 0) ? 0 : (boost::math::signbit)(z) ? -1 : 1; + return (z == 0) ? 0 : (BOOST_MATH_NAMESPACE::signbit)(z) ? -1 : 1; } template @@ -181,39 +181,37 @@ BOOST_MATH_GPU_ENABLED typename tools::promote_args_permissive::type (changes return detail::changesign_impl(static_cast(x), method()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args_permissive::type copysign BOOST_NO_MACRO_EXPAND(const T& x, const U& y) { BOOST_MATH_STD_USING typedef typename tools::promote_args_permissive::type result_type; - return (boost::math::signbit)(static_cast(x)) != (boost::math::signbit)(static_cast(y)) - ? (boost::math::changesign)(static_cast(x)) : static_cast(x); + return (BOOST_MATH_NAMESPACE::signbit)(static_cast(x)) != (BOOST_MATH_NAMESPACE::signbit)(static_cast(y)) + ? (BOOST_MATH_NAMESPACE::changesign)(static_cast(x)) : static_cast(x); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else // NVRTC alias versions #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int signbit(T x) { return ::signbit(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T changesign(T x) { return -x; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T copysign(T x, T y) { return ::copysign(x, y); @@ -225,14 +223,13 @@ BOOST_MATH_GPU_ENABLED float copysign(float x, float y) return ::copysignf(x, y); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T sign(T z) { return (z == 0) ? 0 : ::signbit(z) ? -1 : 1; } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC diff --git a/include/boost/math/special_functions/sin_pi.hpp b/include/boost/math/special_functions/sin_pi.hpp index 05a155434a..103e76b287 100644 --- a/include/boost/math/special_functions/sin_pi.hpp +++ b/include/boost/math/special_functions/sin_pi.hpp @@ -15,16 +15,18 @@ #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template BOOST_MATH_GPU_ENABLED inline T sin_pi_imp(T x, const Policy&) @@ -43,7 +45,7 @@ BOOST_MATH_GPU_ENABLED inline T sin_pi_imp(T x, const Policy&) invert = false; T rem = floor(x); - if(abs(floor(rem/2)*2 - rem) > boost::math::numeric_limits::epsilon()) + if(abs(floor(rem/2)*2 - rem) > BOOST_MATH_NAMESPACE::numeric_limits::epsilon()) { invert = !invert; } @@ -72,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline T sin_pi_dispatch(T x, const Policy& pol) } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type sin_pi(T x, const Policy&) { typedef typename tools::promote_args::type result_type; @@ -86,23 +88,21 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type sin_pi(T x, // We want to ignore overflows since the result is in [-1,1] and the // check slows the code down considerably. policies::overflow_error >::type forwarding_policy; - return policies::checked_narrowing_cast(boost::math::detail::sin_pi_dispatch(x, forwarding_policy()), "sin_pi"); + return policies::checked_narrowing_cast(BOOST_MATH_NAMESPACE::detail::sin_pi_dispatch(x, forwarding_policy()), "sin_pi"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type sin_pi(T x) { - return boost::math::sin_pi(x, policies::policy<>()); + return BOOST_MATH_NAMESPACE::sin_pi(x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else // Special handling for NVRTC -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto sin_pi(T x) { return ::sinpi(x); @@ -114,20 +114,19 @@ BOOST_MATH_GPU_ENABLED auto sin_pi(float x) return ::sinpif(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto sin_pi(T x, const Policy&) { return ::sinpi(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto sin_pi(float x, const Policy&) { return ::sinpif(x); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC diff --git a/include/boost/math/special_functions/sinc.hpp b/include/boost/math/special_functions/sinc.hpp index 0c18ac3468..ea95a15b3e 100644 --- a/include/boost/math/special_functions/sinc.hpp +++ b/include/boost/math/special_functions/sinc.hpp @@ -27,10 +27,7 @@ // These are the the "Sinus Cardinal" functions. -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // This is the "Sinus Cardinal" of index Pi. @@ -40,7 +37,7 @@ namespace boost { BOOST_MATH_STD_USING - if ((boost::math::isinf)(x)) + if ((BOOST_MATH_NAMESPACE::isinf)(x)) { return 0; } @@ -57,21 +54,21 @@ namespace boost } // namespace detail - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type sinc_pi(T x) { typedef typename tools::promote_args::type result_type; return detail::sinc_pi_imp(static_cast(x)); } - template + BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type sinc_pi(T x, const Policy&) { typedef typename tools::promote_args::type result_type; return detail::sinc_pi_imp(static_cast(x)); } - template class U> + BOOST_MATH_EXPORT template class U> BOOST_MATH_GPU_ENABLED inline U sinc_pi(const U x) { BOOST_MATH_STD_USING @@ -111,13 +108,12 @@ namespace boost } } - template class U, class Policy> + BOOST_MATH_EXPORT template class U, class Policy> BOOST_MATH_GPU_ENABLED inline U sinc_pi(const U x, const Policy&) { return sinc_pi(x); } - } -} + BOOST_MATH_NAMESPACE_END #endif /* BOOST_SINC_HPP */ diff --git a/include/boost/math/special_functions/sinhc.hpp b/include/boost/math/special_functions/sinhc.hpp index b8c5f9f2e4..8f9499c9c3 100644 --- a/include/boost/math/special_functions/sinhc.hpp +++ b/include/boost/math/special_functions/sinhc.hpp @@ -19,17 +19,16 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif // These are the the "Hyperbolic Sinus Cardinal" functions. -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { // This is the "Hyperbolic Sinus Cardinal" of index Pi. @@ -45,7 +44,7 @@ namespace boost static T const taylor_2_bound = sqrt(taylor_0_bound); static T const taylor_n_bound = sqrt(taylor_2_bound); - if((boost::math::isinf)(x)) + if((BOOST_MATH_NAMESPACE::isinf)(x)) { return policies::raise_overflow_error("sinhc(%1%)", nullptr, Policy()); } @@ -78,21 +77,21 @@ namespace boost } // namespace detail - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type sinhc_pi(T x, const Policy& pol) { typedef typename tools::promote_args::type result_type; return policies::checked_narrowing_cast(detail::sinhc_pi_imp(static_cast(x), pol), "sinhc(%1%)"); } - template + BOOST_MATH_EXPORT template inline typename tools::promote_args::type sinhc_pi(T x) { typedef typename tools::promote_args::type result_type; return sinhc_pi(static_cast(x), policies::policy<>()); } - template class U> + BOOST_MATH_EXPORT template class U> inline U sinhc_pi(const U x) { using std::abs; @@ -135,8 +134,7 @@ namespace boost return(result); } } - } -} + BOOST_MATH_NAMESPACE_END #endif /* BOOST_SINHC_HPP */ diff --git a/include/boost/math/special_functions/spherical_harmonic.hpp b/include/boost/math/special_functions/spherical_harmonic.hpp index 5da9265757..46e08ea626 100644 --- a/include/boost/math/special_functions/spherical_harmonic.hpp +++ b/include/boost/math/special_functions/spherical_harmonic.hpp @@ -14,10 +14,11 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost{ -namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ @@ -39,7 +40,7 @@ inline T spherical_harmonic_prefix(unsigned n, unsigned m, T theta, const Policy T leg = detail::legendre_p_imp(n, m, x, static_cast(pow(fabs(sin_theta), T(m))), pol); - T prefix = boost::math::tgamma_delta_ratio(static_cast(n - m + 1), static_cast(2 * m), pol); + T prefix = BOOST_MATH_NAMESPACE::tgamma_delta_ratio(static_cast(n - m + 1), static_cast(2 * m), pol); prefix *= (2 * n + 1) / (4 * constants::pi()); prefix = sqrt(prefix); return prefix * leg; @@ -62,7 +63,7 @@ T spherical_harmonic_r(unsigned n, int m, T theta, T phi, const Policy& pol) if(m&1) { // Check phase if theta is outside [0, PI]: - T mod = boost::math::tools::fmod_workaround(theta, T(2 * constants::pi())); + T mod = BOOST_MATH_NAMESPACE::tools::fmod_workaround(theta, T(2 * constants::pi())); if(mod < 0) mod += 2 * constants::pi(); if(mod > constants::pi()) @@ -89,7 +90,7 @@ T spherical_harmonic_i(unsigned n, int m, T theta, T phi, const Policy& pol) if(m&1) { // Check phase if theta is outside [0, PI]: - T mod = boost::math::tools::fmod_workaround(theta, T(2 * constants::pi())); + T mod = BOOST_MATH_NAMESPACE::tools::fmod_workaround(theta, T(2 * constants::pi())); if(mod < 0) mod += 2 * constants::pi(); if(mod > constants::pi()) @@ -120,7 +121,7 @@ std::complex spherical_harmonic(unsigned n, int m, U theta, U phi, const Poli if(m&1) { // Check phase if theta is outside [0, PI]: - U mod = boost::math::tools::fmod_workaround(theta, U(2 * constants::pi())); + U mod = BOOST_MATH_NAMESPACE::tools::fmod_workaround(theta, U(2 * constants::pi())); if(mod < 0) mod += 2 * constants::pi(); if(mod > constants::pi()) @@ -148,7 +149,7 @@ std::complex spherical_harmonic(unsigned n, int m, U theta, U phi, const Poli } // namespace detail -template +BOOST_MATH_EXPORT template inline std::complex::type> spherical_harmonic(unsigned n, int m, T1 theta, T2 phi, const Policy& pol) { @@ -157,14 +158,14 @@ inline std::complex::type> return detail::spherical_harmonic(n, m, static_cast(theta), static_cast(phi), pol); } -template +BOOST_MATH_EXPORT template inline std::complex::type> spherical_harmonic(unsigned n, int m, T1 theta, T2 phi) { - return boost::math::spherical_harmonic(n, m, theta, phi, policies::policy<>()); + return BOOST_MATH_NAMESPACE::spherical_harmonic(n, m, theta, phi, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi, const Policy& pol) { @@ -173,14 +174,14 @@ inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::spherical_harmonic_r(n, m, static_cast(theta), static_cast(phi), pol), "boost::math::spherical_harmonic_r<%1%>(unsigned, int, %1%, %1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type spherical_harmonic_r(unsigned n, int m, T1 theta, T2 phi) { - return boost::math::spherical_harmonic_r(n, m, theta, phi, policies::policy<>()); + return BOOST_MATH_NAMESPACE::spherical_harmonic_r(n, m, theta, phi, policies::policy<>()); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi, const Policy& pol) { @@ -189,15 +190,14 @@ inline typename tools::promote_args::type return policies::checked_narrowing_cast(detail::spherical_harmonic_i(n, m, static_cast(theta), static_cast(phi), pol), "boost::math::spherical_harmonic_i<%1%>(unsigned, int, %1%, %1%)"); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type spherical_harmonic_i(unsigned n, int m, T1 theta, T2 phi) { - return boost::math::spherical_harmonic_i(n, m, theta, phi, policies::policy<>()); + return BOOST_MATH_NAMESPACE::spherical_harmonic_i(n, m, theta, phi, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_SPHERICAL_HARMONIC_HPP diff --git a/include/boost/math/special_functions/sqrt1pm1.hpp b/include/boost/math/special_functions/sqrt1pm1.hpp index 4d8aeb38cf..47286928be 100644 --- a/include/boost/math/special_functions/sqrt1pm1.hpp +++ b/include/boost/math/special_functions/sqrt1pm1.hpp @@ -19,9 +19,9 @@ // This algorithm computes sqrt(1+x)-1 for small x: // -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type sqrt1pm1(const T& val, const Policy& pol) { typedef typename tools::promote_args::type result_type; @@ -29,17 +29,16 @@ BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type sqrt1pm1(con if(fabs(result_type(val)) > result_type(0.75)) return sqrt(1 + result_type(val)) - 1; - return boost::math::expm1(boost::math::log1p(val, pol) / 2, pol); + return BOOST_MATH_NAMESPACE::expm1(BOOST_MATH_NAMESPACE::log1p(val, pol) / 2, pol); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type sqrt1pm1(const T& val) { return sqrt1pm1(val, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SQRT1PM1 diff --git a/include/boost/math/special_functions/trigamma.hpp b/include/boost/math/special_functions/trigamma.hpp index 7ac99466cb..fb1bedb5c7 100644 --- a/include/boost/math/special_functions/trigamma.hpp +++ b/include/boost/math/special_functions/trigamma.hpp @@ -38,8 +38,7 @@ #pragma GCC system_header #endif -namespace boost{ -namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ // TODO(mborland): Temporary for NVRTC @@ -48,14 +47,14 @@ template T polygamma_imp(const int n, T x, const Policy &pol); template -T trigamma_prec(T x, const Policy& pol, const boost::math::integral_constant&) +T trigamma_prec(T x, const Policy& pol, const BOOST_MATH_NAMESPACE::integral_constant&) { return polygamma_imp(1, x, pol); } #endif template -BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const BOOST_MATH_NAMESPACE::integral_constant&) { // Max error in interpolated form: 3.736e-017 BOOST_MATH_STATIC const T offset = BOOST_MATH_BIG_CONSTANT(T, 53, 2.1093254089355469); @@ -116,7 +115,7 @@ BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const boost::math::in if(x <= 2) { - return (offset + boost::math::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x); + return (offset + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x); } else if(x <= 4) { @@ -128,7 +127,7 @@ BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const boost::math::in } template -BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const BOOST_MATH_NAMESPACE::integral_constant&) { // Max error in interpolated form: 1.178e-020 BOOST_MATH_STATIC const T offset_1_2 = BOOST_MATH_BIG_CONSTANT(T, 64, 2.109325408935546875); @@ -194,7 +193,7 @@ BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const boost::math::in if(x <= 2) { - return (offset_1_2 + boost::math::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x); + return (offset_1_2 + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x); } else if(x <= 8) { @@ -206,7 +205,7 @@ BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const boost::math::in } template -BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const BOOST_MATH_NAMESPACE::integral_constant&) { // Max error in interpolated form: 1.916e-035 @@ -354,11 +353,11 @@ BOOST_MATH_GPU_ENABLED T trigamma_prec(T x, const Policy&, const boost::math::in if(x <= 2) { - return (2 + boost::math::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x); + return (2 + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x); } else if(x <= 4) { - return (y_offset_2_4 + boost::math::tools::evaluate_polynomial(P_2_4, x) / tools::evaluate_polynomial(Q_2_4, x)) / (x * x); + return (y_offset_2_4 + BOOST_MATH_NAMESPACE::tools::evaluate_polynomial(P_2_4, x) / tools::evaluate_polynomial(Q_2_4, x)) / (x * x); } else if(x <= 8) { @@ -399,8 +398,8 @@ BOOST_MATH_GPU_ENABLED T trigamma_dispatch(T x, const Policy& pol, const Tag& ta { return policies::raise_pole_error("boost::math::trigamma<%1%>(%1%)", nullptr, (1-x), pol); } - T s = fabs(x) < fabs(z) ? boost::math::sin_pi(x, pol) : boost::math::sin_pi(z, pol); - return result - trigamma_prec(T(z), pol, tag) + boost::math::pow<2>(constants::pi()) / (s * s); + T s = fabs(x) < fabs(z) ? BOOST_MATH_NAMESPACE::sin_pi(x, pol) : BOOST_MATH_NAMESPACE::sin_pi(z, pol); + return result - trigamma_prec(T(z), pol, tag) + BOOST_MATH_NAMESPACE::pow<2>(constants::pi()) / (s * s); } if(x < 1) { @@ -412,14 +411,14 @@ BOOST_MATH_GPU_ENABLED T trigamma_dispatch(T x, const Policy& pol, const Tag& ta } // namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type trigamma(T x, const Policy&) { typedef typename tools::promote_args::type result_type; typedef typename policies::evaluation::type value_type; typedef typename policies::precision::type precision_type; - typedef boost::math::integral_constant::type return policies::checked_narrowing_cast(detail::trigamma_dispatch(static_cast(x), forwarding_policy(), tag_type()), "boost::math::trigamma<%1%>(%1%)"); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename tools::promote_args::type trigamma(T x) { return trigamma(x, policies::policy<>()); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/special_functions/trunc.hpp b/include/boost/math/special_functions/trunc.hpp index b52f4f321c..5126c3db38 100644 --- a/include/boost/math/special_functions/trunc.hpp +++ b/include/boost/math/special_functions/trunc.hpp @@ -17,7 +17,9 @@ #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #include #include #include @@ -29,14 +31,16 @@ # define BOOST_MATH_HAS_CONSTEXPR_LDEXP #endif -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN + +namespace detail{ template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t trunc(const T& v, const Policy& pol, const std::false_type&) { BOOST_MATH_STD_USING using result_type = tools::promote_args_t; - if(!(boost::math::isfinite)(v)) + if(!(BOOST_MATH_NAMESPACE::isfinite)(v)) { return policies::raise_rounding_error("boost::math::trunc<%1%>(%1%)", nullptr, static_cast(v), static_cast(v), pol); } @@ -51,13 +55,13 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t trunc(const T& v, const P } // Namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t trunc(const T& v, const Policy& pol) { return detail::trunc(v, pol, std::integral_constant::value>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline tools::promote_args_t trunc(const T& v) { return trunc(v, policies::policy<>()); @@ -65,8 +69,7 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t trunc(const T& v) #else // Special handling for nvrtc -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { @@ -88,13 +91,13 @@ BOOST_MATH_GPU_ENABLED inline double trunc_impl(double x) } // Namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto trunc(T x, const Policy&) { return detail::trunc_impl(x); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED auto trunc(T x) { return detail::trunc_impl(x); @@ -117,12 +120,12 @@ BOOST_MATH_GPU_ENABLED auto trunc(T x) // is to avoid macro substiution from MSVC // https://stackoverflow.com/questions/27442885/syntax-error-with-stdnumeric-limitsmax // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v, const Policy& pol) { BOOST_MATH_STD_USING using result_type = tools::promote_args_t; - result_type r = boost::math::trunc(v, pol); + result_type r = BOOST_MATH_NAMESPACE::trunc(v, pol); #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) if constexpr (std::is_arithmetic_v @@ -131,11 +134,11 @@ BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v, const Policy& pol) #endif ) { - constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); + constexpr result_type max_val = BOOST_MATH_NAMESPACE::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } else @@ -144,7 +147,7 @@ BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } #else @@ -152,25 +155,25 @@ BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } #endif return static_cast(r); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v) { return itrunc(v, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v, const Policy& pol) { BOOST_MATH_STD_USING using result_type = tools::promote_args_t; - result_type r = boost::math::trunc(v, pol); + result_type r = BOOST_MATH_NAMESPACE::trunc(v, pol); #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) if constexpr (std::is_arithmetic_v @@ -179,11 +182,11 @@ BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v, const Policy& pol) #endif ) { - constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); + constexpr result_type max_val = BOOST_MATH_NAMESPACE::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } else @@ -192,7 +195,7 @@ BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } #else @@ -200,25 +203,25 @@ BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } #endif return static_cast(r); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v) { return ltrunc(v, policies::policy<>()); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v, const Policy& pol) { BOOST_MATH_STD_USING using result_type = tools::promote_args_t; - result_type r = boost::math::trunc(v, pol); + result_type r = BOOST_MATH_NAMESPACE::trunc(v, pol); #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) if constexpr (std::is_arithmetic_v @@ -227,11 +230,11 @@ BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v, const Policy& pol) #endif ) { - constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); + constexpr result_type max_val = BOOST_MATH_NAMESPACE::ccmath::ldexp(static_cast(1), std::numeric_limits::digits); if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } else @@ -240,7 +243,7 @@ BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } } #else @@ -248,14 +251,14 @@ BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v, const Policy& pol) if (r >= max_val || r < -max_val) { - return static_cast(boost::math::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); + return static_cast(BOOST_MATH_NAMESPACE::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast(0), pol)); } #endif return static_cast(r); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v) { return lltrunc(v, policies::policy<>()); @@ -268,9 +271,9 @@ namespace detail { template BOOST_MATH_GPU_ENABLED TargetType integer_trunc_impl(T v) { - double r = boost::math::trunc(v); + double r = BOOST_MATH_NAMESPACE::trunc(v); - const double max_val = ldexp(1.0, boost::math::numeric_limits::digits); + const double max_val = ldexp(1.0, BOOST_MATH_NAMESPACE::numeric_limits::digits); if (r >= max_val || r < -max_val) { @@ -282,37 +285,37 @@ BOOST_MATH_GPU_ENABLED TargetType integer_trunc_impl(T v) } // Namespace detail -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int itrunc(T v) { return detail::integer_trunc_impl(v); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED int itrunc(T v, const Policy&) { return detail::integer_trunc_impl(v); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long ltrunc(T v) { return detail::integer_trunc_impl(v); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long ltrunc(T v, const Policy&) { return detail::integer_trunc_impl(v); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long long lltrunc(T v) { return detail::integer_trunc_impl(v); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED long long lltrunc(T v, const Policy&) { return detail::integer_trunc_impl(v); @@ -321,65 +324,65 @@ BOOST_MATH_GPU_ENABLED long long lltrunc(T v, const Policy&) #endif // BOOST_MATH_HAS_NVRTC template -BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t, int> +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::enable_if_t, int> iconvert(const T& v, const Policy&) { return static_cast(v); } template -BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t, int> +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::enable_if_t, int> iconvert(const T& v, const Policy& pol) { - using boost::math::itrunc; + using BOOST_MATH_NAMESPACE::itrunc; return itrunc(v, pol); } template -BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t, long> +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::enable_if_t, long> lconvert(const T& v, const Policy&) { return static_cast(v); } template -BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t, long> +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::enable_if_t, long> lconvert(const T& v, const Policy& pol) { - using boost::math::ltrunc; + using BOOST_MATH_NAMESPACE::ltrunc; return ltrunc(v, pol); } template -BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t, long long> +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::enable_if_t, long long> llconvert(const T& v, const Policy&) { return static_cast(v); } template -BOOST_MATH_GPU_ENABLED inline typename boost::math::enable_if_t, long long> +BOOST_MATH_GPU_ENABLED inline typename BOOST_MATH_NAMESPACE::enable_if_t, long long> llconvert(const T& v, const Policy& pol) { - using boost::math::lltrunc; + using BOOST_MATH_NAMESPACE::lltrunc; return lltrunc(v, pol); } template -BOOST_MATH_GPU_ENABLED [[deprecated("Use llconvert")]] inline boost::math::enable_if_t, long long> +BOOST_MATH_GPU_ENABLED [[deprecated("Use llconvert")]] inline BOOST_MATH_NAMESPACE::enable_if_t, long long> llconvertert(const T& v, const Policy&) { return static_cast(v); } template -BOOST_MATH_GPU_ENABLED [[deprecated("Use llconvert")]] inline typename boost::math::enable_if_t, long long> +BOOST_MATH_GPU_ENABLED [[deprecated("Use llconvert")]] inline typename BOOST_MATH_NAMESPACE::enable_if_t, long long> llconvertert(const T& v, const Policy& pol) { - using boost::math::lltrunc; + using BOOST_MATH_NAMESPACE::lltrunc; return lltrunc(v, pol); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TRUNC_HPP diff --git a/include/boost/math/special_functions/ulp.hpp b/include/boost/math/special_functions/ulp.hpp index 5805c171a3..77aa4f4801 100644 --- a/include/boost/math/special_functions/ulp.hpp +++ b/include/boost/math/special_functions/ulp.hpp @@ -16,7 +16,7 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ template T ulp_imp(const T& val, const std::true_type&, const Policy& pol) @@ -25,7 +25,7 @@ T ulp_imp(const T& val, const std::true_type&, const Policy& pol) int expon; static const char* function = "ulp<%1%>(%1%)"; - int fpclass = (boost::math::fpclassify)(val); + int fpclass = (BOOST_MATH_NAMESPACE::fpclassify)(val); if(fpclass == FP_NAN) { @@ -57,7 +57,7 @@ T ulp_imp(const T& val, const std::false_type&, const Policy& pol) int expon; static const char* function = "ulp<%1%>(%1%)"; - int fpclass = (boost::math::fpclassify)(val); + int fpclass = (BOOST_MATH_NAMESPACE::fpclassify)(val); if(fpclass == FP_NAN) { @@ -82,21 +82,21 @@ T ulp_imp(const T& val, const std::false_type&, const Policy& pol) } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type ulp(const T& val, const Policy& pol) { typedef typename tools::promote_args::type result_type; return detail::ulp_imp(static_cast(val), std::integral_constant::is_specialized || (std::numeric_limits::radix == 2)>(), pol); } -template +BOOST_MATH_EXPORT template inline typename tools::promote_args::type ulp(const T& val) { return ulp(val, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_SPECIAL_ULP_HPP diff --git a/include/boost/math/special_functions/zeta.hpp b/include/boost/math/special_functions/zeta.hpp index 4a374cdd5f..78fe81cd30 100644 --- a/include/boost/math/special_functions/zeta.hpp +++ b/include/boost/math/special_functions/zeta.hpp @@ -29,7 +29,7 @@ #pragma GCC system_header #endif -namespace boost{ namespace math{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail{ #if 0 // @@ -48,7 +48,7 @@ struct zeta_series_cache_size // time. This is important when constructing rational approximations // to zeta for example. // - typedef typename boost::math::policies::precision::type precision_type; + typedef typename BOOST_MATH_NAMESPACE::policies::precision::type precision_type; typedef typename mpl::if_< mpl::less_equal >, std::integral_constant, @@ -105,7 +105,7 @@ T zeta_series_imp(T s, T sc, const Policy&) ++n; }while(fabs(change / sum) > tools::epsilon()); - return sum * 1 / -boost::math::powm1(T(2), sc); + return sum * 1 / -BOOST_MATH_NAMESPACE::powm1(T(2), sc); } // @@ -151,7 +151,7 @@ T zeta_polynomial_series(T s, T sc, Policy const &) // See: http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P155.pdf // BOOST_MATH_STD_USING - int n = itrunc(T(log(boost::math::tools::epsilon()) / -2)); + int n = itrunc(T(log(BOOST_MATH_NAMESPACE::tools::epsilon()) / -2)); T sum = 0; // LCOV_EXCL_LINE spurious miss as surrounding lines hit. T two_n = ldexp(T(1), n); int ej_sign = 1; // LCOV_EXCL_LINE spurious miss as surrounding lines hit. @@ -974,23 +974,23 @@ T zeta_imp(T s, T sc, const Policy& pol, const Tag& tag) if(((-v) & 1) == 0) return 0; int n = (-v + 1) / 2; - if(n <= (int)boost::math::max_bernoulli_b2n::value) - return T((-v & 1) ? -1 : 1) * boost::math::unchecked_bernoulli_b2n(n) / (1 - v); + if(n <= (int)BOOST_MATH_NAMESPACE::max_bernoulli_b2n::value) + return T((-v & 1) ? -1 : 1) * BOOST_MATH_NAMESPACE::unchecked_bernoulli_b2n(n) / (1 - v); } else if((v & 1) == 0) { - if(((v / 2) <= (int)boost::math::max_bernoulli_b2n::value) && (v <= (int)boost::math::max_factorial::value)) + if(((v / 2) <= (int)BOOST_MATH_NAMESPACE::max_bernoulli_b2n::value) && (v <= (int)BOOST_MATH_NAMESPACE::max_factorial::value)) return T(((v / 2 - 1) & 1) ? -1 : 1) * ldexp(T(1), v - 1) * static_cast(pow(constants::pi(), T(v))) * - boost::math::unchecked_bernoulli_b2n(v / 2) / boost::math::unchecked_factorial(v); + BOOST_MATH_NAMESPACE::unchecked_bernoulli_b2n(v / 2) / BOOST_MATH_NAMESPACE::unchecked_factorial(v); return T(((v / 2 - 1) & 1) ? -1 : 1) * ldexp(T(1), v - 1) * static_cast(pow(constants::pi(), T(v))) * - boost::math::bernoulli_b2n(v / 2) / boost::math::factorial(v, pol); + BOOST_MATH_NAMESPACE::bernoulli_b2n(v / 2) / BOOST_MATH_NAMESPACE::factorial(v, pol); } else return zeta_imp_odd_integer(v, sc, pol, std::integral_constant()); } #ifndef BOOST_MATH_NO_EXCEPTIONS } - catch(const boost::math::rounding_error&){} // Just fall through, s is too large to round + catch(const BOOST_MATH_NAMESPACE::rounding_error&){} // Just fall through, s is too large to round catch(const std::overflow_error&){} // LCOV_EXCL_LINE We can only get here for "strange" MP types with small exponents and very large digit counts. #endif } @@ -1008,8 +1008,8 @@ T zeta_imp(T s, T sc, const Policy& pol, const Tag& tag) { if(s > max_factorial::value) { - T mult = boost::math::sin_pi(0.5f * sc, pol) * 2 * zeta_imp(s, sc, pol, tag); - result = boost::math::lgamma(s, pol); + T mult = BOOST_MATH_NAMESPACE::sin_pi(0.5f * sc, pol) * 2 * zeta_imp(s, sc, pol, tag); + result = BOOST_MATH_NAMESPACE::lgamma(s, pol); result -= s * log(2 * constants::pi()); if(result > tools::log_max_value()) return sign(mult) * policies::raise_overflow_error(function, nullptr, pol); @@ -1020,14 +1020,14 @@ T zeta_imp(T s, T sc, const Policy& pol, const Tag& tag) // half integer. // if(tools::max_value() / fabs(mult) < result) - return boost::math::sign(mult) * policies::raise_overflow_error(function, nullptr, pol); // LCOV_EXCL_LINE + return BOOST_MATH_NAMESPACE::sign(mult) * policies::raise_overflow_error(function, nullptr, pol); // LCOV_EXCL_LINE result *= mult; } else { - result = boost::math::sin_pi(0.5f * sc, pol) + result = BOOST_MATH_NAMESPACE::sin_pi(0.5f * sc, pol) * 2 * pow(2 * constants::pi(), -s) - * boost::math::tgamma(s, pol) + * BOOST_MATH_NAMESPACE::tgamma(s, pol) * zeta_imp(s, sc, pol, tag); } } @@ -1073,7 +1073,7 @@ inline typename tools::promote_args::type zeta(T s) return zeta(s, policies::policy<>()); } -}} // namespaces +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ZETA_HPP diff --git a/include/boost/math/statistics/anderson_darling.hpp b/include/boost/math/statistics/anderson_darling.hpp index f892f27e0f..9990679a9f 100644 --- a/include/boost/math/statistics/anderson_darling.hpp +++ b/include/boost/math/statistics/anderson_darling.hpp @@ -8,14 +8,16 @@ #ifndef BOOST_MATH_STATISTICS_ANDERSON_DARLING_HPP #define BOOST_MATH_STATISTICS_ANDERSON_DARLING_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include -namespace boost { namespace math { namespace statistics { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { -template +BOOST_MATH_EXPORT template auto anderson_darling_normality_statistic(RandomAccessContainer const & v, typename RandomAccessContainer::value_type mu = std::numeric_limits::quiet_NaN(), typename RandomAccessContainer::value_type sd = std::numeric_limits::quiet_NaN()) @@ -23,18 +25,18 @@ auto anderson_darling_normality_statistic(RandomAccessContainer const & v, using Real = typename RandomAccessContainer::value_type; using std::log; using std::sqrt; - using boost::math::erfc; + using BOOST_MATH_NAMESPACE::erfc; if (std::isnan(mu)) { - mu = boost::math::statistics::mean(v); + mu = BOOST_MATH_NAMESPACE::statistics::mean(v); } if (std::isnan(sd)) { - sd = sqrt(boost::math::statistics::sample_variance(v)); + sd = sqrt(BOOST_MATH_NAMESPACE::statistics::sample_variance(v)); } - typedef boost::math::policies::policy< - boost::math::policies::promote_float, - boost::math::policies::promote_double > + typedef BOOST_MATH_NAMESPACE::policies::policy< + BOOST_MATH_NAMESPACE::policies::promote_float, + BOOST_MATH_NAMESPACE::policies::promote_double > no_promote_policy; // This is where Knuth's literate programming could really come in handy! @@ -108,5 +110,5 @@ auto anderson_darling_normality_statistic(RandomAccessContainer const & v, return v.size()*(left_tail + right_tail + integrals); } -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/statistics/bivariate_statistics.hpp b/include/boost/math/statistics/bivariate_statistics.hpp index d6f91faa93..b1aa5e83f0 100644 --- a/include/boost/math/statistics/bivariate_statistics.hpp +++ b/include/boost/math/statistics/bivariate_statistics.hpp @@ -7,6 +7,7 @@ #ifndef BOOST_MATH_STATISTICS_BIVARIATE_STATISTICS_HPP #define BOOST_MATH_STATISTICS_BIVARIATE_STATISTICS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -15,16 +16,19 @@ #include #include #include +#endif #include #include #ifdef BOOST_MATH_EXEC_COMPATIBLE +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #endif +#endif -namespace boost{ namespace math{ namespace statistics { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { // See Equation III.9 of "Numerically Stable, Single-Pass, Parallel Statistics Algorithms", Bennet et al. template @@ -297,7 +301,7 @@ ReturnType correlation_coefficient_parallel_impl(ForwardIterator u_begin, Forwar mu_u_a = mu_u_a + delta_u*(n_b/n_ab); mu_v_a = mu_v_a + delta_v*(n_b/n_ab); Qu_a = Qu_a + Qu_b + delta_u*delta_u*((n_a*n_b)/n_ab); - Qv_b = Qv_a + Qv_b + delta_v*delta_v*((n_a*n_b)/n_ab); + Qv_a = Qv_a + Qv_b + delta_v*delta_v*((n_a*n_b)/n_ab); n_a = n_ab; } @@ -327,7 +331,7 @@ ReturnType correlation_coefficient_parallel_impl(ForwardIterator u_begin, Forwar #ifdef BOOST_MATH_EXEC_COMPATIBLE -template +BOOST_MATH_EXPORT template inline auto means_and_covariance(ExecutionPolicy&& exec, Container const & u, Container const & v) { if constexpr (std::is_same_v, decltype(std::execution::seq)>) @@ -362,25 +366,25 @@ inline auto means_and_covariance(ExecutionPolicy&& exec, Container const & u, Co } } -template +BOOST_MATH_EXPORT template inline auto means_and_covariance(Container const & u, Container const & v) { return means_and_covariance(std::execution::seq, u, v); } -template +BOOST_MATH_EXPORT template inline auto covariance(ExecutionPolicy&& exec, Container const & u, Container const & v) { return std::get<2>(means_and_covariance(exec, u, v)); } -template +BOOST_MATH_EXPORT template inline auto covariance(Container const & u, Container const & v) { return covariance(std::execution::seq, u, v); } -template +BOOST_MATH_EXPORT template inline auto correlation_coefficient(ExecutionPolicy&& exec, Container const & u, Container const & v) { if constexpr (std::is_same_v, decltype(std::execution::seq)>) @@ -411,7 +415,7 @@ inline auto correlation_coefficient(ExecutionPolicy&& exec, Container const & u, } } -template +BOOST_MATH_EXPORT template inline auto correlation_coefficient(Container const & u, Container const & v) { return correlation_coefficient(std::execution::seq, u, v); @@ -419,7 +423,7 @@ inline auto correlation_coefficient(Container const & u, Container const & v) #else // C++11 and single threaded bindings -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto means_and_covariance(Container const & u, Container const & v) -> std::tuple { using ReturnType = std::tuple; @@ -427,7 +431,7 @@ inline auto means_and_covariance(Container const & u, Container const & v) -> st return std::make_tuple(std::get<0>(temp), std::get<1>(temp), std::get<2>(temp)); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto means_and_covariance(Container const & u, Container const & v) -> std::tuple { using ReturnType = std::tuple; @@ -435,28 +439,28 @@ inline auto means_and_covariance(Container const & u, Container const & v) -> st return std::make_tuple(std::get<0>(temp), std::get<1>(temp), std::get<2>(temp)); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline double covariance(Container const & u, Container const & v) { using ReturnType = std::tuple; return std::get<2>(detail::means_and_covariance_seq_impl(std::begin(u), std::end(u), std::begin(v), std::end(v))); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline Real covariance(Container const & u, Container const & v) { using ReturnType = std::tuple; return std::get<2>(detail::means_and_covariance_seq_impl(std::begin(u), std::end(u), std::begin(v), std::end(v))); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline double correlation_coefficient(Container const & u, Container const & v) { using ReturnType = std::tuple; return std::get<5>(detail::correlation_coefficient_seq_impl(std::begin(u), std::end(u), std::begin(v), std::end(v))); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline Real correlation_coefficient(Container const & u, Container const & v) { using ReturnType = std::tuple; @@ -465,6 +469,6 @@ inline Real correlation_coefficient(Container const & u, Container const & v) #endif -}}} // namespace boost::math::statistics +} BOOST_MATH_NAMESPACE_END // namespace boost::math::statistics #endif diff --git a/include/boost/math/statistics/chatterjee_correlation.hpp b/include/boost/math/statistics/chatterjee_correlation.hpp index ad0b33a429..78cca8bc95 100644 --- a/include/boost/math/statistics/chatterjee_correlation.hpp +++ b/include/boost/math/statistics/chatterjee_correlation.hpp @@ -1,4 +1,5 @@ // (C) Copyright Matt Borland 2022. +// (C) Copyright Oleksandr Kornijcuk 2026. // 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) @@ -6,6 +7,7 @@ #ifndef BOOST_MATH_STATISTICS_CHATTERJEE_CORRELATION_HPP #define BOOST_MATH_STATISTICS_CHATTERJEE_CORRELATION_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -14,17 +16,20 @@ #include #include #include +#endif #include #include #include #ifdef BOOST_MATH_EXEC_COMPATIBLE +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #endif +#endif -namespace boost { namespace math { namespace statistics { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { @@ -52,7 +57,7 @@ template ReturnType chatterjee_correlation_seq_impl(ForwardIterator u_begin, ForwardIterator u_end, ForwardIterator v_begin, ForwardIterator v_end) { using std::abs; - + BOOST_MATH_ASSERT_MSG(std::is_sorted(u_begin, u_end), "The x values must be sorted in order to use this functionality"); const std::vector rank_vector = rank(v_begin, v_end); @@ -70,20 +75,112 @@ ReturnType chatterjee_correlation_seq_impl(ForwardIterator u_begin, ForwardItera return result; } +// Generalised (M right-nearest-neighbour) Chatterjee correlation of Lin and Han (2021), +// "On boosting the power of Chatterjee's rank correlation", https://arxiv.org/abs/2108.06828. +// +// For a sample sorted by X, the inner sum of equation (2.4) is +// +// S = sum_{i} sum_{m=1}^{M} min(R_i, R_{j_m(i)}), +// +// where R_i is the (1-based) rank of Y_i and j_m(i) is the m-th right nearest neighbour of X_i. +// After sorting by X the m-th right neighbour of element i is element i + m when it exists +// (i + m < n); otherwise j_m(i) = i (the sentinel of the paper), contributing min(R_i, R_i) = R_i. +// +// Note: rank() returns 0-based ranks, whereas the paper's formula uses 1-based ranks. The +1 offset +// cancels in the M = 1 statistic above (which uses |R_{i+1} - R_i|) but does NOT cancel under +// min(.,.), so it is applied explicitly here. +inline std::uint64_t chatterjee_mnn_min_sum(const std::vector& rank_vector, + std::size_t lo, std::size_t hi, std::size_t M) +{ + const std::size_t n = rank_vector.size(); + std::uint64_t sum = 0; + + for (std::size_t i = lo; i < hi; ++i) + { + const std::size_t r_i = rank_vector[i] + 1; + + // Number of right neighbours of i that actually exist within [0, n). + const std::size_t existing = (i + M < n) ? M : (n - 1 - i); + + for (std::size_t m = 1; m <= existing; ++m) + { + const std::size_t r_j = rank_vector[i + m] + 1; + sum += static_cast((std::min)(r_i, r_j)); + } + + // The remaining (M - existing) neighbours are sentinels j_m(i) = i, each contributing r_i. + sum += static_cast(M - existing) * static_cast(r_i); + } + + return sum; +} + +template +ReturnType chatterjee_mnn_result(std::uint64_t sum, std::size_t n, std::size_t M) +{ + const ReturnType n_r = static_cast(n); + const ReturnType m_r = static_cast(M); + + // Denominator (n + 1) * [nM + M(M + 1) / 4] of equation (2.4); chosen so that E[xi_{n,M}] = 0 under H0. + const ReturnType denominator = (n_r + static_cast(1)) * + (n_r * m_r + m_r * (m_r + static_cast(1)) / static_cast(4)); + + return static_cast(-2) + static_cast(6) * static_cast(sum) / denominator; +} + +template +ReturnType chatterjee_correlation_mnn_seq_impl(ForwardIterator u_begin, ForwardIterator u_end, + ForwardIterator v_begin, ForwardIterator v_end, std::size_t M) +{ + BOOST_MATH_ASSERT_MSG(std::is_sorted(u_begin, u_end), "The x values must be sorted in order to use this functionality"); + + const std::size_t n = static_cast(std::distance(v_begin, v_end)); + + BOOST_MATH_ASSERT_MSG(M >= 1, "The number of right nearest neighbours M must be at least 1"); + BOOST_MATH_ASSERT_MSG(M <= n, "The number of right nearest neighbours M must not exceed the number of samples"); + + // If Y is constant the statistic is undefined (Y must be non-constant); return a quiet NaN. + // This is checked on the input directly: rank() collapses tied values, so a constant Y would + // otherwise reduce the effective sample size to one. + if (v_begin != v_end) + { + using value_type = typename std::iterator_traits::value_type; + const value_type first_value = *v_begin; + if (std::all_of(std::next(v_begin), v_end, + [&first_value](const value_type& value) { return value == first_value; })) + { + return std::numeric_limits::quiet_NaN(); + } + } + + const std::vector rank_vector = rank(v_begin, v_end); + + const std::uint64_t sum = chatterjee_mnn_min_sum(rank_vector, 0, n, M); + + return chatterjee_mnn_result(sum, n, M); +} + } // Namespace detail -template ::value, double, Real>::type> inline ReturnType chatterjee_correlation(const Container& u, const Container& v) { return detail::chatterjee_correlation_seq_impl(std::begin(u), std::end(u), std::begin(v), std::end(v)); } -}}} // Namespace boost::math::statistics +BOOST_MATH_EXPORT template ::value, double, Real>::type> +inline ReturnType chatterjee_correlation_mnn(const Container& u, const Container& v, std::size_t M) +{ + return detail::chatterjee_correlation_mnn_seq_impl(std::begin(u), std::end(u), std::begin(v), std::end(v), M); +} + +} BOOST_MATH_NAMESPACE_END // Namespace boost::math::statistics #ifdef BOOST_MATH_EXEC_COMPATIBLE -namespace boost::math::statistics { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { @@ -121,7 +218,7 @@ ReturnType chatterjee_correlation_par_impl(ExecutionPolicy&& exec, ForwardIterat { sum += future_manager[i].get(); } - + ReturnType result = static_cast(1) - (static_cast(3 * sum) / static_cast(rank_vector.size() * rank_vector.size() - 1)); // If the result is 1 then Y is constant and all the elements must be ties @@ -133,9 +230,69 @@ ReturnType chatterjee_correlation_par_impl(ExecutionPolicy&& exec, ForwardIterat return result; } +template +ReturnType chatterjee_correlation_mnn_par_impl(ExecutionPolicy&& exec, ForwardIterator u_begin, ForwardIterator u_end, + ForwardIterator v_begin, ForwardIterator v_end, std::size_t M) +{ + BOOST_MATH_ASSERT_MSG(std::is_sorted(std::forward(exec), u_begin, u_end), "The x values must be sorted in order to use this functionality"); + + const std::size_t n = static_cast(std::distance(v_begin, v_end)); + + BOOST_MATH_ASSERT_MSG(M >= 1, "The number of right nearest neighbours M must be at least 1"); + BOOST_MATH_ASSERT_MSG(M <= n, "The number of right nearest neighbours M must not exceed the number of samples"); + + // If Y is constant the statistic is undefined (Y must be non-constant); return a quiet NaN. + // This is checked on the input directly: rank() collapses tied values, so a constant Y would + // otherwise reduce the effective sample size to one. + if (v_begin != v_end) + { + using value_type = typename std::iterator_traits::value_type; + const value_type first_value = *v_begin; + if (std::all_of(std::next(v_begin), v_end, + [&first_value](const value_type& value) { return value == first_value; })) + { + return std::numeric_limits::quiet_NaN(); + } + } + + const auto rank_vector = rank(std::forward(exec), v_begin, v_end); + + const auto num_threads = std::thread::hardware_concurrency() == 0 ? 2u : std::thread::hardware_concurrency(); + + // The i-loop is embarrassingly parallel: each task sums over a disjoint contiguous range of + // indices [lo, hi) and reads (read-only) rank_vector entries up to i + M, which may fall in a + // neighbouring task's range. Because there are no writes, the partition needs no overlap; this + // differs from the M = 1 parallel path above, which splits the data array (and overlaps by one + // element) for the difference-based transform. + std::vector> future_manager {}; + future_manager.reserve(num_threads); + + const std::size_t chunk = static_cast(std::ceil(static_cast(n) / num_threads)); + + std::size_t lo = 0; + while (lo < n) + { + const std::size_t hi = (std::min)(lo + chunk, n); + future_manager.emplace_back(std::async(std::launch::async | std::launch::deferred, + [&rank_vector, lo, hi, M]() -> std::uint64_t + { + return chatterjee_mnn_min_sum(rank_vector, lo, hi, M); + })); + lo = hi; + } + + std::uint64_t sum = 0; + for (std::size_t i {}; i < future_manager.size(); ++i) + { + sum += future_manager[i].get(); + } + + return chatterjee_mnn_result(sum, n, M); +} + } // Namespace detail -template , double, Real>> inline ReturnType chatterjee_correlation(ExecutionPolicy&& exec, const Container& u, const Container& v) { @@ -152,7 +309,24 @@ inline ReturnType chatterjee_correlation(ExecutionPolicy&& exec, const Container } } -} // Namespace boost::math::statistics +BOOST_MATH_EXPORT template , double, Real>> +inline ReturnType chatterjee_correlation_mnn(ExecutionPolicy&& exec, const Container& u, const Container& v, std::size_t M) +{ + if constexpr (std::is_same_v, decltype(std::execution::seq)>) + { + return detail::chatterjee_correlation_mnn_seq_impl(std::cbegin(u), std::cend(u), + std::cbegin(v), std::cend(v), M); + } + else + { + return detail::chatterjee_correlation_mnn_par_impl(std::forward(exec), + std::cbegin(u), std::cend(u), + std::cbegin(v), std::cend(v), M); + } +} + +} BOOST_MATH_NAMESPACE_END // Namespace boost::math::statistics #endif diff --git a/include/boost/math/statistics/detail/rank.hpp b/include/boost/math/statistics/detail/rank.hpp index 4e5211607e..8bc418d7a0 100644 --- a/include/boost/math/statistics/detail/rank.hpp +++ b/include/boost/math/statistics/detail/rank.hpp @@ -6,19 +6,23 @@ #ifndef BOOST_MATH_STATISTICS_DETAIL_RANK_HPP #define BOOST_MATH_STATISTICS_DETAIL_RANK_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include +#endif #include #ifdef BOOST_MATH_EXEC_COMPATIBLE +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif -namespace boost { namespace math { namespace statistics { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { struct pair_equal { @@ -29,11 +33,11 @@ struct pair_equal } }; -}}}} // Namespaces +}} BOOST_MATH_NAMESPACE_END #ifndef BOOST_MATH_EXEC_COMPATIBLE -namespace boost { namespace math { namespace statistics { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { template ::value_type> auto rank(ForwardIterator first, ForwardIterator last) -> std::vector @@ -75,11 +79,11 @@ inline auto rank(const Container& c) -> std::vector return rank(std::begin(c), std::end(c)); } -}}}} // Namespaces +}} BOOST_MATH_NAMESPACE_END #else -namespace boost::math::statistics::detail { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics::detail { template ::value_type> auto rank(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) @@ -133,7 +137,7 @@ inline auto rank(const Container& c) return rank(std::execution::seq, std::cbegin(c), std::cend(c)); } -} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_EXEC_COMPATIBLE diff --git a/include/boost/math/statistics/detail/single_pass.hpp b/include/boost/math/statistics/detail/single_pass.hpp index 015021f2b3..4d0e4402bd 100644 --- a/include/boost/math/statistics/detail/single_pass.hpp +++ b/include/boost/math/statistics/detail/single_pass.hpp @@ -9,6 +9,7 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -18,20 +19,23 @@ #include #include #include +#endif #ifdef BOOST_MATH_HAS_THREADS +#ifndef BOOST_MATH_BUILD_MODULE #include #include #endif +#endif -namespace boost { namespace math { namespace statistics { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { template ReturnType mean_sequential_impl(ForwardIterator first, ForwardIterator last) { const std::size_t elements {static_cast(std::distance(first, last))}; - std::valarray mu {0, 0, 0, 0}; - std::valarray temp {0, 0, 0, 0}; + std::valarray mu {ReturnType(0), ReturnType(0), ReturnType(0), ReturnType(0)}; + std::valarray temp {ReturnType(0), ReturnType(0), ReturnType(0), ReturnType(0)}; ReturnType i {1}; const ForwardIterator end {std::next(first, elements - (elements % 4))}; ForwardIterator it {first}; @@ -66,9 +70,9 @@ ReturnType variance_sequential_impl(ForwardIterator first, ForwardIterator last) using Real = typename std::tuple_element<0, ReturnType>::type; Real M = *first; - Real Q = 0; - Real k = 2; - Real M2 = 0; + Real Q = Real(0); + Real k = Real(2); + Real M2 = Real(0); std::size_t n = 1; for(auto it = std::next(first); it != last; ++it) @@ -94,9 +98,9 @@ ReturnType first_four_moments_sequential_impl(ForwardIterator first, ForwardIter using Size = typename std::tuple_element<4, ReturnType>::type; Real M1 = *first; - Real M2 = 0; - Real M3 = 0; - Real M4 = 0; + Real M2 = Real(0); + Real M3 = Real(0); + Real M4 = Real(0); Size n = 2; for (auto it = std::next(first); it != last; ++it) { @@ -211,8 +215,8 @@ ReturnType skewness_sequential_impl(ForwardIterator first, ForwardIterator last) BOOST_MATH_ASSERT_MSG(first != last, "At least one sample is required to compute skewness."); ReturnType M1 = *first; - ReturnType M2 = 0; - ReturnType M3 = 0; + ReturnType M2 = ReturnType(0); + ReturnType M3 = ReturnType(0); ReturnType n = 2; for (auto it = std::next(first); it != last; ++it) @@ -242,8 +246,8 @@ template ReturnType gini_coefficient_sequential_impl(ForwardIterator first, ForwardIterator last) { ReturnType i = 1; - ReturnType num = 0; - ReturnType denom = 0; + ReturnType num = ReturnType(0); + ReturnType denom = ReturnType(0); for(auto it = first; it != last; ++it) { @@ -269,8 +273,8 @@ ReturnType gini_range_fraction(ForwardIterator first, ForwardIterator last, std: using Real = typename std::tuple_element<0, ReturnType>::type; std::size_t i = starting_index + 1; - Real num = 0; - Real denom = 0; + Real num = Real(0); + Real denom = Real(0); for(auto it = first; it != last; ++it) { @@ -336,8 +340,8 @@ ReturnType gini_coefficient_parallel_impl(ExecutionPolicy&&, ForwardIterator fir return gini_range_fraction(it, last, (num_threads - 1)*elements_per_thread); })); - ReturnType num = 0; - ReturnType denom = 0; + ReturnType num = ReturnType(0); + ReturnType denom = ReturnType(0); for(std::size_t i = 0; i < future_manager.size(); ++i) { @@ -396,6 +400,6 @@ OutputIterator mode_impl(ForwardIterator first, ForwardIterator last, OutputIter return std::move(modes.begin(), modes.end(), output); } -}}}} +}} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_STATISTICS_UNIVARIATE_STATISTICS_DETAIL_SINGLE_PASS_HPP diff --git a/include/boost/math/statistics/linear_regression.hpp b/include/boost/math/statistics/linear_regression.hpp index 2def7ab7ea..e2f6da2696 100644 --- a/include/boost/math/statistics/linear_regression.hpp +++ b/include/boost/math/statistics/linear_regression.hpp @@ -9,16 +9,18 @@ #ifndef BOOST_MATH_STATISTICS_LINEAR_REGRESSION_HPP #define BOOST_MATH_STATISTICS_LINEAR_REGRESSION_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include +#endif #include #include -namespace boost { namespace math { namespace statistics { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { template @@ -35,12 +37,12 @@ ReturnType simple_ordinary_least_squares_impl(RandomAccessContainer const & x, { throw std::domain_error("The same number of samples must be in the independent and dependent variable."); } - std::tuple temp = boost::math::statistics::means_and_covariance(x, y); + std::tuple temp = BOOST_MATH_NAMESPACE::statistics::means_and_covariance(x, y); Real mu_x = std::get<0>(temp); Real mu_y = std::get<1>(temp); Real cov_xy = std::get<2>(temp); - Real var_x = boost::math::statistics::variance(x); + Real var_x = BOOST_MATH_NAMESPACE::statistics::variance(x); if (var_x <= 0) { throw std::domain_error("Independent variable has no variance; this breaks linear regression."); @@ -67,12 +69,12 @@ ReturnType simple_ordinary_least_squares_with_R_squared_impl(RandomAccessContain { throw std::domain_error("The same number of samples must be in the independent and dependent variable."); } - std::tuple temp = boost::math::statistics::means_and_covariance(x, y); + std::tuple temp = BOOST_MATH_NAMESPACE::statistics::means_and_covariance(x, y); Real mu_x = std::get<0>(temp); Real mu_y = std::get<1>(temp); Real cov_xy = std::get<2>(temp); - Real var_x = boost::math::statistics::variance(x); + Real var_x = BOOST_MATH_NAMESPACE::statistics::variance(x); if (var_x <= 0) { throw std::domain_error("Independent variable has no variance; this breaks linear regression."); @@ -102,32 +104,32 @@ ReturnType simple_ordinary_least_squares_with_R_squared_impl(RandomAccessContain } } // namespace detail -template::value, bool>::type = true> inline auto simple_ordinary_least_squares(RandomAccessContainer const & x, RandomAccessContainer const & y) -> std::pair { return detail::simple_ordinary_least_squares_impl>(x, y); } -template::value, bool>::type = true> inline auto simple_ordinary_least_squares(RandomAccessContainer const & x, RandomAccessContainer const & y) -> std::pair { return detail::simple_ordinary_least_squares_impl>(x, y); } -template::value, bool>::type = true> inline auto simple_ordinary_least_squares_with_R_squared(RandomAccessContainer const & x, RandomAccessContainer const & y) -> std::tuple { return detail::simple_ordinary_least_squares_with_R_squared_impl>(x, y); } -template::value, bool>::type = true> inline auto simple_ordinary_least_squares_with_R_squared(RandomAccessContainer const & x, RandomAccessContainer const & y) -> std::tuple { return detail::simple_ordinary_least_squares_with_R_squared_impl>(x, y); } -}}} // namespace boost::math::statistics +} BOOST_MATH_NAMESPACE_END // namespace boost::math::statistics #endif diff --git a/include/boost/math/statistics/ljung_box.hpp b/include/boost/math/statistics/ljung_box.hpp index 6417665ce4..d15571c8a9 100644 --- a/include/boost/math/statistics/ljung_box.hpp +++ b/include/boost/math/statistics/ljung_box.hpp @@ -6,15 +6,17 @@ #ifndef BOOST_MATH_STATISTICS_LJUNG_BOX_HPP #define BOOST_MATH_STATISTICS_LJUNG_BOX_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include -namespace boost::math::statistics { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { -template +BOOST_MATH_EXPORT template auto ljung_box(RandomAccessIterator begin, RandomAccessIterator end, int64_t lags = -1, int64_t fit_dof = 0) { using Real = typename std::iterator_traits::value_type; int64_t n = std::distance(begin, end); @@ -31,7 +33,7 @@ auto ljung_box(RandomAccessIterator begin, RandomAccessIterator end, int64_t lag throw std::domain_error("Must have at least one lag."); } - auto mu = boost::math::statistics::mean(begin, end); + auto mu = BOOST_MATH_NAMESPACE::statistics::mean(begin, end); std::vector r(lags + 1, Real(0)); for (size_t i = 0; i < r.size(); ++i) { @@ -49,22 +51,22 @@ auto ljung_box(RandomAccessIterator begin, RandomAccessIterator end, int64_t lag } Q *= n*(n+2); - typedef boost::math::policies::policy< - boost::math::policies::promote_float, - boost::math::policies::promote_double > + typedef BOOST_MATH_NAMESPACE::policies::policy< + BOOST_MATH_NAMESPACE::policies::promote_float, + BOOST_MATH_NAMESPACE::policies::promote_double > no_promote_policy; - auto chi = boost::math::chi_squared_distribution(Real(lags - fit_dof)); + auto chi = BOOST_MATH_NAMESPACE::chi_squared_distribution(Real(lags - fit_dof)); - Real pvalue = 1 - boost::math::cdf(chi, Q); + Real pvalue = 1 - BOOST_MATH_NAMESPACE::cdf(chi, Q); return std::make_pair(Q, pvalue); } -template +BOOST_MATH_EXPORT template auto ljung_box(RandomAccessContainer const & v, int64_t lags = -1, int64_t fit_dof = 0) { return ljung_box(v.begin(), v.end(), lags, fit_dof); } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/statistics/runs_test.hpp b/include/boost/math/statistics/runs_test.hpp index dc1a6ecf68..c1e1c5cef2 100644 --- a/include/boost/math/statistics/runs_test.hpp +++ b/include/boost/math/statistics/runs_test.hpp @@ -8,15 +8,17 @@ #ifndef BOOST_MATH_STATISTICS_RUNS_TEST_HPP #define BOOST_MATH_STATISTICS_RUNS_TEST_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include -namespace boost::math::statistics { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { -template +BOOST_MATH_EXPORT template auto runs_above_and_below_threshold(RandomAccessContainer const & v, typename RandomAccessContainer::value_type threshold) { @@ -27,9 +29,9 @@ auto runs_above_and_below_threshold(RandomAccessContainer const & v, { throw std::domain_error("At least 2 samples are required to get number of runs."); } - typedef boost::math::policies::policy< - boost::math::policies::promote_float, - boost::math::policies::promote_double > + typedef BOOST_MATH_NAMESPACE::policies::policy< + BOOST_MATH_NAMESPACE::policies::promote_float, + BOOST_MATH_NAMESPACE::policies::promote_double > no_promote_policy; decltype(v.size()) nabove = 0; @@ -98,12 +100,12 @@ auto runs_above_and_below_threshold(RandomAccessContainer const & v, Real sd = sqrt(variance); Real statistic = (runs - expected_runs)/sd; - auto normal = boost::math::normal_distribution(0,1); - Real pvalue = 2*boost::math::cdf(normal, -abs(statistic)); + auto normal = BOOST_MATH_NAMESPACE::normal_distribution(0,1); + Real pvalue = 2*BOOST_MATH_NAMESPACE::cdf(normal, -abs(statistic)); return std::make_pair(statistic, pvalue); } -template +BOOST_MATH_EXPORT template auto runs_above_and_below_median(RandomAccessContainer const & v) { using Real = typename RandomAccessContainer::value_type; @@ -113,9 +115,9 @@ auto runs_above_and_below_median(RandomAccessContainer const & v) // We have to memcpy v because the median does a partial sort, // and that would be catastrophic for the runs test. auto w = v; - Real median = boost::math::statistics::median(w); + Real median = BOOST_MATH_NAMESPACE::statistics::median(w); return runs_above_and_below_threshold(v, median); } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/statistics/signal_statistics.hpp b/include/boost/math/statistics/signal_statistics.hpp index d2ded721ce..d975f70ef3 100644 --- a/include/boost/math/statistics/signal_statistics.hpp +++ b/include/boost/math/statistics/signal_statistics.hpp @@ -6,8 +6,10 @@ #ifndef BOOST_MATH_TOOLS_SIGNAL_STATISTICS_HPP #define BOOST_MATH_TOOLS_SIGNAL_STATISTICS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include #include @@ -21,9 +23,9 @@ #endif #endif -namespace boost::math::statistics { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { -template +BOOST_MATH_EXPORT template auto absolute_gini_coefficient(ForwardIterator first, ForwardIterator last) { using std::abs; @@ -53,29 +55,29 @@ auto absolute_gini_coefficient(ForwardIterator first, ForwardIterator last) return ((2*num)/denom - i)/(i-1); } -template +BOOST_MATH_EXPORT template inline auto absolute_gini_coefficient(RandomAccessContainer & v) { - return boost::math::statistics::absolute_gini_coefficient(v.begin(), v.end()); + return BOOST_MATH_NAMESPACE::statistics::absolute_gini_coefficient(v.begin(), v.end()); } -template +BOOST_MATH_EXPORT template auto sample_absolute_gini_coefficient(ForwardIterator first, ForwardIterator last) { size_t n = std::distance(first, last); - return n*boost::math::statistics::absolute_gini_coefficient(first, last)/(n-1); + return n*BOOST_MATH_NAMESPACE::statistics::absolute_gini_coefficient(first, last)/(n-1); } -template +BOOST_MATH_EXPORT template inline auto sample_absolute_gini_coefficient(RandomAccessContainer & v) { - return boost::math::statistics::sample_absolute_gini_coefficient(v.begin(), v.end()); + return BOOST_MATH_NAMESPACE::statistics::sample_absolute_gini_coefficient(v.begin(), v.end()); } // The Hoyer sparsity measure is defined in: // https://arxiv.org/pdf/0811.4706.pdf -template +BOOST_MATH_EXPORT template auto hoyer_sparsity(const ForwardIterator first, const ForwardIterator last) { using T = typename std::iterator_traits::value_type; @@ -124,14 +126,14 @@ auto hoyer_sparsity(const ForwardIterator first, const ForwardIterator last) } } -template +BOOST_MATH_EXPORT template inline auto hoyer_sparsity(Container const & v) { - return boost::math::statistics::hoyer_sparsity(v.cbegin(), v.cend()); + return BOOST_MATH_NAMESPACE::statistics::hoyer_sparsity(v.cbegin(), v.cend()); } -template +BOOST_MATH_EXPORT template auto oracle_snr(Container const & signal, Container const & noisy_signal) { using Real = typename Container::value_type; @@ -156,7 +158,7 @@ auto oracle_snr(Container const & signal, Container const & noisy_signal) } return numerator/denominator; } - else if constexpr (boost::math::tools::is_complex_type::value) + else if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { using std::norm; @@ -200,13 +202,13 @@ auto oracle_snr(Container const & signal, Container const & noisy_signal) } } -template +BOOST_MATH_EXPORT template auto mean_invariant_oracle_snr(Container const & signal, Container const & noisy_signal) { using Real = typename Container::value_type; BOOST_MATH_ASSERT_MSG(signal.size() == noisy_signal.size(), "Signal and noisy signal must be have the same number of elements."); - Real mu = boost::math::statistics::mean(signal); + Real mu = BOOST_MATH_NAMESPACE::statistics::mean(signal); Real numerator = 0; Real denominator = 0; for (size_t i = 0; i < signal.size(); ++i) @@ -228,27 +230,27 @@ auto mean_invariant_oracle_snr(Container const & signal, Container const & noisy } -template +BOOST_MATH_EXPORT template auto mean_invariant_oracle_snr_db(Container const & signal, Container const & noisy_signal) { using std::log10; - return 10*log10(boost::math::statistics::mean_invariant_oracle_snr(signal, noisy_signal)); + return 10*log10(BOOST_MATH_NAMESPACE::statistics::mean_invariant_oracle_snr(signal, noisy_signal)); } // Follows the definition of SNR given in Mallat, A Wavelet Tour of Signal Processing, equation 11.16. -template +BOOST_MATH_EXPORT template auto oracle_snr_db(Container const & signal, Container const & noisy_signal) { using std::log10; - return 10*log10(boost::math::statistics::oracle_snr(signal, noisy_signal)); + return 10*log10(BOOST_MATH_NAMESPACE::statistics::oracle_snr(signal, noisy_signal)); } // A good reference on the M2M4 estimator: // D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR estimation techniques for the AWGN channel," IEEE Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. // A nice python implementation: // https://github.com/gnuradio/gnuradio/blob/master/gr-digital/examples/snr_estimators.py -template +BOOST_MATH_EXPORT template auto m2m4_snr_estimator(ForwardIterator first, ForwardIterator last, decltype(*first) estimated_signal_kurtosis=1, decltype(*first) estimated_noise_kurtosis=3) { BOOST_MATH_ASSERT_MSG(estimated_signal_kurtosis > 0, "The estimated signal kurtosis must be positive"); @@ -266,7 +268,7 @@ auto m2m4_snr_estimator(ForwardIterator first, ForwardIterator last, decltype(*f // However, I can't prove that, so there is a chance that this does unnecessary work. // Future improvements: There are algorithms which can solve quadratics much more effectively than the naive implementation found here. // See: https://stackoverflow.com/questions/48979861/numerically-stable-method-for-solving-quadratic-equations/50065711#50065711 - auto [M1, M2, M3, M4] = boost::math::statistics::first_four_moments(first, last); + auto [M1, M2, M3, M4] = BOOST_MATH_NAMESPACE::statistics::first_four_moments(first, last); if (M4 == 0) { // The signal is constant. There is no noise: @@ -281,7 +283,7 @@ auto m2m4_snr_estimator(ForwardIterator first, ForwardIterator last, decltype(*f Real cs = kw*M2*M2 - M4; Real bn = 2*M2*(3-ka); Real cn = ka*M2*M2 - M4; - auto [S0, S1] = boost::math::tools::quadratic_roots(a, bs, cs); + auto [S0, S1] = BOOST_MATH_NAMESPACE::tools::quadratic_roots(a, bs, cs); if (S1 > 0) { auto N = M2 - S1; @@ -298,7 +300,7 @@ auto m2m4_snr_estimator(ForwardIterator first, ForwardIterator last, decltype(*f } } } - auto [N0, N1] = boost::math::tools::quadratic_roots(a, bn, cn); + auto [N0, N1] = BOOST_MATH_NAMESPACE::tools::quadratic_roots(a, bn, cn); if (N1 > 0) { auto S = M2 - N1; @@ -325,13 +327,13 @@ auto m2m4_snr_estimator(ForwardIterator first, ForwardIterator last, decltype(*f } } -template +BOOST_MATH_EXPORT template inline auto m2m4_snr_estimator(Container const & noisy_signal, typename Container::value_type estimated_signal_kurtosis=1, typename Container::value_type estimated_noise_kurtosis=3) { return m2m4_snr_estimator(noisy_signal.cbegin(), noisy_signal.cend(), estimated_signal_kurtosis, estimated_noise_kurtosis); } -template +BOOST_MATH_EXPORT template inline auto m2m4_snr_estimator_db(ForwardIterator first, ForwardIterator last, decltype(*first) estimated_signal_kurtosis=1, decltype(*first) estimated_noise_kurtosis=3) { using std::log10; @@ -339,12 +341,12 @@ inline auto m2m4_snr_estimator_db(ForwardIterator first, ForwardIterator last, d } -template +BOOST_MATH_EXPORT template inline auto m2m4_snr_estimator_db(Container const & noisy_signal, typename Container::value_type estimated_signal_kurtosis=1, typename Container::value_type estimated_noise_kurtosis=3) { using std::log10; return 10*log10(m2m4_snr_estimator(noisy_signal, estimated_signal_kurtosis, estimated_noise_kurtosis)); } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/statistics/t_test.hpp b/include/boost/math/statistics/t_test.hpp index ec06bda8c3..fa993acfd8 100644 --- a/include/boost/math/statistics/t_test.hpp +++ b/include/boost/math/statistics/t_test.hpp @@ -7,6 +7,7 @@ #ifndef BOOST_MATH_STATISTICS_T_TEST_HPP #define BOOST_MATH_STATISTICS_T_TEST_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -14,29 +15,30 @@ #include #include #include +#endif #include #include -namespace boost { namespace math { namespace statistics { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { template ReturnType one_sample_t_test_impl(T sample_mean, T sample_variance, T num_samples, T assumed_mean) { using Real = typename std::tuple_element<0, ReturnType>::type; using std::sqrt; - typedef boost::math::policies::policy< - boost::math::policies::promote_float, - boost::math::policies::promote_double > + typedef BOOST_MATH_NAMESPACE::policies::policy< + BOOST_MATH_NAMESPACE::policies::promote_float, + BOOST_MATH_NAMESPACE::policies::promote_double > no_promote_policy; Real test_statistic = (sample_mean - assumed_mean)/sqrt(sample_variance/num_samples); - auto student = boost::math::students_t_distribution(num_samples - 1); + auto student = BOOST_MATH_NAMESPACE::students_t_distribution(num_samples - 1); Real pvalue; if (test_statistic > 0) { - pvalue = 2*boost::math::cdf(student, -test_statistic);; + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(student, -test_statistic);; } else { - pvalue = 2*boost::math::cdf(student, test_statistic); + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(student, test_statistic); } return std::make_pair(test_statistic, pvalue); } @@ -56,7 +58,7 @@ template ReturnType welchs_t_test_impl(T mean_1, T variance_1, T size_1, T mean_2, T variance_2, T size_2) { using Real = typename std::tuple_element<0, ReturnType>::type; - using no_promote_policy = boost::math::policies::policy, boost::math::policies::promote_double>; + using no_promote_policy = BOOST_MATH_NAMESPACE::policies::policy, BOOST_MATH_NAMESPACE::policies::promote_double>; using std::sqrt; Real dof_num = (variance_1/size_1 + variance_2/size_2) * (variance_1/size_1 + variance_2/size_2); @@ -67,15 +69,15 @@ ReturnType welchs_t_test_impl(T mean_1, T variance_1, T size_1, T mean_2, T vari Real s_estimator = sqrt((variance_1/size_1) + (variance_2/size_2)); Real test_statistic = (static_cast(mean_1) - static_cast(mean_2))/s_estimator; - auto student = boost::math::students_t_distribution(dof); + auto student = BOOST_MATH_NAMESPACE::students_t_distribution(dof); Real pvalue; if (test_statistic > 0) { - pvalue = 2*boost::math::cdf(student, -test_statistic);; + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(student, -test_statistic);; } else { - pvalue = 2*boost::math::cdf(student, test_statistic); + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(student, test_statistic); } return std::make_pair(test_statistic, pvalue); @@ -86,22 +88,22 @@ template ReturnType two_sample_t_test_impl(T mean_1, T variance_1, T size_1, T mean_2, T variance_2, T size_2) { using Real = typename std::tuple_element<0, ReturnType>::type; - using no_promote_policy = boost::math::policies::policy, boost::math::policies::promote_double>; + using no_promote_policy = BOOST_MATH_NAMESPACE::policies::policy, BOOST_MATH_NAMESPACE::policies::promote_double>; using std::sqrt; Real dof = size_1 + size_2 - 2; Real pooled_std_dev = sqrt(((size_1-1)*variance_1 + (size_2-1)*variance_2) / dof); Real test_statistic = (mean_1-mean_2) / (pooled_std_dev*sqrt(1.0/static_cast(size_1) + 1.0/static_cast(size_2))); - auto student = boost::math::students_t_distribution(dof); + auto student = BOOST_MATH_NAMESPACE::students_t_distribution(dof); Real pvalue; if (test_statistic > 0) { - pvalue = 2*boost::math::cdf(student, -test_statistic);; + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(student, -test_statistic);; } else { - pvalue = 2*boost::math::cdf(student, test_statistic); + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(student, test_statistic); } return std::make_pair(test_statistic, pvalue); @@ -140,7 +142,7 @@ template ReturnType paired_samples_t_test_impl(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2) { using Real = typename std::tuple_element<0, ReturnType>::type; - using no_promote_policy = boost::math::policies::policy, boost::math::policies::promote_double>; + using no_promote_policy = BOOST_MATH_NAMESPACE::policies::policy, BOOST_MATH_NAMESPACE::policies::promote_double>; using std::sqrt; std::vector delta; @@ -164,112 +166,112 @@ ReturnType paired_samples_t_test_impl(ForwardIterator begin_1, ForwardIterator e Real test_statistic = delta_mean/(delta_std_dev/sqrt(n)); - auto student = boost::math::students_t_distribution(n - 1); + auto student = BOOST_MATH_NAMESPACE::students_t_distribution(n - 1); Real pvalue; if (test_statistic > 0) { - pvalue = 2*boost::math::cdf(student, -test_statistic);; + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(student, -test_statistic);; } else { - pvalue = 2*boost::math::cdf(student, test_statistic); + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(student, test_statistic); } return std::make_pair(test_statistic, pvalue); } } // namespace detail -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto one_sample_t_test(Real sample_mean, Real sample_variance, Real num_samples, Real assumed_mean) -> std::pair { return detail::one_sample_t_test_impl>(sample_mean, sample_variance, num_samples, assumed_mean); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto one_sample_t_test(Real sample_mean, Real sample_variance, Real num_samples, Real assumed_mean) -> std::pair { return detail::one_sample_t_test_impl>(sample_mean, sample_variance, num_samples, assumed_mean); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto one_sample_t_test(ForwardIterator begin, ForwardIterator end, Real assumed_mean) -> std::pair { return detail::one_sample_t_test_impl>(begin, end, assumed_mean); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto one_sample_t_test(ForwardIterator begin, ForwardIterator end, Real assumed_mean) -> std::pair { return detail::one_sample_t_test_impl>(begin, end, assumed_mean); } -template::value, bool>::type = true> inline auto one_sample_t_test(Container const & v, Real assumed_mean) -> std::pair { return detail::one_sample_t_test_impl>(std::begin(v), std::end(v), assumed_mean); } -template::value, bool>::type = true> inline auto one_sample_t_test(Container const & v, Real assumed_mean) -> std::pair { return detail::one_sample_t_test_impl>(std::begin(v), std::end(v), assumed_mean); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto two_sample_t_test(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2) -> std::pair { return detail::two_sample_t_test_impl>(begin_1, end_1, begin_2, end_2); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto two_sample_t_test(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2) -> std::pair { return detail::two_sample_t_test_impl>(begin_1, end_1, begin_2, end_2); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto two_sample_t_test(Container const & u, Container const & v) -> std::pair { return detail::two_sample_t_test_impl>(std::begin(u), std::end(u), std::begin(v), std::end(v)); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto two_sample_t_test(Container const & u, Container const & v) -> std::pair { return detail::two_sample_t_test_impl>(std::begin(u), std::end(u), std::begin(v), std::end(v)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto paired_samples_t_test(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2) -> std::pair { return detail::paired_samples_t_test_impl>(begin_1, end_1, begin_2, end_2); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto paired_samples_t_test(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2) -> std::pair { return detail::paired_samples_t_test_impl>(begin_1, end_1, begin_2, end_2); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto paired_samples_t_test(Container const & u, Container const & v) -> std::pair { return detail::paired_samples_t_test_impl>(std::begin(u), std::end(u), std::begin(v), std::end(v)); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto paired_samples_t_test(Container const & u, Container const & v) -> std::pair { return detail::paired_samples_t_test_impl>(std::begin(u), std::end(u), std::begin(v), std::end(v)); } -}}} // namespace boost::math::statistics +} BOOST_MATH_NAMESPACE_END // namespace boost::math::statistics #endif diff --git a/include/boost/math/statistics/univariate_statistics.hpp b/include/boost/math/statistics/univariate_statistics.hpp index 20acd63572..45ca876879 100644 --- a/include/boost/math/statistics/univariate_statistics.hpp +++ b/include/boost/math/statistics/univariate_statistics.hpp @@ -10,6 +10,7 @@ #include #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -19,16 +20,35 @@ #include #include #include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { + +// mode() can only sort a range in place when its iterators are random access and +// writable. A const random access iterator (e.g. vector::const_iterator) satisfies +// random_access_iterator_tag but cannot be sorted through, so such ranges must instead +// be pre-sorted by the caller. +template +using is_sortable_iterator = std::integral_constant::iterator_category, std::random_access_iterator_tag>::value && + std::is_assignable::reference, + typename std::iterator_traits::value_type>::value>; + +}} BOOST_MATH_NAMESPACE_END // namespace boost::math::statistics::detail #ifdef BOOST_MATH_EXEC_COMPATIBLE +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost::math::statistics { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { -template +BOOST_MATH_EXPORT template inline auto mean(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { using Real = typename std::iterator_traits::value_type; + static_assert(std::is_convertible_v::iterator_category, std::forward_iterator_tag>, + "mean() requires at least a forward iterator. Input iterators such as std::istream_iterator are single-pass and produce incorrect results."); BOOST_MATH_ASSERT_MSG(first != last, "At least one sample is required to compute the mean."); if constexpr (std::is_integral_v) @@ -55,25 +75,25 @@ inline auto mean(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator } } -template +BOOST_MATH_EXPORT template inline auto mean(ExecutionPolicy&& exec, Container const & v) { return mean(exec, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto mean(ForwardIterator first, ForwardIterator last) { return mean(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto mean(Container const & v) { return mean(std::execution::seq, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto variance(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { using Real = typename std::iterator_traits::value_type; @@ -104,25 +124,25 @@ inline auto variance(ExecutionPolicy&& exec, ForwardIterator first, ForwardItera } } -template +BOOST_MATH_EXPORT template inline auto variance(ExecutionPolicy&& exec, Container const & v) { return variance(exec, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto variance(ForwardIterator first, ForwardIterator last) { return variance(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto variance(Container const & v) { return variance(std::execution::seq, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto sample_variance(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { const auto n = std::distance(first, last); @@ -130,25 +150,25 @@ inline auto sample_variance(ExecutionPolicy&& exec, ForwardIterator first, Forwa return n*variance(exec, first, last)/(n-1); } -template +BOOST_MATH_EXPORT template inline auto sample_variance(ExecutionPolicy&& exec, Container const & v) { return sample_variance(exec, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto sample_variance(ForwardIterator first, ForwardIterator last) { return sample_variance(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto sample_variance(Container const & v) { return sample_variance(std::execution::seq, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto mean_and_sample_variance(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { using Real = typename std::iterator_traits::value_type; @@ -181,25 +201,25 @@ inline auto mean_and_sample_variance(ExecutionPolicy&& exec, ForwardIterator fir } } -template +BOOST_MATH_EXPORT template inline auto mean_and_sample_variance(ExecutionPolicy&& exec, Container const & v) { return mean_and_sample_variance(exec, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto mean_and_sample_variance(ForwardIterator first, ForwardIterator last) { return mean_and_sample_variance(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto mean_and_sample_variance(Container const & v) { return mean_and_sample_variance(std::execution::seq, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto first_four_moments(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { using Real = typename std::iterator_traits::value_type; @@ -236,26 +256,26 @@ inline auto first_four_moments(ExecutionPolicy&& exec, ForwardIterator first, Fo } } -template +BOOST_MATH_EXPORT template inline auto first_four_moments(ExecutionPolicy&& exec, Container const & v) { return first_four_moments(exec, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto first_four_moments(ForwardIterator first, ForwardIterator last) { return first_four_moments(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto first_four_moments(Container const & v) { return first_four_moments(std::execution::seq, std::cbegin(v), std::cend(v)); } // https://prod.sandia.gov/techlib-noauth/access-control.cgi/2008/086212.pdf -template +BOOST_MATH_EXPORT template inline auto skewness(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { using Real = typename std::iterator_traits::value_type; @@ -298,19 +318,19 @@ inline auto skewness(ExecutionPolicy&& exec, ForwardIterator first, ForwardItera } } -template +BOOST_MATH_EXPORT template inline auto skewness(ExecutionPolicy&& exec, Container & v) { return skewness(exec, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto skewness(ForwardIterator first, ForwardIterator last) { return skewness(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto skewness(Container const & v) { return skewness(std::execution::seq, std::cbegin(v), std::cend(v)); @@ -318,7 +338,7 @@ inline auto skewness(Container const & v) // Follows equation 1.6 of: // https://prod.sandia.gov/techlib-noauth/access-control.cgi/2008/086212.pdf -template +BOOST_MATH_EXPORT template inline auto kurtosis(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { const auto [M1, M2, M3, M4] = first_four_moments(exec, first, last); @@ -329,50 +349,50 @@ inline auto kurtosis(ExecutionPolicy&& exec, ForwardIterator first, ForwardItera return M4/(M2*M2); } -template +BOOST_MATH_EXPORT template inline auto kurtosis(ExecutionPolicy&& exec, Container const & v) { return kurtosis(exec, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto kurtosis(ForwardIterator first, ForwardIterator last) { return kurtosis(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto kurtosis(Container const & v) { return kurtosis(std::execution::seq, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto excess_kurtosis(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { return kurtosis(exec, first, last) - 3; } -template +BOOST_MATH_EXPORT template inline auto excess_kurtosis(ExecutionPolicy&& exec, Container const & v) { return excess_kurtosis(exec, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template inline auto excess_kurtosis(ForwardIterator first, ForwardIterator last) { return excess_kurtosis(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto excess_kurtosis(Container const & v) { return excess_kurtosis(std::execution::seq, std::cbegin(v), std::cend(v)); } -template +BOOST_MATH_EXPORT template auto median(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { const auto num_elems = std::distance(first, last); @@ -393,19 +413,19 @@ auto median(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIter } -template +BOOST_MATH_EXPORT template inline auto median(ExecutionPolicy&& exec, RandomAccessContainer & v) { return median(exec, std::begin(v), std::end(v)); } -template +BOOST_MATH_EXPORT template inline auto median(RandomAccessIterator first, RandomAccessIterator last) { return median(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto median(RandomAccessContainer & v) { return median(std::execution::seq, std::begin(v), std::end(v)); @@ -417,7 +437,7 @@ inline auto median(RandomAccessContainer & v) // https://github.com/boostorg/math/issues/585 // We will fix this at a later date, for now just use a serial implementation: // -template +BOOST_MATH_EXPORT template inline auto gini_coefficient(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { using Real = typename std::iterator_traits::value_type; @@ -450,7 +470,7 @@ inline auto gini_coefficient(ExecutionPolicy&& exec, RandomAccessIterator first, } } #else -template +BOOST_MATH_EXPORT template inline auto gini_coefficient(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { using Real = typename std::iterator_traits::value_type; @@ -471,50 +491,50 @@ inline auto gini_coefficient(ExecutionPolicy&& exec, RandomAccessIterator first, } #endif -template +BOOST_MATH_EXPORT template inline auto gini_coefficient(ExecutionPolicy&& exec, RandomAccessContainer & v) { return gini_coefficient(exec, std::begin(v), std::end(v)); } -template +BOOST_MATH_EXPORT template inline auto gini_coefficient(RandomAccessIterator first, RandomAccessIterator last) { return gini_coefficient(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto gini_coefficient(RandomAccessContainer & v) { return gini_coefficient(std::execution::seq, std::begin(v), std::end(v)); } -template +BOOST_MATH_EXPORT template inline auto sample_gini_coefficient(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { const auto n = std::distance(first, last); return n*gini_coefficient(exec, first, last)/(n-1); } -template +BOOST_MATH_EXPORT template inline auto sample_gini_coefficient(ExecutionPolicy&& exec, RandomAccessContainer & v) { return sample_gini_coefficient(exec, std::begin(v), std::end(v)); } -template +BOOST_MATH_EXPORT template inline auto sample_gini_coefficient(RandomAccessIterator first, RandomAccessIterator last) { return sample_gini_coefficient(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto sample_gini_coefficient(RandomAccessContainer & v) { return sample_gini_coefficient(std::execution::seq, std::begin(v), std::end(v)); } -template +BOOST_MATH_EXPORT template auto median_absolute_deviation(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, typename std::iterator_traits::value_type center=std::numeric_limits::value_type>::quiet_NaN()) { @@ -523,7 +543,7 @@ auto median_absolute_deviation(ExecutionPolicy&& exec, RandomAccessIterator firs using std::isnan; if (isnan(center)) { - center = boost::math::statistics::median(exec, first, last); + center = BOOST_MATH_NAMESPACE::statistics::median(exec, first, last); } const auto num_elems = std::distance(first, last); BOOST_MATH_ASSERT_MSG(num_elems > 0, "The median of a zero-length vector is undefined."); @@ -543,28 +563,28 @@ auto median_absolute_deviation(ExecutionPolicy&& exec, RandomAccessIterator firs } } -template +BOOST_MATH_EXPORT template inline auto median_absolute_deviation(ExecutionPolicy&& exec, RandomAccessContainer & v, typename RandomAccessContainer::value_type center=std::numeric_limits::quiet_NaN()) { return median_absolute_deviation(exec, std::begin(v), std::end(v), center); } -template +BOOST_MATH_EXPORT template inline auto median_absolute_deviation(RandomAccessIterator first, RandomAccessIterator last, typename RandomAccessIterator::value_type center=std::numeric_limits::quiet_NaN()) { return median_absolute_deviation(std::execution::seq, first, last, center); } -template +BOOST_MATH_EXPORT template inline auto median_absolute_deviation(RandomAccessContainer & v, typename RandomAccessContainer::value_type center=std::numeric_limits::quiet_NaN()) { return median_absolute_deviation(std::execution::seq, std::begin(v), std::end(v), center); } -template +BOOST_MATH_EXPORT template auto interquartile_range(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { using Real = typename std::iterator_traits::value_type; @@ -605,49 +625,49 @@ auto interquartile_range(ExecutionPolicy&& exec, ForwardIterator first, ForwardI } } -template +BOOST_MATH_EXPORT template inline auto interquartile_range(ExecutionPolicy&& exec, RandomAccessContainer & v) { return interquartile_range(exec, std::begin(v), std::end(v)); } -template +BOOST_MATH_EXPORT template inline auto interquartile_range(RandomAccessIterator first, RandomAccessIterator last) { return interquartile_range(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto interquartile_range(RandomAccessContainer & v) { return interquartile_range(std::execution::seq, std::begin(v), std::end(v)); } -template +BOOST_MATH_EXPORT template inline OutputIterator mode(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, OutputIterator output) { if(!std::is_sorted(exec, first, last)) { - if constexpr (std::is_same_v::iterator_category(), std::random_access_iterator_tag>) + if constexpr (detail::is_sortable_iterator::value) { std::sort(exec, first, last); } else { - BOOST_MATH_ASSERT("Data must be sorted for sequential mode calculation"); + BOOST_MATH_ASSERT_MSG(false, "Data must be sorted for sequential mode calculation"); } } return detail::mode_impl(first, last, output); } -template +BOOST_MATH_EXPORT template inline OutputIterator mode(ExecutionPolicy&& exec, Container & v, OutputIterator output) { return mode(exec, std::begin(v), std::end(v), output); } -template +BOOST_MATH_EXPORT template inline OutputIterator mode(ForwardIterator first, ForwardIterator last, OutputIterator output) { return mode(std::execution::seq, first, last, output); @@ -655,7 +675,7 @@ inline OutputIterator mode(ForwardIterator first, ForwardIterator last, OutputIt // Requires enable_if_t to not clash with impl that returns std::list // Very ugly. std::is_execution_policy_v returns false for the std::execution objects and decltype of the objects (e.g. std::execution::seq) -template && +BOOST_MATH_EXPORT template && !std::is_convertible_v && !std::is_convertible_v #if __cpp_lib_execution > 201900 @@ -669,7 +689,7 @@ inline OutputIterator mode(Container & v, OutputIterator output) // std::list is the return type for the proposed STL stats library -template::value_type> +BOOST_MATH_EXPORT template::value_type> inline auto mode(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { std::list modes; @@ -677,78 +697,82 @@ inline auto mode(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator return modes; } -template +BOOST_MATH_EXPORT template inline auto mode(ExecutionPolicy&& exec, Container & v) { return mode(exec, std::begin(v), std::end(v)); } -template +BOOST_MATH_EXPORT template inline auto mode(ForwardIterator first, ForwardIterator last) { return mode(std::execution::seq, first, last); } -template +BOOST_MATH_EXPORT template inline auto mode(Container & v) { return mode(std::execution::seq, std::begin(v), std::end(v)); } -} // Namespace boost::math::statistics +} BOOST_MATH_NAMESPACE_END // Namespace boost::math::statistics #else // Backwards compatible bindings for C++11 or execution is not implemented -namespace boost { namespace math { namespace statistics { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { template using enable_if_t = typename std::enable_if::type; -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline double mean(const ForwardIterator first, const ForwardIterator last) { + static_assert(std::is_convertible::iterator_category, std::forward_iterator_tag>::value, + "mean() requires at least a forward iterator. Input iterators such as std::istream_iterator are single-pass and produce incorrect results."); BOOST_MATH_ASSERT_MSG(first != last, "At least one sample is required to compute the mean."); return detail::mean_sequential_impl(first, last); } -template::value, bool> = true> inline double mean(const Container& c) { return mean(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline Real mean(const ForwardIterator first, const ForwardIterator last) { + static_assert(std::is_convertible::iterator_category, std::forward_iterator_tag>::value, + "mean() requires at least a forward iterator. Input iterators such as std::istream_iterator are single-pass and produce incorrect results."); BOOST_MATH_ASSERT_MSG(first != last, "At least one sample is required to compute the mean."); return detail::mean_sequential_impl(first, last); } -template::value, bool> = true> inline Real mean(const Container& c) { return mean(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline double variance(const ForwardIterator first, const ForwardIterator last) { return std::get<2>(detail::variance_sequential_impl>(first, last)); } -template::value, bool> = true> inline double variance(const Container& c) { return variance(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline Real variance(const ForwardIterator first, const ForwardIterator last) { @@ -756,14 +780,14 @@ inline Real variance(const ForwardIterator first, const ForwardIterator last) } -template::value, bool> = true> inline Real variance(const Container& c) { return variance(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline double sample_variance(const ForwardIterator first, const ForwardIterator last) { @@ -772,14 +796,14 @@ inline double sample_variance(const ForwardIterator first, const ForwardIterator return n*variance(first, last)/(n-1); } -template::value, bool> = true> inline double sample_variance(const Container& c) { return sample_variance(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline Real sample_variance(const ForwardIterator first, const ForwardIterator last) { @@ -788,14 +812,14 @@ inline Real sample_variance(const ForwardIterator first, const ForwardIterator l return n*variance(first, last)/(n-1); } -template::value, bool> = true> inline Real sample_variance(const Container& c) { return sample_variance(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline std::pair mean_and_sample_variance(const ForwardIterator first, const ForwardIterator last) { @@ -803,14 +827,14 @@ inline std::pair mean_and_sample_variance(const ForwardIterator return std::make_pair(std::get<0>(results), std::get<3>(results)*std::get<2>(results)/(std::get<3>(results)-1.0)); } -template::value, bool> = true> inline std::pair mean_and_sample_variance(const Container& c) { return mean_and_sample_variance(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline std::pair mean_and_sample_variance(const ForwardIterator first, const ForwardIterator last) { @@ -818,14 +842,14 @@ inline std::pair mean_and_sample_variance(const ForwardIterator firs return std::make_pair(std::get<0>(results), std::get<3>(results)*std::get<2>(results)/(std::get<3>(results)-Real(1))); } -template::value, bool> = true> inline std::pair mean_and_sample_variance(const Container& c) { return mean_and_sample_variance(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline std::tuple first_four_moments(const ForwardIterator first, const ForwardIterator last) { @@ -834,14 +858,14 @@ inline std::tuple first_four_moments(const Forwa std::get<3>(results) / std::get<4>(results)); } -template::value, bool> = true> inline std::tuple first_four_moments(const Container& c) { return first_four_moments(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline std::tuple first_four_moments(const ForwardIterator first, const ForwardIterator last) { @@ -850,42 +874,42 @@ inline std::tuple first_four_moments(const ForwardIterat std::get<3>(results) / std::get<4>(results)); } -template::value, bool> = true> inline std::tuple first_four_moments(const Container& c) { return first_four_moments(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline double skewness(const ForwardIterator first, const ForwardIterator last) { return detail::skewness_sequential_impl(first, last); } -template::value, bool> = true> inline double skewness(const Container& c) { return skewness(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline Real skewness(const ForwardIterator first, const ForwardIterator last) { return detail::skewness_sequential_impl(first, last); } -template::value, bool> = true> inline Real skewness(const Container& c) { return skewness(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline double kurtosis(const ForwardIterator first, const ForwardIterator last) { @@ -901,14 +925,14 @@ inline double kurtosis(const ForwardIterator first, const ForwardIterator last) } } -template::value, bool> = true> inline double kurtosis(const Container& c) { return kurtosis(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline Real kurtosis(const ForwardIterator first, const ForwardIterator last) { @@ -924,42 +948,42 @@ inline Real kurtosis(const ForwardIterator first, const ForwardIterator last) } } -template::value, bool> = true> inline Real kurtosis(const Container& c) { return kurtosis(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline double excess_kurtosis(const ForwardIterator first, const ForwardIterator last) { return kurtosis(first, last) - 3; } -template::value, bool> = true> inline double excess_kurtosis(const Container& c) { return excess_kurtosis(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline Real excess_kurtosis(const ForwardIterator first, const ForwardIterator last) { return kurtosis(first, last) - 3; } -template::value, bool> = true> inline Real excess_kurtosis(const Container& c) { return excess_kurtosis(std::begin(c), std::end(c)); } -template::value_type> +BOOST_MATH_EXPORT template::value_type> Real median(RandomAccessIterator first, RandomAccessIterator last) { const auto num_elems = std::distance(first, last); @@ -979,13 +1003,13 @@ Real median(RandomAccessIterator first, RandomAccessIterator last) } } -template +BOOST_MATH_EXPORT template inline Real median(RandomAccessContainer& c) { return median(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline double gini_coefficient(RandomAccessIterator first, RandomAccessIterator last) { @@ -997,14 +1021,14 @@ inline double gini_coefficient(RandomAccessIterator first, RandomAccessIterator return detail::gini_coefficient_sequential_impl(first, last); } -template::value, bool> = true> inline double gini_coefficient(RandomAccessContainer& c) { return gini_coefficient(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline Real gini_coefficient(RandomAccessIterator first, RandomAccessIterator last) { @@ -1016,14 +1040,14 @@ inline Real gini_coefficient(RandomAccessIterator first, RandomAccessIterator la return detail::gini_coefficient_sequential_impl(first, last); } -template::value, bool> = true> inline Real gini_coefficient(RandomAccessContainer& c) { return gini_coefficient(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline double sample_gini_coefficient(RandomAccessIterator first, RandomAccessIterator last) { @@ -1031,14 +1055,14 @@ inline double sample_gini_coefficient(RandomAccessIterator first, RandomAccessIt return n*gini_coefficient(first, last)/(n-1); } -template::value, bool> = true> inline double sample_gini_coefficient(RandomAccessContainer& c) { return sample_gini_coefficient(std::begin(c), std::end(c)); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, enable_if_t::value, bool> = true> inline Real sample_gini_coefficient(RandomAccessIterator first, RandomAccessIterator last) { @@ -1046,14 +1070,14 @@ inline Real sample_gini_coefficient(RandomAccessIterator first, RandomAccessIter return n*gini_coefficient(first, last)/(n-1); } -template::value, bool> = true> inline Real sample_gini_coefficient(RandomAccessContainer& c) { return sample_gini_coefficient(std::begin(c), std::end(c)); } -template::value_type> +BOOST_MATH_EXPORT template::value_type> Real median_absolute_deviation(RandomAccessIterator first, RandomAccessIterator last, typename std::iterator_traits::value_type center=std::numeric_limits::value_type>::quiet_NaN()) { @@ -1061,7 +1085,7 @@ Real median_absolute_deviation(RandomAccessIterator first, RandomAccessIterator using std::isnan; if (isnan(center)) { - center = boost::math::statistics::median(first, last); + center = BOOST_MATH_NAMESPACE::statistics::median(first, last); } const auto num_elems = std::distance(first, last); BOOST_MATH_ASSERT_MSG(num_elems > 0, "The median of a zero-length vector is undefined."); @@ -1081,14 +1105,14 @@ Real median_absolute_deviation(RandomAccessIterator first, RandomAccessIterator } } -template +BOOST_MATH_EXPORT template inline Real median_absolute_deviation(RandomAccessContainer& c, typename RandomAccessContainer::value_type center=std::numeric_limits::quiet_NaN()) { return median_absolute_deviation(std::begin(c), std::end(c), center); } -template::value_type> +BOOST_MATH_EXPORT template::value_type> Real interquartile_range(ForwardIterator first, ForwardIterator last) { static_assert(!std::is_integral::value, "Integer values have not yet been implemented."); @@ -1130,14 +1154,14 @@ Real interquartile_range(ForwardIterator first, ForwardIterator last) } } -template +BOOST_MATH_EXPORT template Real interquartile_range(Container& c) { return interquartile_range(std::begin(c), std::end(c)); } -template::iterator_category(), std::random_access_iterator_tag>::value, bool> = true> +BOOST_MATH_EXPORT template::value, bool> = true> inline OutputIterator mode(ForwardIterator first, ForwardIterator last, OutputIterator output) { if(!std::is_sorted(first, last)) @@ -1148,37 +1172,57 @@ inline OutputIterator mode(ForwardIterator first, ForwardIterator last, OutputIt return detail::mode_impl(first, last, output); } -template::iterator_category(), std::random_access_iterator_tag>::value, bool> = true> +BOOST_MATH_EXPORT template::value, bool> = true> inline OutputIterator mode(ForwardIterator first, ForwardIterator last, OutputIterator output) { if(!std::is_sorted(first, last)) { - BOOST_MATH_ASSERT("Data must be sorted for mode calculation"); + BOOST_MATH_ASSERT_MSG(false, "Data must be sorted for mode calculation"); } return detail::mode_impl(first, last, output); } -template +BOOST_MATH_EXPORT template inline OutputIterator mode(Container& c, OutputIterator output) { return mode(std::begin(c), std::end(c), output); } -template::value_type> +BOOST_MATH_EXPORT template::value_type, + enable_if_t::value, bool> = true> inline std::list mode(ForwardIterator first, ForwardIterator last) { + if (!std::is_sorted(first, last)) + { + std::sort(first, last); + } + + std::list modes; + mode(first, last, std::inserter(modes, modes.begin())); + return modes; +} + +BOOST_MATH_EXPORT template::value_type, + enable_if_t::value, bool> = true> +inline std::list mode(ForwardIterator first, ForwardIterator last) +{ + if (!std::is_sorted(first, last)) + { + BOOST_MATH_ASSERT_MSG(false, "Data must be sorted for mode calculation"); + } + std::list modes; mode(first, last, std::inserter(modes, modes.begin())); return modes; } -template +BOOST_MATH_EXPORT template inline std::list mode(Container& c) { return mode(std::begin(c), std::end(c)); } -}}} +} BOOST_MATH_NAMESPACE_END #endif #endif // BOOST_MATH_STATISTICS_UNIVARIATE_STATISTICS_HPP diff --git a/include/boost/math/statistics/z_test.hpp b/include/boost/math/statistics/z_test.hpp index a8ef838e40..2f69271083 100644 --- a/include/boost/math/statistics/z_test.hpp +++ b/include/boost/math/statistics/z_test.hpp @@ -8,30 +8,32 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif -namespace boost { namespace math { namespace statistics { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace statistics { namespace detail { template ReturnType one_sample_z_test_impl(T sample_mean, T sample_variance, T sample_size, T assumed_mean) { using Real = typename std::tuple_element<0, ReturnType>::type; using std::sqrt; - using no_promote_policy = boost::math::policies::policy, boost::math::policies::promote_double>; + using no_promote_policy = BOOST_MATH_NAMESPACE::policies::policy, BOOST_MATH_NAMESPACE::policies::promote_double>; Real test_statistic = (sample_mean - assumed_mean) / (sample_variance / sqrt(sample_size)); - auto z = boost::math::normal_distribution(sample_size - 1); + auto z = BOOST_MATH_NAMESPACE::normal_distribution(sample_size - 1); Real pvalue; if(test_statistic > 0) { - pvalue = 2*boost::math::cdf(z, -test_statistic); + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(z, -test_statistic); } else { - pvalue = 2*boost::math::cdf(z, test_statistic); + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(z, test_statistic); } return std::make_pair(test_statistic, pvalue); @@ -52,18 +54,18 @@ ReturnType two_sample_z_test_impl(T mean_1, T variance_1, T size_1, T mean_2, T { using Real = typename std::tuple_element<0, ReturnType>::type; using std::sqrt; - using no_promote_policy = boost::math::policies::policy, boost::math::policies::promote_double>; + using no_promote_policy = BOOST_MATH_NAMESPACE::policies::policy, BOOST_MATH_NAMESPACE::policies::promote_double>; Real test_statistic = (mean_1 - mean_2) / sqrt(variance_1/size_1 + variance_2/size_2); - auto z = boost::math::normal_distribution(size_1 + size_2 - 1); + auto z = BOOST_MATH_NAMESPACE::normal_distribution(size_1 + size_2 - 1); Real pvalue; if(test_statistic > 0) { - pvalue = 2*boost::math::cdf(z, -test_statistic); + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(z, -test_statistic); } else { - pvalue = 2*boost::math::cdf(z, test_statistic); + pvalue = 2*BOOST_MATH_NAMESPACE::cdf(z, test_statistic); } return std::make_pair(test_statistic, pvalue); @@ -90,72 +92,72 @@ ReturnType two_sample_z_test_impl(ForwardIterator begin_1, ForwardIterator end_1 } // detail -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto one_sample_z_test(Real sample_mean, Real sample_variance, Real sample_size, Real assumed_mean) -> std::pair { return detail::one_sample_z_test_impl>(sample_mean, sample_variance, sample_size, assumed_mean); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto one_sample_z_test(Real sample_mean, Real sample_variance, Real sample_size, Real assumed_mean) -> std::pair { return detail::one_sample_z_test_impl>(sample_mean, sample_variance, sample_size, assumed_mean); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto one_sample_z_test(ForwardIterator begin, ForwardIterator end, Real assumed_mean) -> std::pair { return detail::one_sample_z_test_impl>(begin, end, assumed_mean); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto one_sample_z_test(ForwardIterator begin, ForwardIterator end, Real assumed_mean) -> std::pair { return detail::one_sample_z_test_impl>(begin, end, assumed_mean); } -template::value, bool>::type = true> inline auto one_sample_z_test(Container const & v, Real assumed_mean) -> std::pair { return detail::one_sample_z_test_impl>(std::begin(v), std::end(v), assumed_mean); } -template::value, bool>::type = true> inline auto one_sample_z_test(Container const & v, Real assumed_mean) -> std::pair { return detail::one_sample_z_test_impl>(std::begin(v), std::end(v), assumed_mean); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto two_sample_z_test(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2) -> std::pair { return detail::two_sample_z_test_impl>(begin_1, end_1, begin_2, end_2); } -template::value_type, +BOOST_MATH_EXPORT template::value_type, typename std::enable_if::value, bool>::type = true> inline auto two_sample_z_test(ForwardIterator begin_1, ForwardIterator end_1, ForwardIterator begin_2, ForwardIterator end_2) -> std::pair { return detail::two_sample_z_test_impl>(begin_1, end_1, begin_2, end_2); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto two_sample_z_test(Container const & u, Container const & v) -> std::pair { return detail::two_sample_z_test_impl>(std::begin(u), std::end(u), std::begin(v), std::end(v)); } -template::value, bool>::type = true> +BOOST_MATH_EXPORT template::value, bool>::type = true> inline auto two_sample_z_test(Container const & u, Container const & v) -> std::pair { return detail::two_sample_z_test_impl>(std::begin(u), std::end(u), std::begin(v), std::end(v)); } -}}} // boost::math::statistics +} BOOST_MATH_NAMESPACE_END // boost::math::statistics #endif // BOOST_MATH_STATISTICS_Z_TEST_HPP diff --git a/include/boost/math/tools/agm.hpp b/include/boost/math/tools/agm.hpp index 2b5a06be5d..b71e0d51af 100644 --- a/include/boost/math/tools/agm.hpp +++ b/include/boost/math/tools/agm.hpp @@ -5,12 +5,16 @@ #ifndef BOOST_MATH_TOOLS_AGM_HPP #define BOOST_MATH_TOOLS_AGM_HPP + +#include +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif -namespace boost { namespace math { namespace tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { -template +BOOST_MATH_EXPORT template Real agm(Real a, Real g) { using std::sqrt; @@ -43,5 +47,5 @@ Real agm(Real a, Real g) } -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/array.hpp b/include/boost/math/tools/array.hpp index 23e666673c..54fce7d076 100644 --- a/include/boost/math/tools/array.hpp +++ b/include/boost/math/tools/array.hpp @@ -16,25 +16,23 @@ #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN using cuda::std::array; -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN using std::array; -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ENABLE_CUDA diff --git a/include/boost/math/tools/assert.hpp b/include/boost/math/tools/assert.hpp index 3f57351fc1..5c37aa4cef 100644 --- a/include/boost/math/tools/assert.hpp +++ b/include/boost/math/tools/assert.hpp @@ -36,9 +36,14 @@ #else // Standalone mode - use cassert +#ifndef BOOST_MATH_BUILD_MODULE #include #define BOOST_MATH_ASSERT(expr) assert(expr) #define BOOST_MATH_ASSERT_MSG(expr, msg) assert((expr)&&(msg)) +#else +#define BOOST_MATH_ASSERT(expr) +#define BOOST_MATH_ASSERT_MSG(expr, msg) +#endif #define BOOST_MATH_STATIC_ASSERT(expr) static_assert(expr, #expr " failed") #define BOOST_MATH_STATIC_ASSERT_MSG(expr, msg) static_assert(expr, msg) diff --git a/include/boost/math/tools/atomic.hpp b/include/boost/math/tools/atomic.hpp index f558bd63ae..c5d43e03b2 100644 --- a/include/boost/math/tools/atomic.hpp +++ b/include/boost/math/tools/atomic.hpp @@ -11,10 +11,11 @@ #include #ifdef BOOST_MATH_HAS_THREADS +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace detail { #if (ATOMIC_INT_LOCK_FREE == 2) && !defined(BOOST_MATH_NO_ATOMIC_INT) typedef std::atomic atomic_counter_type; @@ -40,8 +41,7 @@ namespace boost { # define BOOST_MATH_NO_ATOMIC_INT #endif } // Namespace detail - } // Namespace math -} // Namespace boost + BOOST_MATH_NAMESPACE_END #else # define BOOST_MATH_NO_ATOMIC_INT diff --git a/include/boost/math/tools/big_constant.hpp b/include/boost/math/tools/big_constant.hpp index 8e731c090e..11b695a673 100644 --- a/include/boost/math/tools/big_constant.hpp +++ b/include/boost/math/tools/big_constant.hpp @@ -18,11 +18,13 @@ #include #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ @@ -85,24 +87,24 @@ inline constexpr T make_big_value(largest_float, const char* s, std::false_type // actually work. Workaround is the || std::is_floating_point::value part which thankfully is true. // #define BOOST_MATH_BIG_CONSTANT(T, D, x)\ - boost::math::tools::make_big_value(\ + BOOST_MATH_NAMESPACE::tools::make_big_value(\ BOOST_MATH_LARGEST_FLOAT_C(x), \ BOOST_MATH_STRINGIZE(x), \ - std::integral_constant::value || std::is_floating_point::value) && \ - ((D <= boost::math::tools::numeric_traits::digits) \ + std::integral_constant::value || std::is_floating_point::value) && \ + ((D <= BOOST_MATH_NAMESPACE::tools::numeric_traits::digits) \ || std::is_floating_point::value \ - || (boost::math::tools::numeric_traits::is_specialized && \ - (boost::math::tools::numeric_traits::digits10 <= boost::math::tools::numeric_traits::digits10))) >(), \ + || (BOOST_MATH_NAMESPACE::tools::numeric_traits::is_specialized && \ + (BOOST_MATH_NAMESPACE::tools::numeric_traits::digits10 <= BOOST_MATH_NAMESPACE::tools::numeric_traits::digits10))) >(), \ std::is_constructible()) // // For constants too huge for any conceivable long double (and which generate compiler errors if we try and declare them as such): // #define BOOST_MATH_HUGE_CONSTANT(T, D, x)\ - boost::math::tools::make_big_value(0.0L, BOOST_MATH_STRINGIZE(x), \ - std::integral_constant::value || (boost::math::tools::numeric_traits::is_specialized && boost::math::tools::numeric_traits::max_exponent <= boost::math::tools::numeric_traits::max_exponent && boost::math::tools::numeric_traits::digits <= boost::math::tools::numeric_traits::digits)>(), \ + BOOST_MATH_NAMESPACE::tools::make_big_value(0.0L, BOOST_MATH_STRINGIZE(x), \ + std::integral_constant::value || (BOOST_MATH_NAMESPACE::tools::numeric_traits::is_specialized && BOOST_MATH_NAMESPACE::tools::numeric_traits::max_exponent <= BOOST_MATH_NAMESPACE::tools::numeric_traits::max_exponent && BOOST_MATH_NAMESPACE::tools::numeric_traits::digits <= BOOST_MATH_NAMESPACE::tools::numeric_traits::digits)>(), \ std::is_constructible()) -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC diff --git a/include/boost/math/tools/bit.hpp b/include/boost/math/tools/bit.hpp new file mode 100644 index 0000000000..e68f987d13 --- /dev/null +++ b/include/boost/math/tools/bit.hpp @@ -0,0 +1,148 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Portable bit manipulation helpers usable from host and device code. +// Everything here works on 64-bit unsigned values and never relies on +// function-local static tables, so it is safe under CUDA and SYCL. + +#ifndef BOOST_MATH_TOOLS_BIT_HPP +#define BOOST_MATH_TOOLS_BIT_HPP + +#include +#include + +#ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE +#if defined(__has_include) +# if __has_include() +# include +# endif +#endif +#if defined(__cpp_lib_bitops) && (__cpp_lib_bitops >= 201907L) +# include +#endif +#if defined(_MSC_VER) && !defined(__clang__) +# include +#endif +#endif // BOOST_MATH_BUILD_MODULE +#endif // BOOST_MATH_HAS_NVRTC + +BOOST_MATH_NAMESPACE_BEGIN namespace tools { + +// Number of trailing zero bits in x. Returns 64 when x is zero. +BOOST_MATH_GPU_ENABLED inline int countr_zero(BOOST_MATH_NAMESPACE::uint64_t x) noexcept +{ +#if defined(__CUDA_ARCH__) + return x == 0 ? 64 : __ffsll(static_cast(x)) - 1; +#elif defined(__cpp_lib_bitops) && (__cpp_lib_bitops >= 201907L) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) + return std::countr_zero(static_cast(x)); +#elif defined(__GNUC__) || defined(__clang__) + return x == 0 ? 64 : __builtin_ctzll(static_cast(x)); +#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) + unsigned long index {}; + return _BitScanForward64(&index, static_cast(x)) ? static_cast(index) : 64; +#else + if (x == 0) + { + return 64; + } + int n {0}; + while ((x & 1u) == 0) + { + x >>= 1; + ++n; + } + return n; +#endif +} + +// Number of leading zero bits in x. Returns 64 when x is zero. +BOOST_MATH_GPU_ENABLED inline int countl_zero(BOOST_MATH_NAMESPACE::uint64_t x) noexcept +{ +#if defined(__CUDA_ARCH__) + return __clzll(static_cast(x)); +#elif defined(__cpp_lib_bitops) && (__cpp_lib_bitops >= 201907L) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) + return std::countl_zero(static_cast(x)); +#elif defined(__GNUC__) || defined(__clang__) + return x == 0 ? 64 : __builtin_clzll(static_cast(x)); +#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) + unsigned long index {}; + return _BitScanReverse64(&index, static_cast(x)) ? 63 - static_cast(index) : 64; +#else + if (x == 0) + { + return 64; + } + int n {0}; + while ((x >> 63) == 0) + { + x <<= 1; + ++n; + } + return n; +#endif +} + +// Number of set bits in x. +BOOST_MATH_GPU_ENABLED inline int popcount(BOOST_MATH_NAMESPACE::uint64_t x) noexcept +{ +#if defined(__CUDA_ARCH__) + return __popcll(static_cast(x)); +#elif defined(__cpp_lib_bitops) && (__cpp_lib_bitops >= 201907L) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) + return std::popcount(static_cast(x)); +#elif defined(__GNUC__) || defined(__clang__) + return __builtin_popcountll(static_cast(x)); +#else + // Parallel bit count (Hacker's Delight, figure 5-2) + x = x - ((x >> 1) & 0x5555555555555555ULL); + x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL); + x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fULL; + return static_cast((x * 0x0101010101010101ULL) >> 56); +#endif +} + +// Largest power of two not exceeding x. Returns 0 for x == 0. +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::uint64_t floor_pow2(BOOST_MATH_NAMESPACE::uint64_t x) noexcept +{ + return x == 0 ? 0 : BOOST_MATH_NAMESPACE::uint64_t(1) << (63 - countl_zero(x)); +} + +// Exact integer square root: the largest r with r * r <= n. +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::uint64_t isqrt(BOOST_MATH_NAMESPACE::uint64_t n) noexcept +{ + if (n < 2) + { + return n; + } + // Newton iteration from a power of two above the root converges monotonically down. + const int bits {64 - countl_zero(n)}; + BOOST_MATH_NAMESPACE::uint64_t x {BOOST_MATH_NAMESPACE::uint64_t(1) << ((bits + 1) / 2)}; + while (true) + { + const BOOST_MATH_NAMESPACE::uint64_t y {(x + n / x) / 2}; + if (y >= x) + { + return x; + } + x = y; + } +} + +// Reads eight bytes as a little-endian 64-bit value regardless of host byte order. +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::uint64_t load_le64(const unsigned char* p) noexcept +{ + return static_cast(p[0]) + | (static_cast(p[1]) << 8) + | (static_cast(p[2]) << 16) + | (static_cast(p[3]) << 24) + | (static_cast(p[4]) << 32) + | (static_cast(p[5]) << 40) + | (static_cast(p[6]) << 48) + | (static_cast(p[7]) << 56); +} + +} BOOST_MATH_NAMESPACE_END // namespace boost::math::tools + +#endif // BOOST_MATH_TOOLS_BIT_HPP diff --git a/include/boost/math/tools/bivariate_statistics.hpp b/include/boost/math/tools/bivariate_statistics.hpp index eaed5838ea..5e81a2ed52 100644 --- a/include/boost/math/tools/bivariate_statistics.hpp +++ b/include/boost/math/tools/bivariate_statistics.hpp @@ -6,15 +6,17 @@ #ifndef BOOST_MATH_TOOLS_BIVARIATE_STATISTICS_HPP #define BOOST_MATH_TOOLS_BIVARIATE_STATISTICS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include BOOST_MATH_HEADER_DEPRECATED(""); -namespace boost{ namespace math{ namespace tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { template auto means_and_covariance(Container const & u, Container const & v) @@ -44,7 +46,7 @@ auto means_and_covariance(Container const & u, Container const & v) template auto covariance(Container const & u, Container const & v) { - auto [mu_u, mu_v, cov] = boost::math::tools::means_and_covariance(u, v); + auto [mu_u, mu_v, cov] = BOOST_MATH_NAMESPACE::tools::means_and_covariance(u, v); return cov; } @@ -92,5 +94,5 @@ auto correlation_coefficient(Container const & u, Container const & v) return rho; } -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/centered_continued_fraction.hpp b/include/boost/math/tools/centered_continued_fraction.hpp index 87e76b51b3..5e27eacc24 100644 --- a/include/boost/math/tools/centered_continued_fraction.hpp +++ b/include/boost/math/tools/centered_continued_fraction.hpp @@ -6,6 +6,9 @@ #ifndef BOOST_MATH_TOOLS_CENTERED_CONTINUED_FRACTION_HPP #define BOOST_MATH_TOOLS_CENTERED_CONTINUED_FRACTION_HPP +#include + +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -16,6 +19,7 @@ #include #include #include +#endif #include #ifndef BOOST_MATH_STANDALONE @@ -29,9 +33,9 @@ #include #endif -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { -template +BOOST_MATH_EXPORT template class centered_continued_fraction { public: centered_continued_fraction(Real x) : x_{x} { @@ -87,11 +91,11 @@ class centered_continued_fraction { } b_.shrink_to_fit(); - for (size_t i = 1; i < b_.size(); ++i) + for (size_t k = 1; k < b_.size(); ++k) { - if (b_[i] == 0) { + if (b_[k] == 0) { std::ostringstream oss; - oss << "Found a zero partial denominator: b[" << i << "] = " << b_[i] << "." + oss << "Found a zero partial denominator: b[" << k << "] = " << b_[k] << "." #ifndef BOOST_MATH_STANDALONE << " This means the integer type '" << boost::core::demangle(typeid(Z).name()) #else @@ -142,7 +146,7 @@ class centered_continued_fraction { }; -template +BOOST_MATH_EXPORT template std::ostream& operator<<(std::ostream& out, centered_continued_fraction& scf) { constexpr const int p = std::numeric_limits::max_digits10; if constexpr (p == 2147483647) @@ -169,5 +173,5 @@ std::ostream& operator<<(std::ostream& out, centered_continued_fraction +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { // Algorithm 1 of https://people.mpim-bonn.mpg.de/zagier/files/exp-math-9/fulltext.pdf // Convergence Acceleration of Alternating Series: Henri Cohen, Fernando Rodriguez Villegas, and Don Zagier -template +BOOST_MATH_EXPORT template auto cohen_acceleration(G& generator, std::int64_t n = -1) { using Real = decltype(generator()); @@ -47,5 +51,5 @@ auto cohen_acceleration(G& generator, std::int64_t n = -1) return s/d; } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/color_maps.hpp b/include/boost/math/tools/color_maps.hpp index e3cc8b9b09..e156361434 100644 --- a/include/boost/math/tools/color_maps.hpp +++ b/include/boost/math/tools/color_maps.hpp @@ -6,25 +6,32 @@ #ifndef BOOST_MATH_COLOR_MAPS_HPP #define BOOST_MATH_COLOR_MAPS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include // for std::clamp #include // for table data #include // for std::floor #include // fixed width integer types +#endif #include -#if __has_include("lodepng.h") - +// write_png uses lodepng (https://github.com/lvandeve/lodepng) only on request, so that a program which merely has lodepng.h +// on its include path still links: define BOOST_MATH_USE_LODEPNG, or include lodepng.h before this header, and link lodepng.cpp. +#if defined(BOOST_MATH_USE_LODEPNG) && !defined(LODEPNG_H) #include "lodepng.h" +#endif +#ifdef LODEPNG_H +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { // In lodepng, the vector is expected to be row major, with the top row // specified first. Note that this is a bit confusing sometimes as it's more // natural to let y increase moving *up*. -unsigned write_png(const std::string &filename, +inline unsigned write_png(const std::string &filename, const std::vector &img, std::size_t width, std::size_t height) { unsigned error = lodepng::encode(filename, img, width, height, @@ -35,16 +42,16 @@ unsigned write_png(const std::string &filename, return error; } -} // Namespace boost::math::tools -#endif // __has_include("lodepng.h") +} BOOST_MATH_NAMESPACE_END // Namespace boost::math::tools +#endif // LODEPNG_H -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { // Data taken from: https://www.kennethmoreland.com/color-advice template -static constexpr std::array, 256> extended_kindlmann_data_ = {{ +BOOST_MATH_INLINE_CONSTEXPR std::array, 256> extended_kindlmann_data_ = {{ {0.0, 0.0, 0.0}, {0.01780246283347332, 0.0008750907117329381, 0.01626889466306607}, {0.03532931821571093, 0.001701802855992888, 0.03371323527689844}, @@ -304,7 +311,7 @@ static constexpr std::array, 256> extended_kindlmann_data_ = }}; template -static constexpr std::array, 256> kindlmann_data_ = {{ +BOOST_MATH_INLINE_CONSTEXPR std::array, 256> kindlmann_data_ = {{ {0.0, 0.0, 0.0}, {0.017846074066284252, 0.0009158559874893362, 0.016056295374498146}, {0.03572864786642702, 0.0017291229250328806, 0.03302143519907636}, @@ -564,7 +571,7 @@ static constexpr std::array, 256> kindlmann_data_ = {{ }}; template -static constexpr std::array, 256> inferno_data_ = {{ +BOOST_MATH_INLINE_CONSTEXPR std::array, 256> inferno_data_ = {{ {0.0014619955811715805, 0.0004659913919114934, 0.013866005775115809}, {0.0022669056023600243, 0.001269897101615975, 0.018569490325902337}, {0.003299036110031063, 0.0022490183451722313, 0.024239243465136288}, @@ -824,7 +831,7 @@ static constexpr std::array, 256> inferno_data_ = {{ }}; template -static constexpr std::array, 256> black_body_data_ = {{ +BOOST_MATH_INLINE_CONSTEXPR std::array, 256> black_body_data_ = {{ {0.0, 0.0, 0.0}, {0.013038855104993618, 0.0037537033758315535, 0.002103027943341456}, {0.02607771020998725, 0.007507406751663157, 0.004206055886683011}, @@ -1084,7 +1091,7 @@ static constexpr std::array, 256> black_body_data_ = {{ }}; template -static constexpr std::array, 256> plasma_data_ = {{ +BOOST_MATH_INLINE_CONSTEXPR std::array, 256> plasma_data_ = {{ {0.05038205347059877, 0.029801736499741757, 0.5279751010495176}, {0.06353382706361996, 0.028424851177690835, 0.5331235351456174}, {0.07535267397875561, 0.027204618108821313, 0.5380072654878371}, @@ -1344,7 +1351,7 @@ static constexpr std::array, 256> plasma_data_ = {{ }}; template -static constexpr std::array, 256> smooth_cool_warm_data_ = { +BOOST_MATH_INLINE_CONSTEXPR std::array, 256> smooth_cool_warm_data_ = { {{0.22999950386952345, 0.2989989340493756, 0.754000138575591}, {0.23451750918602265, 0.30586471825124395, 0.760211287847582}, {0.23905139222321087, 0.31271835359723077, 0.7663613706951183}, @@ -1603,7 +1610,7 @@ static constexpr std::array, 256> smooth_cool_warm_data_ = { {0.7060001359117047, 0.015991824033980695, 0.15000007192220008}}}; template -static constexpr std::array, 256> viridis_data_ = { +BOOST_MATH_INLINE_CONSTEXPR std::array, 256> viridis_data_ = { {{0.2670039853213788, 0.0048725657145795975, 0.32941506855247793}, {0.26850981914385313, 0.009602990407952114, 0.33542640725404194}, {0.2699440291511295, 0.014623657659867702, 0.34137927634304566}, @@ -1869,7 +1876,7 @@ color_map_(Real scalar, std::array, 256> const &table) { "arithmetic. If you require bytes please submit an issue or " "pull request"); - using boost::math::isnan; + using BOOST_MATH_NAMESPACE::isnan; if ((isnan)(scalar)) { @@ -1895,36 +1902,36 @@ color_map_(Real scalar, std::array, 256> const &table) { } } // namespace detail -template std::array viridis(Real x) { +BOOST_MATH_EXPORT template std::array viridis(Real x) { return detail::color_map_(x, detail::viridis_data_); } -template std::array smooth_cool_warm(Real x) { +BOOST_MATH_EXPORT template std::array smooth_cool_warm(Real x) { return detail::color_map_(x, detail::smooth_cool_warm_data_); } -template std::array plasma(Real x) { +BOOST_MATH_EXPORT template std::array plasma(Real x) { return detail::color_map_(x, detail::plasma_data_); } -template std::array black_body(Real x) { +BOOST_MATH_EXPORT template std::array black_body(Real x) { return detail::color_map_(x, detail::black_body_data_); } -template std::array inferno(Real x) { +BOOST_MATH_EXPORT template std::array inferno(Real x) { return detail::color_map_(x, detail::inferno_data_); } -template std::array kindlmann(Real x) { +BOOST_MATH_EXPORT template std::array kindlmann(Real x) { return detail::color_map_(x, detail::kindlmann_data_); } -template +BOOST_MATH_EXPORT template std::array extended_kindlmann(Real x) { return detail::color_map_(x, detail::extended_kindlmann_data_); } -template +BOOST_MATH_EXPORT template std::array to_8bit_rgba(const std::array &v) { using std::sqrt; std::array pixel {}; @@ -1938,6 +1945,6 @@ std::array to_8bit_rgba(const std::array &v) { return pixel; } -} // Namespace boost::math::tools +} BOOST_MATH_NAMESPACE_END // Namespace boost::math::tools #endif // BOOST_MATH_COLOR_MAPS_HPP diff --git a/include/boost/math/tools/compensated_arithmetic.hpp b/include/boost/math/tools/compensated_arithmetic.hpp new file mode 100644 index 0000000000..57b566cbca --- /dev/null +++ b/include/boost/math/tools/compensated_arithmetic.hpp @@ -0,0 +1,182 @@ +// (C) Copyright Nick Thompson 2026. +// 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) + +#ifndef BOOST_MATH_TOOLS_COMPENSATED_ARITHMETIC_HPP +#define BOOST_MATH_TOOLS_COMPENSATED_ARITHMETIC_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include + +#if !defined(BOOST_MATH_BUILD_MODULE) && !defined(BOOST_MATH_HAS_NVRTC) +#include +#endif + +// +// Reassociation (-ffast-math, /fp:fast) simplifies every error term below to zero, so forbid it here. GCC won't +// inline these into fast-math callers, so only pin it there when it's needed. Clang has the pragma from 12 +// (Apple clang 13). +// +#if defined(__clang__) && (__clang_major__ >= (defined(__apple_build_version__) ? 13 : 12)) +#define BOOST_MATH_COMPENSATED_ARITHMETIC_CLANG_FP +#endif +#if defined(BOOST_MATH_COMPENSATED_ARITHMETIC_CLANG_FP) +#pragma float_control(push) +#pragma clang fp reassociate(off) +#elif defined(__GNUC__) && defined(__ASSOCIATIVE_MATH__) +#pragma GCC push_options +#pragma GCC optimize("no-associative-math") +#elif defined(_MSC_VER) && !defined(__clang__) && defined(_M_FP_FAST) +#pragma float_control(precise, on, push) +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace detail { + +#ifndef BOOST_MATH_HAS_NVRTC + +namespace two_product_fma { +using std::fma; + +// result = fma(a, b, c) where the type has an fma, found by argument-dependent lookup for the +// non-built-in types. Returns false, leaving result alone, where there is none. +template +inline auto evaluate(const T& a, const T& b, const T& c, T& result, int) -> decltype(static_cast(fma(a, b, c)), bool()) +{ + result = fma(a, b, c); + return true; +} +template +inline bool evaluate(const T&, const T&, const T&, T&, long) +{ + return false; +} +} // namespace two_product_fma + +// +// Splits a product into its rounded value and its rounding error: p + e = a b exactly. A fused fma gives e +// directly, but having an fma is no guarantee of one: some C libraries (newlib, hence Cygwin) and the +// Boost.Multiprecision backends without a native one (cpp_bin_float) evaluate it as a * b + c with two +// roundings, which would make every e zero. So probe once per type: (1 + eps)^2 = 1 + 2 eps + eps^2, and only +// a fused fma(x, x, -(1 + 2 eps)) returns the last term. Otherwise split the factors in half (Veltkamp) so that +// the partial products are exact (Dekker). +// The rounded product comes from fma(a, b, 0), which the compiler can't contract into a later addition. +// +template +class two_product +{ +public: + two_product() : splitter(0) + { + BOOST_MATH_STD_USING + if (!is_fused()) + splitter = ldexp(T(1), (tools::digits() + 1) / 2) + 1; + } + void operator()(const T& a, const T& b, T& p, T& e) const + { + if (is_fused()) + two_product_fma::evaluate(a, b, T(0), p, 0); + else + p = a * b; + e = error(a, b, p); + } + // The rounding error of ab = fl(a b): a b = ab + error(a, b, ab) exactly. + T error(const T& a, const T& b, const T& ab) const + { + if (is_fused()) + { + T e; + two_product_fma::evaluate(a, b, T(-ab), e, 0); + return e; + } + T ah, al, bh, bl; + split(a, ah, al); + split(b, bh, bl); + return (((ah * bh - ab) + ah * bl) + al * bh) + al * bl; + } +private: + void split(const T& t, T& hi, T& lo) const + { + T g = splitter * t; + hi = g - (g - t); + lo = t - hi; + } + static bool is_fused() + { + static const bool result = [] + { + // From a volatile, so that the compiler can't fold the probe at compile time: + volatile int volatile_one = 1; + T one = static_cast(volatile_one); + T eps = tools::epsilon(); + T x = one + eps; + T eps_squared = 0; + return two_product_fma::evaluate(x, x, T(-(one + 2 * eps)), eps_squared, 0) && (eps_squared != 0); + }(); + return result; + } + T splitter; +}; + +// +// a b - c d without the cancellation: with p1 + e1 = a b and p2 + e2 = c d exactly, p1 - p2 is exact where they +// cancel (Sterbenz's lemma). Measured near cancellation it was correctly rounded, where Kahan's +// fma(a, b, -p2) - e2 is out by up to 1.5 ulps. +// +template +inline T difference_of_products(const T& a, const T& b, const T& c, const T& d) +{ + two_product product; + T p1, e1, p2, e2; + product(a, b, p1, e1); + product(c, d, p2, e2); + return (p1 - p2) + (e1 - e2); +} + +#endif // BOOST_MATH_HAS_NVRTC + +// +// The exact sum a + b is s + (return value), where s = fl(a + b): +// +template +BOOST_MATH_GPU_ENABLED inline T two_sum_error(T a, T b, T s) +{ + T bb = s - a; + return (a - (s - bb)) + (b - bb); +} + +// +// Neumaier's compensated sum: sum + comp carries the total to about one rounding, however many terms are added. +// +template +struct compensated_sum +{ + T sum; + T comp; + BOOST_MATH_GPU_ENABLED explicit compensated_sum(T s0 = 0) : sum(s0), comp(0) {} + BOOST_MATH_GPU_ENABLED void add(T x) + { + BOOST_MATH_STD_USING + T t = sum + x; + comp += (fabs(sum) >= fabs(x)) ? T((sum - t) + x) : T((x - t) + sum); + sum = t; + } + BOOST_MATH_GPU_ENABLED T value() const { return sum + comp; } +}; + +} BOOST_MATH_NAMESPACE_END // namespace detail + +#if defined(BOOST_MATH_COMPENSATED_ARITHMETIC_CLANG_FP) +#undef BOOST_MATH_COMPENSATED_ARITHMETIC_CLANG_FP +#pragma float_control(pop) +#elif defined(__GNUC__) && defined(__ASSOCIATIVE_MATH__) +#pragma GCC pop_options +#elif defined(_MSC_VER) && !defined(__clang__) && defined(_M_FP_FAST) +#pragma float_control(pop) +#endif + +#endif // BOOST_MATH_TOOLS_COMPENSATED_ARITHMETIC_HPP diff --git a/include/boost/math/tools/complex.hpp b/include/boost/math/tools/complex.hpp index ec51440116..fe273db691 100644 --- a/include/boost/math/tools/complex.hpp +++ b/include/boost/math/tools/complex.hpp @@ -18,33 +18,30 @@ #include #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN template using complex = cuda::std::complex; -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN template using complex = std::complex; -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { @@ -110,6 +107,6 @@ namespace boost { }; -} } } +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_COMPLEX_HPP diff --git a/include/boost/math/tools/condition_numbers.hpp b/include/boost/math/tools/condition_numbers.hpp index c285b479fb..2bc014d199 100644 --- a/include/boost/math/tools/condition_numbers.hpp +++ b/include/boost/math/tools/condition_numbers.hpp @@ -5,14 +5,16 @@ #ifndef BOOST_MATH_TOOLS_CONDITION_NUMBERS_HPP #define BOOST_MATH_TOOLS_CONDITION_NUMBERS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include -namespace boost { namespace math { namespace tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { -template +BOOST_MATH_EXPORT template class summation_condition_number { public: summation_condition_number(Real const x = 0) @@ -80,13 +82,13 @@ class summation_condition_number { Real m_c; }; -template +BOOST_MATH_EXPORT template Real evaluation_condition_number(F const & f, Real const & x) { using std::abs; using std::isnan; using std::sqrt; - using boost::math::differentiation::finite_difference_derivative; + using BOOST_MATH_NAMESPACE::differentiation::finite_difference_derivative; Real fx = f(x); if (isnan(fx)) @@ -94,7 +96,8 @@ Real evaluation_condition_number(F const & f, Real const & x) return std::numeric_limits::quiet_NaN(); } bool caught_exception = false; - Real fp; + // Initialized because it is read below even when the derivative threw: + Real fp = std::numeric_limits::quiet_NaN(); #ifndef BOOST_MATH_NO_EXCEPTIONS try { @@ -116,7 +119,7 @@ Real evaluation_condition_number(F const & f, Real const & x) // Check if a left derivative exists: const Real eps = (std::numeric_limits::epsilon)(); Real h = - 2 * sqrt(eps); - h = boost::math::differentiation::detail::make_xph_representable(x, h); + h = BOOST_MATH_NAMESPACE::differentiation::detail::make_xph_representable(x, h); Real yh = f(x + h); Real y0 = f(x); Real diff = yh - y0; @@ -140,5 +143,5 @@ Real evaluation_condition_number(F const & f, Real const & x) return abs(x*fp/fx); } -}}} // Namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/config.hpp b/include/boost/math/tools/config.hpp index 40346c9b0f..845f20dc4c 100644 --- a/include/boost/math/tools/config.hpp +++ b/include/boost/math/tools/config.hpp @@ -11,6 +11,102 @@ #pragma once #endif +// Configurable top level namespace (https://github.com/boostorg/math/issues/769). +// Define BOOST_MATH_NAMESPACE_COMPONENTS as a comma separated list of 1 to 5 identifiers +// outermost first, e.g. "my_lib, math" places the library in ::my_lib::math. +// Without C++17 nested namespaces we needed some heroics to make this work +#if defined(BOOST_MATH_NAMESPACE) || defined(BOOST_MATH_NAMESPACE_LEVELS) || defined(BOOST_MATH_NAMESPACE_BEGIN) || defined(BOOST_MATH_NAMESPACE_END) || defined(BOOST_MATH_DETAIL_NAMESPACE) || defined(BOOST_MATH_DETAIL_NAMESPACE_BEGIN) || defined(BOOST_MATH_DETAIL_NAMESPACE_END) +# error "Configure the namespace with BOOST_MATH_NAMESPACE_COMPONENTS (e.g. my_lib, math); the other BOOST_MATH_NAMESPACE macros are derived from it" +#endif + +#ifndef BOOST_MATH_NAMESPACE_COMPONENTS +# define BOOST_MATH_NAMESPACE_COMPONENTS boost, math +#endif + +// The extra expansion makes MSVC's traditional preprocessor split the components into separate arguments +#define BOOST_MATH_DETAIL_NS_EXPAND(x) x +#define BOOST_MATH_DETAIL_NS_COUNT_I(a1, a2, a3, a4, a5, a6, n, ...) n +#define BOOST_MATH_DETAIL_NS_COUNT(...) BOOST_MATH_DETAIL_NS_EXPAND(BOOST_MATH_DETAIL_NS_COUNT_I(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)) +#define BOOST_MATH_DETAIL_NS_APPLY(macro, args) BOOST_MATH_DETAIL_NS_EXPAND(macro args) + +#if BOOST_MATH_DETAIL_NS_COUNT(BOOST_MATH_NAMESPACE_COMPONENTS) == 1 +# define BOOST_MATH_NAMESPACE_LEVELS 1 +# define BOOST_MATH_DETAIL_NS_OPEN(a1) namespace a1 { +# define BOOST_MATH_DETAIL_NS_QUALIFY(a1) a1 +# define BOOST_MATH_DETAIL_NS_OPEN_SIBLING(a1) namespace a1##_detail { +# define BOOST_MATH_DETAIL_NS_QUALIFY_SIBLING(a1) a1##_detail +# define BOOST_MATH_NAMESPACE_END } +#elif BOOST_MATH_DETAIL_NS_COUNT(BOOST_MATH_NAMESPACE_COMPONENTS) == 2 +# define BOOST_MATH_NAMESPACE_LEVELS 2 +# define BOOST_MATH_DETAIL_NS_OPEN(a1, a2) namespace a1 { namespace a2 { +# define BOOST_MATH_DETAIL_NS_QUALIFY(a1, a2) a1::a2 +# define BOOST_MATH_DETAIL_NS_OPEN_SIBLING(a1, a2) namespace a1 { namespace a2##_detail { +# define BOOST_MATH_DETAIL_NS_QUALIFY_SIBLING(a1, a2) a1::a2##_detail +# define BOOST_MATH_NAMESPACE_END }} +#elif BOOST_MATH_DETAIL_NS_COUNT(BOOST_MATH_NAMESPACE_COMPONENTS) == 3 +# define BOOST_MATH_NAMESPACE_LEVELS 3 +# define BOOST_MATH_DETAIL_NS_OPEN(a1, a2, a3) namespace a1 { namespace a2 { namespace a3 { +# define BOOST_MATH_DETAIL_NS_QUALIFY(a1, a2, a3) a1::a2::a3 +# define BOOST_MATH_DETAIL_NS_OPEN_SIBLING(a1, a2, a3) namespace a1 { namespace a2 { namespace a3##_detail { +# define BOOST_MATH_DETAIL_NS_QUALIFY_SIBLING(a1, a2, a3) a1::a2::a3##_detail +# define BOOST_MATH_NAMESPACE_END }}} +#elif BOOST_MATH_DETAIL_NS_COUNT(BOOST_MATH_NAMESPACE_COMPONENTS) == 4 +# define BOOST_MATH_NAMESPACE_LEVELS 4 +# define BOOST_MATH_DETAIL_NS_OPEN(a1, a2, a3, a4) namespace a1 { namespace a2 { namespace a3 { namespace a4 { +# define BOOST_MATH_DETAIL_NS_QUALIFY(a1, a2, a3, a4) a1::a2::a3::a4 +# define BOOST_MATH_DETAIL_NS_OPEN_SIBLING(a1, a2, a3, a4) namespace a1 { namespace a2 { namespace a3 { namespace a4##_detail { +# define BOOST_MATH_DETAIL_NS_QUALIFY_SIBLING(a1, a2, a3, a4) a1::a2::a3::a4##_detail +# define BOOST_MATH_NAMESPACE_END }}}} +#elif BOOST_MATH_DETAIL_NS_COUNT(BOOST_MATH_NAMESPACE_COMPONENTS) == 5 +# define BOOST_MATH_NAMESPACE_LEVELS 5 +# define BOOST_MATH_DETAIL_NS_OPEN(a1, a2, a3, a4, a5) namespace a1 { namespace a2 { namespace a3 { namespace a4 { namespace a5 { +# define BOOST_MATH_DETAIL_NS_QUALIFY(a1, a2, a3, a4, a5) a1::a2::a3::a4::a5 +# define BOOST_MATH_DETAIL_NS_OPEN_SIBLING(a1, a2, a3, a4, a5) namespace a1 { namespace a2 { namespace a3 { namespace a4 { namespace a5##_detail { +# define BOOST_MATH_DETAIL_NS_QUALIFY_SIBLING(a1, a2, a3, a4, a5) a1::a2::a3::a4::a5##_detail +# define BOOST_MATH_NAMESPACE_END }}}}} +#else +# error "BOOST_MATH_NAMESPACE_COMPONENTS must contain between 1 and 5 identifiers, please file a bug report at https://github.com/boostorg/math/ if you need more" +#endif + +#define BOOST_MATH_NAMESPACE_BEGIN BOOST_MATH_DETAIL_NS_APPLY(BOOST_MATH_DETAIL_NS_OPEN, (BOOST_MATH_NAMESPACE_COMPONENTS)) +#define BOOST_MATH_NAMESPACE BOOST_MATH_DETAIL_NS_APPLY(BOOST_MATH_DETAIL_NS_QUALIFY, (BOOST_MATH_NAMESPACE_COMPONENTS)) + +// Sibling of the library namespace with "_detail" appended to the innermost component +// (::boost::math_detail by default) for helpers that must not be enclosed by the library namespace. +#define BOOST_MATH_DETAIL_NAMESPACE_BEGIN BOOST_MATH_DETAIL_NS_APPLY(BOOST_MATH_DETAIL_NS_OPEN_SIBLING, (BOOST_MATH_NAMESPACE_COMPONENTS)) +#define BOOST_MATH_DETAIL_NAMESPACE_END BOOST_MATH_NAMESPACE_END +#define BOOST_MATH_DETAIL_NAMESPACE BOOST_MATH_DETAIL_NS_APPLY(BOOST_MATH_DETAIL_NS_QUALIFY_SIBLING, (BOOST_MATH_NAMESPACE_COMPONENTS)) + +// C++20 named module support. +// BOOST_MATH_BUILD_MODULE is defined when building or consuming the boost.math +// module (module/math.cppm and the module test harness). BOOST_MATH_EXPORT marks +// every public entity and expands to nothing in ordinary header builds. +// BOOST_MATH_TEST_EXPORT additionally exports detail entities exercised by the +// module test suite, and only when the module is built with +// BOOST_MATH_EXPORT_TESTING. BOOST_MATH_INTERFACE_UNIT is defined only by +// module/math.cppm itself and guards entities that a module consumer must +// receive from the import rather than redeclare. +#ifdef BOOST_MATH_BUILD_MODULE + +#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606L) +# error "Building the boost.math module requires inline variable support (C++17 or later)" +#endif + +#define BOOST_MATH_EXPORT export + +#ifdef BOOST_MATH_EXPORT_TESTING +# define BOOST_MATH_TEST_EXPORT export +#else +# define BOOST_MATH_TEST_EXPORT +#endif + +#else + +#define BOOST_MATH_EXPORT +#define BOOST_MATH_TEST_EXPORT + +#endif + #if !(defined(__CUDACC_RTC__) && defined(BOOST_MATH_ENABLE_NVRTC)) #include @@ -84,7 +180,7 @@ #else // Things from boost/config that are required, and easy to replicate -#if __has_include() +#if !defined(BOOST_MATH_BUILD_MODULE) && __has_include() #include #endif @@ -151,8 +247,13 @@ // // Make sure we have some std lib headers included so we can detect __GXX_RTTI: // -# include // for min and max -# include + // A module build receives these through import std; the module unit stages what + // its global module fragment needs. Textual inclusion after an import trips a + // clang concept-merge bug, so skip it here. +# ifndef BOOST_MATH_BUILD_MODULE +# include // for min and max +# include +# endif # ifndef __GXX_RTTI # ifndef BOOST_MATH_NO_TYPEID # define BOOST_MATH_NO_TYPEID @@ -204,7 +305,7 @@ // C++23 #if __cplusplus > 202002L || (defined(_MSVC_LANG) &&_MSVC_LANG > 202002L) -# if defined(__GNUC__) && __GNUC__ >= 13 +# if !defined(BOOST_MATH_BUILD_MODULE) && defined(__GNUC__) && __GNUC__ >= 13 // libstdc++3 only defines to/from_chars for std::float128_t when one of these defines are set // otherwise we're right out of luck... # if defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) || defined(_GLIBCXX_HAVE_FLOAT128_MATH) @@ -216,11 +317,13 @@ # endif #endif +#ifndef BOOST_MATH_BUILD_MODULE #include // for min and max #include #include #include #include +#endif #include @@ -327,18 +430,18 @@ #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x590) -namespace boost { namespace math { namespace tools { namespace detail { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { template struct type {}; template struct non_type {}; -}}}} // Namespace boost, math tools, detail +}} BOOST_MATH_NAMESPACE_END // Namespace boost, math tools, detail -# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t) boost::math::tools::detail::type* = 0 -# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t) boost::math::tools::detail::type* -# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v) boost::math::tools::detail::non_type* = 0 -# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) boost::math::tools::detail::non_type* +# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t) BOOST_MATH_NAMESPACE::tools::detail::type* = 0 +# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t) BOOST_MATH_NAMESPACE::tools::detail::type* +# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v) BOOST_MATH_NAMESPACE::tools::detail::non_type* = 0 +# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) BOOST_MATH_NAMESPACE::tools::detail::non_type* # define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(t) \ , BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t) @@ -438,7 +541,9 @@ struct non_type {}; // // noexcept support: // +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #define BOOST_MATH_NOEXCEPT(T) noexcept(std::is_floating_point::value) #define BOOST_MATH_IS_FLOAT(T) (std::is_floating_point::value) @@ -538,7 +643,8 @@ struct non_type {}; #define BOOST_MATH_STD_USING BOOST_MATH_STD_USING_CORE -namespace boost{ namespace math{ +#if !defined(BOOST_MATH_BUILD_MODULE) || defined(BOOST_MATH_INTERFACE_UNIT) +BOOST_MATH_NAMESPACE_BEGIN namespace tools { @@ -571,7 +677,8 @@ struct is_integer_for_rounding } -}} // namespace boost namespace math +BOOST_MATH_NAMESPACE_END +#endif #ifdef __GLIBC_PREREQ # if __GLIBC_PREREQ(2,14) @@ -587,11 +694,13 @@ struct is_integer_for_rounding // Much more information in this message thread: https://groups.google.com/forum/#!topic/boost-list/ZT99wtIFlb4 // +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif # ifdef FE_ALL_EXCEPT -namespace boost{ namespace math{ +BOOST_MATH_NAMESPACE_BEGIN namespace detail { struct fpu_guard @@ -610,9 +719,9 @@ namespace boost{ namespace math{ }; } // namespace detail - }} // namespaces + BOOST_MATH_NAMESPACE_END -# define BOOST_FPU_EXCEPTION_GUARD boost::math::detail::fpu_guard local_guard_object; +# define BOOST_FPU_EXCEPTION_GUARD BOOST_MATH_NAMESPACE::detail::fpu_guard local_guard_object; # define BOOST_MATH_INSTRUMENT_FPU do{ fexcept_t cpu_flags; fegetexceptflag(&cpu_flags, FE_ALL_EXCEPT); BOOST_MATH_INSTRUMENT_VARIABLE(cpu_flags); } while(0); # else @@ -627,7 +736,7 @@ namespace boost{ namespace math{ # define BOOST_MATH_INSTRUMENT_FPU #endif -#ifdef BOOST_MATH_INSTRUMENT +#if defined(BOOST_MATH_INSTRUMENT) && !defined(BOOST_MATH_BUILD_MODULE) # include # include @@ -756,6 +865,13 @@ BOOST_MATH_GPU_ENABLED constexpr T gpu_safe_max(const T& a, const T& b) { return #endif +// Native 128-bit integer support (GCC, Clang, Intel, nvcc with a GCC host). +// Boost.Config's BOOST_HAS_INT128 is unavailable in standalone mode, so test the +// compiler macro directly. Define BOOST_MATH_NO_INT128 to force the portable paths. +#if defined(__SIZEOF_INT128__) && !defined(BOOST_MATH_NO_INT128) +# define BOOST_MATH_HAS_INT128 +#endif + // Static variables are not allowed with CUDA or C++20 modules // See if we can inline them instead @@ -801,7 +917,7 @@ BOOST_MATH_GPU_ENABLED constexpr T gpu_safe_max(const T& a, const T& b) { return #define BOOST_MATH_STATIC static #define BOOST_MATH_STATIC_LOCAL_VARIABLE -#define BOOST_MATH_NOEXCEPT(T) noexcept(boost::math::is_floating_point_v) +#define BOOST_MATH_NOEXCEPT(T) noexcept(BOOST_MATH_NAMESPACE::is_floating_point_v) #define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T) #define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) #define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T) @@ -809,7 +925,7 @@ BOOST_MATH_GPU_ENABLED constexpr T gpu_safe_max(const T& a, const T& b) { return #define BOOST_MATH_FORCEINLINE __forceinline__ #define BOOST_MATH_STD_USING #define BOOST_MATH_IF_CONSTEXPR if -#define BOOST_MATH_IS_FLOAT(T) (boost::math::is_floating_point::value) +#define BOOST_MATH_IS_FLOAT(T) (BOOST_MATH_NAMESPACE::is_floating_point::value) #define BOOST_MATH_CONSTEXPR_TABLE_FUNCTION constexpr #define BOOST_MATH_NO_EXCEPTIONS #define BOOST_MATH_PREVENT_MACRO_SUBSTITUTION diff --git a/include/boost/math/tools/convert_from_string.hpp b/include/boost/math/tools/convert_from_string.hpp index 3b7895cdf6..45d958dffd 100644 --- a/include/boost/math/tools/convert_from_string.hpp +++ b/include/boost/math/tools/convert_from_string.hpp @@ -12,7 +12,9 @@ #endif #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif #ifndef BOOST_MATH_STANDALONE #if defined(_MSC_VER) || defined(__GNUC__) @@ -28,7 +30,7 @@ #endif -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ template struct convert_from_string_result @@ -71,15 +73,14 @@ namespace boost{ namespace math{ namespace tools{ { return p; } - template + BOOST_MATH_EXPORT template constexpr typename convert_from_string_result::type convert_from_string(const char* p) noexcept((std::is_constructible::value)) { return convert_from_string(p, std::is_constructible()); } } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_CONVERT_FROM_STRING_INCLUDED diff --git a/include/boost/math/tools/cstdint.hpp b/include/boost/math/tools/cstdint.hpp index ce2c913b5c..5ee1de9ecc 100644 --- a/include/boost/math/tools/cstdint.hpp +++ b/include/boost/math/tools/cstdint.hpp @@ -13,95 +13,94 @@ #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -using cuda::std::int8_t; -using cuda::std::int16_t; -using cuda::std::int32_t; -using cuda::std::int64_t; +BOOST_MATH_EXPORT using cuda::std::int8_t; +BOOST_MATH_EXPORT using cuda::std::int16_t; +BOOST_MATH_EXPORT using cuda::std::int32_t; +BOOST_MATH_EXPORT using cuda::std::int64_t; -using cuda::std::int_fast8_t; -using cuda::std::int_fast16_t; -using cuda::std::int_fast32_t; -using cuda::std::int_fast64_t; +BOOST_MATH_EXPORT using cuda::std::int_fast8_t; +BOOST_MATH_EXPORT using cuda::std::int_fast16_t; +BOOST_MATH_EXPORT using cuda::std::int_fast32_t; +BOOST_MATH_EXPORT using cuda::std::int_fast64_t; -using cuda::std::int_least8_t; -using cuda::std::int_least16_t; -using cuda::std::int_least32_t; -using cuda::std::int_least64_t; +BOOST_MATH_EXPORT using cuda::std::int_least8_t; +BOOST_MATH_EXPORT using cuda::std::int_least16_t; +BOOST_MATH_EXPORT using cuda::std::int_least32_t; +BOOST_MATH_EXPORT using cuda::std::int_least64_t; -using cuda::std::intmax_t; -using cuda::std::intptr_t; +BOOST_MATH_EXPORT using cuda::std::intmax_t; +BOOST_MATH_EXPORT using cuda::std::intptr_t; -using cuda::std::uint8_t; -using cuda::std::uint16_t; -using cuda::std::uint32_t; -using cuda::std::uint64_t; +BOOST_MATH_EXPORT using cuda::std::uint8_t; +BOOST_MATH_EXPORT using cuda::std::uint16_t; +BOOST_MATH_EXPORT using cuda::std::uint32_t; +BOOST_MATH_EXPORT using cuda::std::uint64_t; -using cuda::std::uint_fast8_t; -using cuda::std::uint_fast16_t; -using cuda::std::uint_fast32_t; -using cuda::std::uint_fast64_t; +BOOST_MATH_EXPORT using cuda::std::uint_fast8_t; +BOOST_MATH_EXPORT using cuda::std::uint_fast16_t; +BOOST_MATH_EXPORT using cuda::std::uint_fast32_t; +BOOST_MATH_EXPORT using cuda::std::uint_fast64_t; -using cuda::std::uint_least8_t; -using cuda::std::uint_least16_t; -using cuda::std::uint_least32_t; -using cuda::std::uint_least64_t; +BOOST_MATH_EXPORT using cuda::std::uint_least8_t; +BOOST_MATH_EXPORT using cuda::std::uint_least16_t; +BOOST_MATH_EXPORT using cuda::std::uint_least32_t; +BOOST_MATH_EXPORT using cuda::std::uint_least64_t; -using cuda::std::uintmax_t; -using cuda::std::uintptr_t; +BOOST_MATH_EXPORT using cuda::std::uintmax_t; +BOOST_MATH_EXPORT using cuda::std::uintptr_t; using size_t = unsigned long; #else +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -using std::int8_t; -using std::int16_t; -using std::int32_t; -using std::int64_t; +BOOST_MATH_EXPORT using std::int8_t; +BOOST_MATH_EXPORT using std::int16_t; +BOOST_MATH_EXPORT using std::int32_t; +BOOST_MATH_EXPORT using std::int64_t; -using std::int_fast8_t; -using std::int_fast16_t; -using std::int_fast32_t; -using std::int_fast64_t; +BOOST_MATH_EXPORT using std::int_fast8_t; +BOOST_MATH_EXPORT using std::int_fast16_t; +BOOST_MATH_EXPORT using std::int_fast32_t; +BOOST_MATH_EXPORT using std::int_fast64_t; -using std::int_least8_t; -using std::int_least16_t; -using std::int_least32_t; -using std::int_least64_t; +BOOST_MATH_EXPORT using std::int_least8_t; +BOOST_MATH_EXPORT using std::int_least16_t; +BOOST_MATH_EXPORT using std::int_least32_t; +BOOST_MATH_EXPORT using std::int_least64_t; -using std::intmax_t; -using std::intptr_t; +BOOST_MATH_EXPORT using std::intmax_t; +BOOST_MATH_EXPORT using std::intptr_t; -using std::uint8_t; -using std::uint16_t; -using std::uint32_t; -using std::uint64_t; +BOOST_MATH_EXPORT using std::uint8_t; +BOOST_MATH_EXPORT using std::uint16_t; +BOOST_MATH_EXPORT using std::uint32_t; +BOOST_MATH_EXPORT using std::uint64_t; -using std::uint_fast8_t; -using std::uint_fast16_t; -using std::uint_fast32_t; -using std::uint_fast64_t; +BOOST_MATH_EXPORT using std::uint_fast8_t; +BOOST_MATH_EXPORT using std::uint_fast16_t; +BOOST_MATH_EXPORT using std::uint_fast32_t; +BOOST_MATH_EXPORT using std::uint_fast64_t; -using std::uint_least8_t; -using std::uint_least16_t; -using std::uint_least32_t; -using std::uint_least64_t; +BOOST_MATH_EXPORT using std::uint_least8_t; +BOOST_MATH_EXPORT using std::uint_least16_t; +BOOST_MATH_EXPORT using std::uint_least32_t; +BOOST_MATH_EXPORT using std::uint_least64_t; -using std::uintmax_t; -using std::uintptr_t; +BOOST_MATH_EXPORT using std::uintmax_t; +BOOST_MATH_EXPORT using std::uintptr_t; -using std::size_t; +BOOST_MATH_EXPORT using std::size_t; #endif -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_CSTDINT diff --git a/include/boost/math/tools/cubic_roots.hpp b/include/boost/math/tools/cubic_roots.hpp index 1097ad5ce4..36c5ed012a 100644 --- a/include/boost/math/tools/cubic_roots.hpp +++ b/include/boost/math/tools/cubic_roots.hpp @@ -4,13 +4,15 @@ // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_TOOLS_CUBIC_ROOTS_HPP #define BOOST_MATH_TOOLS_CUBIC_ROOTS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include #include -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { @@ -20,11 +22,11 @@ namespace detail { template bool roots_less(const Real& lhs, const Real& rhs) { - if ((boost::math::isnan)(lhs)) + if ((BOOST_MATH_NAMESPACE::isnan)(lhs)) { return false; } - if ((boost::math::isnan)(rhs)) + if ((BOOST_MATH_NAMESPACE::isnan)(rhs)) { return true; } @@ -39,7 +41,7 @@ bool roots_less(const Real& lhs, const Real& rhs) // algorithm apparently exists: Algorithm 954: An Accurate and Efficient Cubic // and Quartic Equation Solver for Physical Applications However, I don't have // access to that paper! -template +BOOST_MATH_EXPORT template std::array cubic_roots(Real a, Real b, Real c, Real d) { using std::abs; using std::acos; @@ -145,7 +147,7 @@ std::array cubic_roots(Real a, Real b, Real c, Real d) { // eps*|rp'(r)| (second element) for a root. Recall that for a numerically // computed root r satisfying r = r_0(1+eps) of a function p, |p(r)| <= // eps|rp'(r)|. -template +BOOST_MATH_EXPORT template std::array cubic_root_residual(Real a, Real b, Real c, Real d, Real root) { using std::abs; @@ -172,7 +174,7 @@ std::array cubic_root_residual(Real a, Real b, Real c, Real d, // Computes the condition number of rootfinding. This is defined in Corless, A // Graduate Introduction to Numerical Methods, Section 3.2.1. -template +BOOST_MATH_EXPORT template Real cubic_root_condition_number(Real a, Real b, Real c, Real d, Real root) { using std::abs; using std::fma; @@ -194,5 +196,5 @@ Real cubic_root_condition_number(Real a, Real b, Real c, Real d, Real root) { return numerator / abs(denominator); } -} // namespace boost::math::tools +} BOOST_MATH_NAMESPACE_END // namespace boost::math::tools #endif diff --git a/include/boost/math/tools/detail/complex_from_real.hpp b/include/boost/math/tools/detail/complex_from_real.hpp new file mode 100644 index 0000000000..60e466ca02 --- /dev/null +++ b/include/boost/math/tools/detail/complex_from_real.hpp @@ -0,0 +1,51 @@ +// Copyright Nick Thompson 2026. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_TOOLS_DETAIL_COMPLEX_FROM_REAL_HPP +#define BOOST_MATH_TOOLS_DETAIL_COMPLEX_FROM_REAL_HPP + +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +// Specialised by each Boost.Multiprecision backend; declared here so that this header does not depend on Multiprecision. +namespace boost { namespace multiprecision { +template +struct complex_result_from_scalar; +}} + +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { + +// The complex type whose real type is Real, for use with tools::fft and tools::real_fft: +// std::complex for float, double and long double, and the matching Boost.Multiprecision +// complex type otherwise (cpp_complex_50 for cpp_bin_float_50, and so on). For the latter the +// Multiprecision complex header must be included, e.g. , +// or . +template ::value> +struct complex_from_real +{ + using type = std::complex; +}; + +template +struct complex_from_real +{ + using type = typename ::boost::multiprecision::complex_result_from_scalar::type; +}; + +template +using complex_from_real_t = typename complex_from_real::type; + +// The real type of a complex type: Real for std::complex, cpp_bin_float_50 for cpp_complex_50, and so on. +template +using real_from_complex_t = typename std::decay().real())>::type; + +}} BOOST_MATH_NAMESPACE_END + +#endif diff --git a/include/boost/math/tools/detail/is_const_iterable.hpp b/include/boost/math/tools/detail/is_const_iterable.hpp index e5efc82c30..b93eb06c0c 100644 --- a/include/boost/math/tools/detail/is_const_iterable.hpp +++ b/include/boost/math/tools/detail/is_const_iterable.hpp @@ -11,10 +11,11 @@ #define BOOST_MATH_HAS_IS_CONST_ITERABLE #include +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { @@ -33,6 +34,6 @@ namespace boost { && is_detected::value > {}; -} } } } +} } BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_IS_CONST_ITERABLE_HPP diff --git a/include/boost/math/tools/detail/polynomial_horner1_10.hpp b/include/boost/math/tools/detail/polynomial_horner1_10.hpp index 04ad90b69b..f85ffda5c7 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_10.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_10.hpp @@ -9,76 +9,76 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_10_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_10_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_11.hpp b/include/boost/math/tools/detail/polynomial_horner1_11.hpp index f99ab82507..a34c4d6033 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_11.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_11.hpp @@ -9,82 +9,82 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_11_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_11_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_12.hpp b/include/boost/math/tools/detail/polynomial_horner1_12.hpp index 3006ebe51e..592cf4cfee 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_12.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_12.hpp @@ -9,88 +9,88 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_12_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_12_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_13.hpp b/include/boost/math/tools/detail/polynomial_horner1_13.hpp index 0f11189097..68a53a157b 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_13.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_13.hpp @@ -9,94 +9,94 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_13_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_13_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_14.hpp b/include/boost/math/tools/detail/polynomial_horner1_14.hpp index caba4b97ea..1cdc36258b 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_14.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_14.hpp @@ -9,100 +9,100 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_14_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_14_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_15.hpp b/include/boost/math/tools/detail/polynomial_horner1_15.hpp index c8f42ac813..7e48635db8 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_15.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_15.hpp @@ -9,106 +9,106 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_15_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_15_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_16.hpp b/include/boost/math/tools/detail/polynomial_horner1_16.hpp index 2ed591ccf5..aac2318513 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_16.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_16.hpp @@ -9,112 +9,112 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_16_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_16_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_17.hpp b/include/boost/math/tools/detail/polynomial_horner1_17.hpp index 5e9fc8cd7c..2b377a1b48 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_17.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_17.hpp @@ -9,118 +9,118 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_17_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_17_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((((a[16] * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_18.hpp b/include/boost/math/tools/detail/polynomial_horner1_18.hpp index ffb62ff049..3fe5660554 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_18.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_18.hpp @@ -9,124 +9,124 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_18_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_18_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((((a[16] * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((((((a[17] * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_19.hpp b/include/boost/math/tools/detail/polynomial_horner1_19.hpp index 56df108ac8..77001c71ab 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_19.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_19.hpp @@ -9,130 +9,130 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_19_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_19_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((((a[16] * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((((((a[17] * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((((((a[18] * x + a[17]) * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_2.hpp b/include/boost/math/tools/detail/polynomial_horner1_2.hpp index 63091ebddd..2f85ba00c9 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_2.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_2.hpp @@ -9,28 +9,28 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_2_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_2_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_20.hpp b/include/boost/math/tools/detail/polynomial_horner1_20.hpp index c16e5143ec..6ff1f54961 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_20.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_20.hpp @@ -9,136 +9,136 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_20_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_20_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((((a[16] * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((((((a[17] * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((((((((((((a[18] * x + a[17]) * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((((((((((((((a[19] * x + a[18]) * x + a[17]) * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_3.hpp b/include/boost/math/tools/detail/polynomial_horner1_3.hpp index 0aeccc1115..b75f245257 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_3.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_3.hpp @@ -9,34 +9,34 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_3_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_3_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_4.hpp b/include/boost/math/tools/detail/polynomial_horner1_4.hpp index 61058fce84..010536f02a 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_4.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_4.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_4_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_4_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_5.hpp b/include/boost/math/tools/detail/polynomial_horner1_5.hpp index 47021bc509..1e05970d38 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_5.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_5.hpp @@ -9,46 +9,46 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_5_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_5_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_6.hpp b/include/boost/math/tools/detail/polynomial_horner1_6.hpp index bfd24371d5..5db7dbe524 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_6.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_6.hpp @@ -9,52 +9,52 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_6_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_6_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_7.hpp b/include/boost/math/tools/detail/polynomial_horner1_7.hpp index 50ddca63ff..7c17cf978f 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_7.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_7.hpp @@ -9,58 +9,58 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_7_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_7_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_8.hpp b/include/boost/math/tools/detail/polynomial_horner1_8.hpp index 3be7ba4d16..80349b7ff5 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_8.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_8.hpp @@ -9,64 +9,64 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_8_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_8_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner1_9.hpp b/include/boost/math/tools/detail/polynomial_horner1_9.hpp index 4ec53c48bd..ce974a4ee5 100644 --- a/include/boost/math/tools/detail/polynomial_horner1_9.hpp +++ b/include/boost/math/tools/detail/polynomial_horner1_9.hpp @@ -9,70 +9,70 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_9_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_9_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_10.hpp b/include/boost/math/tools/detail/polynomial_horner2_10.hpp index f242d7464e..046f0b0c0a 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_10.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_10.hpp @@ -9,82 +9,82 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_10_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_10_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_11.hpp b/include/boost/math/tools/detail/polynomial_horner2_11.hpp index edf7f86c52..0f07640d62 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_11.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_11.hpp @@ -9,89 +9,89 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_11_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_11_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_12.hpp b/include/boost/math/tools/detail/polynomial_horner2_12.hpp index 969c9c4ddd..17b5344955 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_12.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_12.hpp @@ -9,96 +9,96 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_12_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_12_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_13.hpp b/include/boost/math/tools/detail/polynomial_horner2_13.hpp index ed4559d11e..56ff1ff3b9 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_13.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_13.hpp @@ -9,103 +9,103 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_13_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_13_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_14.hpp b/include/boost/math/tools/detail/polynomial_horner2_14.hpp index 4b79eb78a4..85220f719e 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_14.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_14.hpp @@ -9,110 +9,110 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_14_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_14_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_15.hpp b/include/boost/math/tools/detail/polynomial_horner2_15.hpp index 28b62eee75..f8b6c7ea46 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_15.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_15.hpp @@ -9,117 +9,117 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_15_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_15_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_16.hpp b/include/boost/math/tools/detail/polynomial_horner2_16.hpp index 6368b40548..99d68cc6c3 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_16.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_16.hpp @@ -9,124 +9,124 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_16_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_16_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((a[15] * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_17.hpp b/include/boost/math/tools/detail/polynomial_horner2_17.hpp index 551e6191cf..59bd261738 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_17.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_17.hpp @@ -9,131 +9,131 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_17_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_17_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((a[15] * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((a[16] * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((((a[15] * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_18.hpp b/include/boost/math/tools/detail/polynomial_horner2_18.hpp index 19cfdc19e1..9971d69688 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_18.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_18.hpp @@ -9,138 +9,138 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_18_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_18_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((a[15] * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((a[16] * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((((a[15] * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((((a[17] * x2 + a[15]) * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((((a[16] * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_19.hpp b/include/boost/math/tools/detail/polynomial_horner2_19.hpp index 9ea87fd93b..7d422ec49b 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_19.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_19.hpp @@ -9,145 +9,145 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_19_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_19_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((a[15] * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((a[16] * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((((a[15] * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((((a[17] * x2 + a[15]) * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((((a[16] * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((((a[18] * x2 + a[16]) * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((((((a[17] * x2 + a[15]) * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_2.hpp b/include/boost/math/tools/detail/polynomial_horner2_2.hpp index 1982a81f3f..71d4424104 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_2.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_2.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_2_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_2_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_20.hpp b/include/boost/math/tools/detail/polynomial_horner2_20.hpp index 23afe55e05..95a4f60664 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_20.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_20.hpp @@ -9,152 +9,152 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_20_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_20_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((a[9] * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((a[10] * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((a[11] * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((a[12] * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((((a[13] * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((a[15] * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((((a[14] * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((a[16] * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((((((a[15] * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((((a[17] * x2 + a[15]) * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + (((((((a[16] * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((((((((a[18] * x2 + a[16]) * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((((((((a[17] * x2 + a[15]) * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((((((((a[19] * x2 + a[17]) * x2 + a[15]) * x2 + a[13]) * x2 + a[11]) * x2 + a[9]) * x2 + a[7]) * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((((((((a[18] * x2 + a[16]) * x2 + a[14]) * x2 + a[12]) * x2 + a[10]) * x2 + a[8]) * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_3.hpp b/include/boost/math/tools/detail/polynomial_horner2_3.hpp index f9d6953b82..a9115d659b 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_3.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_3.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_3_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_3_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_4.hpp b/include/boost/math/tools/detail/polynomial_horner2_4.hpp index 8f11de5b31..07a69d8806 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_4.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_4.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_4_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_4_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_5.hpp b/include/boost/math/tools/detail/polynomial_horner2_5.hpp index eba9ee9e6d..78675676a9 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_5.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_5.hpp @@ -9,47 +9,47 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_5_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_5_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_6.hpp b/include/boost/math/tools/detail/polynomial_horner2_6.hpp index ef77c6255b..a2d0793f41 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_6.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_6.hpp @@ -9,54 +9,54 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_6_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_6_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_7.hpp b/include/boost/math/tools/detail/polynomial_horner2_7.hpp index fe8d21b95f..b24da5dc5f 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_7.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_7.hpp @@ -9,61 +9,61 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_7_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_7_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_8.hpp b/include/boost/math/tools/detail/polynomial_horner2_8.hpp index de1810a940..a383263914 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_8.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_8.hpp @@ -9,68 +9,68 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_8_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_8_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner2_9.hpp b/include/boost/math/tools/detail/polynomial_horner2_9.hpp index 5c53b73299..ba465ac78f 100644 --- a/include/boost/math/tools/detail/polynomial_horner2_9.hpp +++ b/include/boost/math/tools/detail/polynomial_horner2_9.hpp @@ -9,75 +9,75 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_9_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_9_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((a[4] * x2 + a[2]) * x2 + a[0] + (a[3] * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[5] * x2 + a[3]) * x2 + a[1]) * x + (a[4] * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast(((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + ((a[5] * x2 + a[3]) * x2 + a[1]) * x); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x + ((a[6] * x2 + a[4]) * x2 + a[2]) * x2 + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; return static_cast((((a[8] * x2 + a[6]) * x2 + a[4]) * x2 + a[2]) * x2 + a[0] + (((a[7] * x2 + a[5]) * x2 + a[3]) * x2 + a[1]) * x); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_10.hpp b/include/boost/math/tools/detail/polynomial_horner3_10.hpp index 7fb5bb4745..49556c9ce6 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_10.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_10.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_10_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_10_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_11.hpp b/include/boost/math/tools/detail/polynomial_horner3_11.hpp index 9f22820dea..e0c86a0e84 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_11.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_11.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_11_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_11_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_12.hpp b/include/boost/math/tools/detail/polynomial_horner3_12.hpp index b049613766..cddab0a62f 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_12.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_12.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_12_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_12_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_13.hpp b/include/boost/math/tools/detail/polynomial_horner3_13.hpp index f39a33cc90..f97ce27164 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_13.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_13.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_13_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_13_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -231,7 +231,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_14.hpp b/include/boost/math/tools/detail/polynomial_horner3_14.hpp index 32b9e7db29..d72f17e6bd 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_14.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_14.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_14_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_14_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -231,7 +231,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -262,7 +262,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_15.hpp b/include/boost/math/tools/detail/polynomial_horner3_15.hpp index 55325c84b9..c45e9f77e5 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_15.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_15.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_15_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_15_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -231,7 +231,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -262,7 +262,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -295,7 +295,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_16.hpp b/include/boost/math/tools/detail/polynomial_horner3_16.hpp index f71d62f50c..231961e819 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_16.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_16.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_16_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_16_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -231,7 +231,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -262,7 +262,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -295,7 +295,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -330,7 +330,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_17.hpp b/include/boost/math/tools/detail/polynomial_horner3_17.hpp index 783a34558c..719760b938 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_17.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_17.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_17_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_17_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -231,7 +231,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -262,7 +262,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -295,7 +295,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -330,7 +330,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -367,7 +367,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_18.hpp b/include/boost/math/tools/detail/polynomial_horner3_18.hpp index b10b270c41..bc8bc27f04 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_18.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_18.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_18_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_18_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -231,7 +231,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -262,7 +262,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -295,7 +295,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -330,7 +330,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -367,7 +367,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -406,7 +406,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_19.hpp b/include/boost/math/tools/detail/polynomial_horner3_19.hpp index 21147591c8..ec92c4e403 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_19.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_19.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_19_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_19_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -231,7 +231,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -262,7 +262,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -295,7 +295,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -330,7 +330,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -367,7 +367,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -406,7 +406,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -447,7 +447,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_2.hpp b/include/boost/math/tools/detail/polynomial_horner3_2.hpp index ee3e35e6ca..1db566f2b1 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_2.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_2.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_2_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_2_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_20.hpp b/include/boost/math/tools/detail/polynomial_horner3_20.hpp index 338aeb7dbc..6a8d3a3328 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_20.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_20.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_20_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_20_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -150,7 +150,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -175,7 +175,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -231,7 +231,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -262,7 +262,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -295,7 +295,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -330,7 +330,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -367,7 +367,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -406,7 +406,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -447,7 +447,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -490,7 +490,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_3.hpp b/include/boost/math/tools/detail/polynomial_horner3_3.hpp index 1eee0cfac0..02625912a9 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_3.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_3.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_3_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_3_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_4.hpp b/include/boost/math/tools/detail/polynomial_horner3_4.hpp index efa7fba485..7658af02d7 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_4.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_4.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_4_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_4_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_5.hpp b/include/boost/math/tools/detail/polynomial_horner3_5.hpp index f150e2a4a4..726624892d 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_5.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_5.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_5_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_5_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_6.hpp b/include/boost/math/tools/detail/polynomial_horner3_6.hpp index fe679e74d2..006e50cf7e 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_6.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_6.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_6_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_6_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_7.hpp b/include/boost/math/tools/detail/polynomial_horner3_7.hpp index 76f080ad9c..0c77197fd5 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_7.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_7.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_7_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_7_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_8.hpp b/include/boost/math/tools/detail/polynomial_horner3_8.hpp index 75634bdfc6..c231ade220 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_8.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_8.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_8_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_8_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/polynomial_horner3_9.hpp b/include/boost/math/tools/detail/polynomial_horner3_9.hpp index 63a40580d1..22d45611db 100644 --- a/include/boost/math/tools/detail/polynomial_horner3_9.hpp +++ b/include/boost/math/tools/detail/polynomial_horner3_9.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_POLY_EVAL_9_HPP #define BOOST_MATH_TOOLS_POLY_EVAL_9_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[1] * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[2] * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[3] * x + a[2]) * x + a[1]) * x + a[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -55,7 +55,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -70,7 +70,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -87,7 +87,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } template -BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { V x2 = x * x; V t[2]; @@ -127,7 +127,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& x } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_10.hpp b/include/boost/math/tools/detail/rational_horner1_10.hpp index e2f6c6d2fb..f7e5595372 100644 --- a/include/boost/math/tools/detail/rational_horner1_10.hpp +++ b/include/boost/math/tools/detail/rational_horner1_10.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_10_HPP #define BOOST_MATH_TOOLS_POLY_RAT_10_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_11.hpp b/include/boost/math/tools/detail/rational_horner1_11.hpp index 31d480a65a..5305d323be 100644 --- a/include/boost/math/tools/detail/rational_horner1_11.hpp +++ b/include/boost/math/tools/detail/rational_horner1_11.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_11_HPP #define BOOST_MATH_TOOLS_POLY_RAT_11_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_12.hpp b/include/boost/math/tools/detail/rational_horner1_12.hpp index c08a85b3a6..d40524fe67 100644 --- a/include/boost/math/tools/detail/rational_horner1_12.hpp +++ b/include/boost/math/tools/detail/rational_horner1_12.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_12_HPP #define BOOST_MATH_TOOLS_POLY_RAT_12_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((b[11] * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_13.hpp b/include/boost/math/tools/detail/rational_horner1_13.hpp index cc87ec2dc7..754b872518 100644 --- a/include/boost/math/tools/detail/rational_horner1_13.hpp +++ b/include/boost/math/tools/detail/rational_horner1_13.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_13_HPP #define BOOST_MATH_TOOLS_POLY_RAT_13_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((b[11] * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((b[12] * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -168,7 +168,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_14.hpp b/include/boost/math/tools/detail/rational_horner1_14.hpp index 256473710f..8cfac3f4ac 100644 --- a/include/boost/math/tools/detail/rational_horner1_14.hpp +++ b/include/boost/math/tools/detail/rational_horner1_14.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_14_HPP #define BOOST_MATH_TOOLS_POLY_RAT_14_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((b[11] * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((b[12] * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -168,7 +168,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((b[13] * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_15.hpp b/include/boost/math/tools/detail/rational_horner1_15.hpp index 2ab24814e7..e87ae611fb 100644 --- a/include/boost/math/tools/detail/rational_horner1_15.hpp +++ b/include/boost/math/tools/detail/rational_horner1_15.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_15_HPP #define BOOST_MATH_TOOLS_POLY_RAT_15_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((b[11] * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((b[12] * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -168,7 +168,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((b[13] * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((b[14] * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -192,7 +192,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_16.hpp b/include/boost/math/tools/detail/rational_horner1_16.hpp index dce0b5e9b1..41d8250ab1 100644 --- a/include/boost/math/tools/detail/rational_horner1_16.hpp +++ b/include/boost/math/tools/detail/rational_horner1_16.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_16_HPP #define BOOST_MATH_TOOLS_POLY_RAT_16_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((b[11] * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((b[12] * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -168,7 +168,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((b[13] * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((b[14] * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -192,7 +192,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((((b[15] * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -204,7 +204,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_17.hpp b/include/boost/math/tools/detail/rational_horner1_17.hpp index 8e875d6576..7380f0771b 100644 --- a/include/boost/math/tools/detail/rational_horner1_17.hpp +++ b/include/boost/math/tools/detail/rational_horner1_17.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_17_HPP #define BOOST_MATH_TOOLS_POLY_RAT_17_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((b[11] * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((b[12] * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -168,7 +168,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((b[13] * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((b[14] * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -192,7 +192,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((((b[15] * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -204,7 +204,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((((a[16] * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((((b[16] * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -216,7 +216,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_18.hpp b/include/boost/math/tools/detail/rational_horner1_18.hpp index ab67a970b0..272277e3bb 100644 --- a/include/boost/math/tools/detail/rational_horner1_18.hpp +++ b/include/boost/math/tools/detail/rational_horner1_18.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_18_HPP #define BOOST_MATH_TOOLS_POLY_RAT_18_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((b[11] * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((b[12] * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -168,7 +168,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((b[13] * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((b[14] * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -192,7 +192,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((((b[15] * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -204,7 +204,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((((a[16] * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((((b[16] * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -216,7 +216,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((((((a[17] * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((((((b[17] * x + b[16]) * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -228,7 +228,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_19.hpp b/include/boost/math/tools/detail/rational_horner1_19.hpp index dc300343a5..e87a391731 100644 --- a/include/boost/math/tools/detail/rational_horner1_19.hpp +++ b/include/boost/math/tools/detail/rational_horner1_19.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_19_HPP #define BOOST_MATH_TOOLS_POLY_RAT_19_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((b[11] * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((b[12] * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -168,7 +168,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((b[13] * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((b[14] * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -192,7 +192,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((((b[15] * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -204,7 +204,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((((a[16] * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((((b[16] * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -216,7 +216,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((((((a[17] * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((((((b[17] * x + b[16]) * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -228,7 +228,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((((((a[18] * x + a[17]) * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((((((b[18] * x + b[17]) * x + b[16]) * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -240,7 +240,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_2.hpp b/include/boost/math/tools/detail/rational_horner1_2.hpp index c6b1ef9ef9..fa943c0224 100644 --- a/include/boost/math/tools/detail/rational_horner1_2.hpp +++ b/include/boost/math/tools/detail/rational_horner1_2.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_2_HPP #define BOOST_MATH_TOOLS_POLY_RAT_2_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_20.hpp b/include/boost/math/tools/detail/rational_horner1_20.hpp index 5b8b170c15..d9062b3cdc 100644 --- a/include/boost/math/tools/detail/rational_horner1_20.hpp +++ b/include/boost/math/tools/detail/rational_horner1_20.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_20_HPP #define BOOST_MATH_TOOLS_POLY_RAT_20_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((b[9] * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -132,7 +132,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((a[10] * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((b[10] * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -144,7 +144,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((a[11] * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((b[11] * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -156,7 +156,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((a[12] * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((b[12] * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -168,7 +168,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((a[13] * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((b[13] * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((a[14] * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((b[14] * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -192,7 +192,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((((a[15] * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((((b[15] * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -204,7 +204,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((((a[16] * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((((b[16] * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -216,7 +216,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((((((a[17] * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((((((b[17] * x + b[16]) * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -228,7 +228,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((((((((((((a[18] * x + a[17]) * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((((((((((((b[18] * x + b[17]) * x + b[16]) * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -240,7 +240,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((((((((((((((a[19] * x + a[18]) * x + a[17]) * x + a[16]) * x + a[15]) * x + a[14]) * x + a[13]) * x + a[12]) * x + a[11]) * x + a[10]) * x + a[9]) * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((((((((((((((b[19] * x + b[18]) * x + b[17]) * x + b[16]) * x + b[15]) * x + b[14]) * x + b[13]) * x + b[12]) * x + b[11]) * x + b[10]) * x + b[9]) * x + b[8]) * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -252,7 +252,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_3.hpp b/include/boost/math/tools/detail/rational_horner1_3.hpp index 6933e22bf1..4f0967d96c 100644 --- a/include/boost/math/tools/detail/rational_horner1_3.hpp +++ b/include/boost/math/tools/detail/rational_horner1_3.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_3_HPP #define BOOST_MATH_TOOLS_POLY_RAT_3_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_4.hpp b/include/boost/math/tools/detail/rational_horner1_4.hpp index 49b9835778..14820821ff 100644 --- a/include/boost/math/tools/detail/rational_horner1_4.hpp +++ b/include/boost/math/tools/detail/rational_horner1_4.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_4_HPP #define BOOST_MATH_TOOLS_POLY_RAT_4_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_5.hpp b/include/boost/math/tools/detail/rational_horner1_5.hpp index 91e97ff445..397fe1910e 100644 --- a/include/boost/math/tools/detail/rational_horner1_5.hpp +++ b/include/boost/math/tools/detail/rational_horner1_5.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_5_HPP #define BOOST_MATH_TOOLS_POLY_RAT_5_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_6.hpp b/include/boost/math/tools/detail/rational_horner1_6.hpp index 876b026cde..451723d52d 100644 --- a/include/boost/math/tools/detail/rational_horner1_6.hpp +++ b/include/boost/math/tools/detail/rational_horner1_6.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_6_HPP #define BOOST_MATH_TOOLS_POLY_RAT_6_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_7.hpp b/include/boost/math/tools/detail/rational_horner1_7.hpp index bcac18293c..60e8732bcd 100644 --- a/include/boost/math/tools/detail/rational_horner1_7.hpp +++ b/include/boost/math/tools/detail/rational_horner1_7.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_7_HPP #define BOOST_MATH_TOOLS_POLY_RAT_7_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_8.hpp b/include/boost/math/tools/detail/rational_horner1_8.hpp index 55e30a53e8..b4815e1d36 100644 --- a/include/boost/math/tools/detail/rational_horner1_8.hpp +++ b/include/boost/math/tools/detail/rational_horner1_8.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_8_HPP #define BOOST_MATH_TOOLS_POLY_RAT_8_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner1_9.hpp b/include/boost/math/tools/detail/rational_horner1_9.hpp index c7087de508..b975dc2440 100644 --- a/include/boost/math/tools/detail/rational_horner1_9.hpp +++ b/include/boost/math/tools/detail/rational_horner1_9.hpp @@ -9,22 +9,22 @@ #ifndef BOOST_MATH_TOOLS_POLY_RAT_9_HPP #define BOOST_MATH_TOOLS_POLY_RAT_9_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); @@ -36,7 +36,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); @@ -60,7 +60,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((a[4] * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((b[4] * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((a[5] * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((b[5] * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((b[6] * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -96,7 +96,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast((((((((a[7] * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / (((((((b[7] * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -108,7 +108,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) return static_cast(((((((((a[8] * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]) / ((((((((b[8] * x + b[7]) * x + b[6]) * x + b[5]) * x + b[4]) * x + b[3]) * x + b[2]) * x + b[1]) * x + b[0])); @@ -120,7 +120,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_10.hpp b/include/boost/math/tools/detail/rational_horner2_10.hpp index 4d74a714d5..3029267d5b 100644 --- a/include/boost/math/tools/detail/rational_horner2_10.hpp +++ b/include/boost/math/tools/detail/rational_horner2_10.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_10_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_10_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_11.hpp b/include/boost/math/tools/detail/rational_horner2_11.hpp index 15f1cf2556..d20b48c284 100644 --- a/include/boost/math/tools/detail/rational_horner2_11.hpp +++ b/include/boost/math/tools/detail/rational_horner2_11.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_11_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_11_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_12.hpp b/include/boost/math/tools/detail/rational_horner2_12.hpp index 24e9d9e7f7..96b6b31be2 100644 --- a/include/boost/math/tools/detail/rational_horner2_12.hpp +++ b/include/boost/math/tools/detail/rational_horner2_12.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_12_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_12_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_13.hpp b/include/boost/math/tools/detail/rational_horner2_13.hpp index 495f88525d..3ee08aa1d7 100644 --- a/include/boost/math/tools/detail/rational_horner2_13.hpp +++ b/include/boost/math/tools/detail/rational_horner2_13.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_13_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_13_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -186,7 +186,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_14.hpp b/include/boost/math/tools/detail/rational_horner2_14.hpp index 273e723b6c..580e70a42a 100644 --- a/include/boost/math/tools/detail/rational_horner2_14.hpp +++ b/include/boost/math/tools/detail/rational_horner2_14.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_14_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_14_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -186,7 +186,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_15.hpp b/include/boost/math/tools/detail/rational_horner2_15.hpp index c7e24ec7db..72287f5792 100644 --- a/include/boost/math/tools/detail/rational_horner2_15.hpp +++ b/include/boost/math/tools/detail/rational_horner2_15.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_15_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_15_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -186,7 +186,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -218,7 +218,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_16.hpp b/include/boost/math/tools/detail/rational_horner2_16.hpp index 2eebd702bc..469ce84e1d 100644 --- a/include/boost/math/tools/detail/rational_horner2_16.hpp +++ b/include/boost/math/tools/detail/rational_horner2_16.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_16_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_16_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -186,7 +186,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -218,7 +218,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -234,7 +234,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_17.hpp b/include/boost/math/tools/detail/rational_horner2_17.hpp index 1fee63047f..d5a701bff3 100644 --- a/include/boost/math/tools/detail/rational_horner2_17.hpp +++ b/include/boost/math/tools/detail/rational_horner2_17.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_17_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_17_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -186,7 +186,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -218,7 +218,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -234,7 +234,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -250,7 +250,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_18.hpp b/include/boost/math/tools/detail/rational_horner2_18.hpp index 7aedbf2aad..bdad29c2f1 100644 --- a/include/boost/math/tools/detail/rational_horner2_18.hpp +++ b/include/boost/math/tools/detail/rational_horner2_18.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_18_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_18_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -186,7 +186,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -218,7 +218,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -234,7 +234,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -250,7 +250,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -266,7 +266,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_19.hpp b/include/boost/math/tools/detail/rational_horner2_19.hpp index 1c36a267cb..b86e528a9e 100644 --- a/include/boost/math/tools/detail/rational_horner2_19.hpp +++ b/include/boost/math/tools/detail/rational_horner2_19.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_19_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_19_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -186,7 +186,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -218,7 +218,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -234,7 +234,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -250,7 +250,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -266,7 +266,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -282,7 +282,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_2.hpp b/include/boost/math/tools/detail/rational_horner2_2.hpp index bb2e2c4dcf..a1c96e2db6 100644 --- a/include/boost/math/tools/detail/rational_horner2_2.hpp +++ b/include/boost/math/tools/detail/rational_horner2_2.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_2_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_2_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_20.hpp b/include/boost/math/tools/detail/rational_horner2_20.hpp index a591b901c9..753bb27b58 100644 --- a/include/boost/math/tools/detail/rational_horner2_20.hpp +++ b/include/boost/math/tools/detail/rational_horner2_20.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_20_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_20_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -138,7 +138,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -154,7 +154,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -170,7 +170,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -186,7 +186,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -202,7 +202,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -218,7 +218,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -234,7 +234,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -250,7 +250,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -266,7 +266,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -282,7 +282,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -298,7 +298,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_3.hpp b/include/boost/math/tools/detail/rational_horner2_3.hpp index 0b410d8bbe..fc3d19e1a8 100644 --- a/include/boost/math/tools/detail/rational_horner2_3.hpp +++ b/include/boost/math/tools/detail/rational_horner2_3.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_3_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_3_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_4.hpp b/include/boost/math/tools/detail/rational_horner2_4.hpp index 07a9a2c5ad..29befd1793 100644 --- a/include/boost/math/tools/detail/rational_horner2_4.hpp +++ b/include/boost/math/tools/detail/rational_horner2_4.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_4_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_4_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_5.hpp b/include/boost/math/tools/detail/rational_horner2_5.hpp index 0933ddfbc4..e7031a7d62 100644 --- a/include/boost/math/tools/detail/rational_horner2_5.hpp +++ b/include/boost/math/tools/detail/rational_horner2_5.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_5_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_5_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_6.hpp b/include/boost/math/tools/detail/rational_horner2_6.hpp index dee9c6e168..fe6b27c1b5 100644 --- a/include/boost/math/tools/detail/rational_horner2_6.hpp +++ b/include/boost/math/tools/detail/rational_horner2_6.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_6_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_6_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_7.hpp b/include/boost/math/tools/detail/rational_horner2_7.hpp index 6f9a85838c..8016ac2f4d 100644 --- a/include/boost/math/tools/detail/rational_horner2_7.hpp +++ b/include/boost/math/tools/detail/rational_horner2_7.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_7_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_7_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_8.hpp b/include/boost/math/tools/detail/rational_horner2_8.hpp index 33dda23bba..f8deefbd55 100644 --- a/include/boost/math/tools/detail/rational_horner2_8.hpp +++ b/include/boost/math/tools/detail/rational_horner2_8.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_8_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_8_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner2_9.hpp b/include/boost/math/tools/detail/rational_horner2_9.hpp index a9025a8900..bfe8de7abf 100644 --- a/include/boost/math/tools/detail/rational_horner2_9.hpp +++ b/include/boost/math/tools/detail/rational_horner2_9.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_9_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_9_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -58,7 +58,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -74,7 +74,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -90,7 +90,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -106,7 +106,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_10.hpp b/include/boost/math/tools/detail/rational_horner3_10.hpp index b7cec124e2..1ccde10782 100644 --- a/include/boost/math/tools/detail/rational_horner3_10.hpp +++ b/include/boost/math/tools/detail/rational_horner3_10.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_10_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_10_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_11.hpp b/include/boost/math/tools/detail/rational_horner3_11.hpp index 579f0e4868..9d3bb4053e 100644 --- a/include/boost/math/tools/detail/rational_horner3_11.hpp +++ b/include/boost/math/tools/detail/rational_horner3_11.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_11_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_11_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_12.hpp b/include/boost/math/tools/detail/rational_horner3_12.hpp index 54300dd08e..5d5be9b402 100644 --- a/include/boost/math/tools/detail/rational_horner3_12.hpp +++ b/include/boost/math/tools/detail/rational_horner3_12.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_12_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_12_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -570,7 +570,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_13.hpp b/include/boost/math/tools/detail/rational_horner3_13.hpp index d2fc7b6331..be8f5d22b1 100644 --- a/include/boost/math/tools/detail/rational_horner3_13.hpp +++ b/include/boost/math/tools/detail/rational_horner3_13.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_13_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_13_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -570,7 +570,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -672,7 +672,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_14.hpp b/include/boost/math/tools/detail/rational_horner3_14.hpp index 0b7675f494..49241d5b7a 100644 --- a/include/boost/math/tools/detail/rational_horner3_14.hpp +++ b/include/boost/math/tools/detail/rational_horner3_14.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_14_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_14_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -570,7 +570,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -672,7 +672,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -782,7 +782,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_15.hpp b/include/boost/math/tools/detail/rational_horner3_15.hpp index 8286caed0b..47c62f12d3 100644 --- a/include/boost/math/tools/detail/rational_horner3_15.hpp +++ b/include/boost/math/tools/detail/rational_horner3_15.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_15_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_15_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -570,7 +570,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -672,7 +672,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -782,7 +782,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -900,7 +900,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_16.hpp b/include/boost/math/tools/detail/rational_horner3_16.hpp index fc823e4162..430c9e1c29 100644 --- a/include/boost/math/tools/detail/rational_horner3_16.hpp +++ b/include/boost/math/tools/detail/rational_horner3_16.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_16_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_16_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -570,7 +570,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -672,7 +672,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -782,7 +782,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -900,7 +900,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1026,7 +1026,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_17.hpp b/include/boost/math/tools/detail/rational_horner3_17.hpp index cf7f75a706..07e3c901a5 100644 --- a/include/boost/math/tools/detail/rational_horner3_17.hpp +++ b/include/boost/math/tools/detail/rational_horner3_17.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_17_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_17_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -570,7 +570,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -672,7 +672,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -782,7 +782,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -900,7 +900,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1026,7 +1026,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1160,7 +1160,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_18.hpp b/include/boost/math/tools/detail/rational_horner3_18.hpp index f853ed3e0c..4809a31cd7 100644 --- a/include/boost/math/tools/detail/rational_horner3_18.hpp +++ b/include/boost/math/tools/detail/rational_horner3_18.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_18_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_18_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -570,7 +570,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -672,7 +672,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -782,7 +782,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -900,7 +900,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1026,7 +1026,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1160,7 +1160,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1302,7 +1302,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_19.hpp b/include/boost/math/tools/detail/rational_horner3_19.hpp index d44e22c90b..d930dbf4b1 100644 --- a/include/boost/math/tools/detail/rational_horner3_19.hpp +++ b/include/boost/math/tools/detail/rational_horner3_19.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_19_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_19_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -570,7 +570,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -672,7 +672,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -782,7 +782,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -900,7 +900,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1026,7 +1026,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1160,7 +1160,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1302,7 +1302,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1452,7 +1452,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_2.hpp b/include/boost/math/tools/detail/rational_horner3_2.hpp index bb2e2c4dcf..a1c96e2db6 100644 --- a/include/boost/math/tools/detail/rational_horner3_2.hpp +++ b/include/boost/math/tools/detail/rational_horner3_2.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_2_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_2_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_20.hpp b/include/boost/math/tools/detail/rational_horner3_20.hpp index 967edf0832..caeb4ab62e 100644 --- a/include/boost/math/tools/detail/rational_horner3_20.hpp +++ b/include/boost/math/tools/detail/rational_horner3_20.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_20_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_20_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -390,7 +390,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -476,7 +476,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -570,7 +570,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -672,7 +672,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -782,7 +782,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -900,7 +900,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1026,7 +1026,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1160,7 +1160,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1302,7 +1302,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1452,7 +1452,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -1610,7 +1610,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_3.hpp b/include/boost/math/tools/detail/rational_horner3_3.hpp index 0b410d8bbe..fc3d19e1a8 100644 --- a/include/boost/math/tools/detail/rational_horner3_3.hpp +++ b/include/boost/math/tools/detail/rational_horner3_3.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_3_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_3_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_4.hpp b/include/boost/math/tools/detail/rational_horner3_4.hpp index 07a9a2c5ad..29befd1793 100644 --- a/include/boost/math/tools/detail/rational_horner3_4.hpp +++ b/include/boost/math/tools/detail/rational_horner3_4.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_4_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_4_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_5.hpp b/include/boost/math/tools/detail/rational_horner3_5.hpp index 62c76dd506..31121d9f61 100644 --- a/include/boost/math/tools/detail/rational_horner3_5.hpp +++ b/include/boost/math/tools/detail/rational_horner3_5.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_5_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_5_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_6.hpp b/include/boost/math/tools/detail/rational_horner3_6.hpp index f81a068acb..507c8f1bba 100644 --- a/include/boost/math/tools/detail/rational_horner3_6.hpp +++ b/include/boost/math/tools/detail/rational_horner3_6.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_6_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_6_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_7.hpp b/include/boost/math/tools/detail/rational_horner3_7.hpp index fea457ccf8..d84e3960fe 100644 --- a/include/boost/math/tools/detail/rational_horner3_7.hpp +++ b/include/boost/math/tools/detail/rational_horner3_7.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_7_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_7_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_8.hpp b/include/boost/math/tools/detail/rational_horner3_8.hpp index 306e2a41d9..22c8081a39 100644 --- a/include/boost/math/tools/detail/rational_horner3_8.hpp +++ b/include/boost/math/tools/detail/rational_horner3_8.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_8_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_8_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/detail/rational_horner3_9.hpp b/include/boost/math/tools/detail/rational_horner3_9.hpp index 93a3527c18..b3e688be61 100644 --- a/include/boost/math/tools/detail/rational_horner3_9.hpp +++ b/include/boost/math/tools/detail/rational_horner3_9.hpp @@ -9,40 +9,40 @@ #ifndef BOOST_MATH_TOOLS_RAT_EVAL_9_HPP #define BOOST_MATH_TOOLS_RAT_EVAL_9_HPP -namespace boost{ namespace math{ namespace tools{ namespace detail{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T*, const U*, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(0); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V&, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(a[0]) / static_cast(b[0]); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((a[1] * x + a[0]) / (b[1] * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast(((a[2] * x + a[1]) * x + a[0]) / ((b[2] * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { return static_cast((((a[3] * x + a[2]) * x + a[1]) * x + a[0]) / (((b[3] * x + b[2]) * x + b[1]) * x + b[0])); } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -80,7 +80,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -126,7 +126,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } template -BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const boost::math::integral_constant*) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, const V& x, const BOOST_MATH_NAMESPACE::integral_constant*) BOOST_MATH_NOEXCEPT(V) { if((-1 <= x) && (x <= 1)) { @@ -312,7 +312,7 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* a, const U* b, } -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // include guard diff --git a/include/boost/math/tools/engel_expansion.hpp b/include/boost/math/tools/engel_expansion.hpp index 2d22a84d83..a28c08ff6f 100644 --- a/include/boost/math/tools/engel_expansion.hpp +++ b/include/boost/math/tools/engel_expansion.hpp @@ -6,6 +6,9 @@ #ifndef BOOST_MATH_TOOLS_ENGEL_EXPANSION_HPP #define BOOST_MATH_TOOLS_ENGEL_EXPANSION_HPP +#include + +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -13,6 +16,7 @@ #include #include #include +#endif #include #ifndef BOOST_MATH_STANDALONE @@ -22,9 +26,9 @@ #endif #endif -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { -template +BOOST_MATH_EXPORT template class engel_expansion { public: engel_expansion(Real x) : x_{x} @@ -96,7 +100,7 @@ class engel_expansion { }; -template +BOOST_MATH_EXPORT template std::ostream& operator<<(std::ostream& out, engel_expansion& engel) { constexpr const int p = std::numeric_limits::max_digits10; @@ -120,5 +124,5 @@ std::ostream& operator<<(std::ostream& out, engel_expansion& engel) } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/estrin.hpp b/include/boost/math/tools/estrin.hpp index 1955e9398f..8d34c1d7b5 100644 --- a/include/boost/math/tools/estrin.hpp +++ b/include/boost/math/tools/estrin.hpp @@ -7,16 +7,17 @@ #ifndef BOOST_MATH_TOOLS_ESTRIN_HPP #define BOOST_MATH_TOOLS_ESTRIN_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { -template +BOOST_MATH_EXPORT template inline RealOrComplex evaluate_polynomial_estrin(RandomAccessContainer1 const &coeffs, RandomAccessContainer2 &scratch, RealOrComplex z) { // Does anyone care about the complex coefficients, real argument case? // I've never seen it used, and this static assert makes the error messages much better: @@ -50,13 +51,13 @@ inline RealOrComplex evaluate_polynomial_estrin(RandomAccessContainer1 const &co } // The std::array template specialization doesn't need to allocate: -template +BOOST_MATH_EXPORT template inline RealOrComplex2 evaluate_polynomial_estrin(const std::array &coeffs, RealOrComplex2 z) { std::array ds; return evaluate_polynomial_estrin(coeffs, ds, z); } -template +BOOST_MATH_EXPORT template inline RealOrComplex evaluate_polynomial_estrin(const RandomAccessContainer &coeffs, RealOrComplex z) { auto n = coeffs.size(); // Normally, I'd make `ds` a RandomAccessContainer, but its value type needs to be RealOrComplex, @@ -67,6 +68,5 @@ inline RealOrComplex evaluate_polynomial_estrin(const RandomAccessContainer &coe } } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/fft.hpp b/include/boost/math/tools/fft.hpp new file mode 100644 index 0000000000..8ab2ff0696 --- /dev/null +++ b/include/boost/math/tools/fft.hpp @@ -0,0 +1,858 @@ +// Copyright Nick Thompson 2026. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_TOOLS_FFT_HPP +#define BOOST_MATH_TOOLS_FFT_HPP + +#include +#include +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace tools { + +namespace fft_detail { + +// The real type of a complex type: std::complex gives T, and a Boost.Multiprecision complex +// number gives its component type. Both have a real() member returning it. +template +using real_type_t = BOOST_MATH_NAMESPACE::tools::detail::real_from_complex_t; + +template +inline Complex conj(Complex const& z) +{ + return Complex(z.real(), -z.imag()); +} + +// Explicit products: std::complex operator* may call a C99 Annex G helper (e.g. __muldc3) +// that is much slower than the four multiplies we need. +template +inline Complex mul(Complex const& a, Complex const& b) +{ + return Complex(a.real() * b.real() - a.imag() * b.imag(), + a.real() * b.imag() + a.imag() * b.real()); +} + +// conj(a)*conj(b) +template +inline Complex mul_conj(Complex const& a, Complex const& b) +{ + return Complex(a.real() * b.real() - a.imag() * b.imag(), + -(a.real() * b.imag() + a.imag() * b.real())); +} + +// exp(i*pi*p/q) for integers p >= 0, q > 0. +// The reduction to the first octant is done in integer arithmetic, so the only rounding +// in the argument is that of a single quotient in [0, 1/4]; each twiddle is then within +// a couple of ulps of the exact root of unity, with no accumulation from a recurrence. +template +Complex cis_pi(std::size_t p, std::size_t q) +{ + using Real = real_type_t; + using BOOST_MATH_NAMESPACE::sin_pi; + using BOOST_MATH_NAMESPACE::cos_pi; + p %= 2 * q; + bool negate_cos = false; + bool negate_sin = false; + if (p >= q) + { + // theta -> theta - pi + p -= q; + negate_cos = true; + negate_sin = true; + } + if (2 * p > q) + { + // theta -> pi - theta + p = q - p; + negate_cos = !negate_cos; + } + // Now theta = pi*p/q lies in [0, pi/2]. + Real c; + Real s; + if (4 * p > q) + { + // theta = pi/2 - pi*x with x in [0, 1/4). + Real x = Real(q - 2 * p) / Real(2 * q); + c = sin_pi(x); + s = cos_pi(x); + } + else + { + Real x = Real(p) / Real(q); + c = cos_pi(x); + s = sin_pi(x); + } + if (negate_cos) + { + c = -c; + } + if (negate_sin) + { + s = -s; + } + return Complex(c, s); +} + +// The largest prime factor the mixed-radix FFT takes; a length with a larger one uses Bluestein. +// A radix-p stage costs O(p) per point, Bluestein a constant factor of about 3 to 4 over a 5-smooth FFT; +// measured (complex, n = p 2^k and 1000 p), Bluestein starts to win between p = 97 and p = 127, +// and the mixed-radix FFT is the more accurate up to about the same point. +constexpr std::size_t max_prime_radix = 97; + +// The prime factors of n, in increasing order, with multiplicity. +inline std::vector prime_factors(std::size_t n) +{ + std::vector f; + for (std::size_t p = 2; p * p <= n; ++p) + { + while (n % p == 0) + { + f.push_back(p); + n /= p; + } + } + if (n > 1) + { + f.push_back(n); + } + return f; +} + +// Whether every prime factor of n is at most max_prime_radix; other lengths use Bluestein. +inline bool is_smooth(std::size_t n) +{ + std::vector f = prime_factors(n); + return f.empty() || f.back() <= max_prime_radix; +} + +inline std::size_t next_5_smooth(std::size_t n) +{ + for (std::size_t m = n;; ++m) + { + std::size_t r = m; + for (std::size_t p : {2, 3, 5}) + { + while (r % p == 0) + { + r /= p; + } + } + if (r == 1) + { + return m; + } + } +} + +// The length of Bluestein's convolution: the smallest 2^a 3^b 5^c >= n, unless the next power of 2 +// is within 20% of it, since radix-4 stages are cheaper than radix-3 and radix-5 ones. +inline std::size_t convolution_length(std::size_t n) +{ + std::size_t smooth = next_5_smooth(n); + std::size_t power_of_two = 1; + while (power_of_two < n) + { + power_of_two <<= 1; + } + return 5 * power_of_two <= 6 * smooth ? power_of_two : smooth; +} + +// Radix-2 and radix-4 butterflies, and a butterfly for any odd prime radix R that pairs t with R - t: +// y[u] = a[0] + sum_{t=1}^{(R-1)/2} (a[t] + a[R-t]) cos(2 pi t u/R) - i (a[t] - a[R-t]) sin(2 pi t u/R). +template +struct butterfly +{ + using Real = real_type_t; + static void apply(Complex* a, Real const* c, Real const* s) + { + constexpr std::size_t h = (R - 1) / 2; + Complex sum[h + 1]; + Complex diff[h + 1]; + Complex y0 = a[0]; + for (std::size_t t = 1; t <= h; ++t) + { + sum[t] = a[t] + a[R - t]; + diff[t] = a[t] - a[R - t]; + y0 += sum[t]; + } + for (std::size_t u = 1; u <= h; ++u) + { + Real even_re = a[0].real(); + Real even_im = a[0].imag(); + Real odd_re = 0; + Real odd_im = 0; + for (std::size_t t = 1; t <= h; ++t) + { + std::size_t k = (t * u) % R; + even_re += sum[t].real() * c[k]; + even_im += sum[t].imag() * c[k]; + odd_re += diff[t].real() * s[k]; + odd_im += diff[t].imag() * s[k]; + } + // even -/+ i*odd + a[u] = Complex(even_re + odd_im, even_im - odd_re); + a[R - u] = Complex(even_re - odd_im, even_im + odd_re); + } + a[0] = y0; + } +}; + +template +struct butterfly +{ + using Real = real_type_t; + static void apply(Complex* a, Real const*, Real const*) + { + Complex t = a[0]; + a[0] = t + a[1]; + a[1] = t - a[1]; + } +}; + +template +struct butterfly +{ + using Real = real_type_t; + static void apply(Complex* a, Real const*, Real const*) + { + Complex s02 = a[0] + a[2]; + Complex d02 = a[0] - a[2]; + Complex s13 = a[1] + a[3]; + Complex d13 = a[1] - a[3]; + // -i*d13 + Complex r(d13.imag(), -d13.real()); + a[0] = s02 + s13; + a[1] = d02 + r; + a[2] = s02 - s13; + a[3] = d02 - r; + } +}; + +// One Stockham autosort stage (decimation in frequency). The current sub-transforms have length L = R*m, +// and there are s of them, interleaved with stride s. Each writes R sub-transforms of length m: +// y[q + s*(R*p + u)] = w_L^{p*u} * sum_t x[q + s*(p + t*m)] w_R^{t*u}. +template +void stockham_stage(Complex const* x, Complex* y, std::size_t m, std::size_t s, Complex const* twiddles, + real_type_t const* c, real_type_t const* sn) +{ + Complex a[R]; + if (s == 1) + { + // The first stage: one sub-transform per p, so make p the inner (vectorizable) loop. + // The p = 0 twiddles are exactly 1. + for (std::size_t p = 0; p < m; ++p) + { + for (std::size_t t = 0; t < R; ++t) + { + a[t] = x[p + t * m]; + } + butterfly::apply(a, c, sn); + Complex const* w = twiddles + p * (R - 1); + y[R * p] = a[0]; + for (std::size_t u = 1; u < R; ++u) + { + y[R * p + u] = mul(a[u], w[u - 1]); + } + } + return; + } + for (std::size_t q = 0; q < s; ++q) + { + for (std::size_t t = 0; t < R; ++t) + { + a[t] = x[q + s * t * m]; + } + butterfly::apply(a, c, sn); + for (std::size_t u = 0; u < R; ++u) + { + y[q + s * u] = a[u]; + } + } + for (std::size_t p = 1; p < m; ++p) + { + Complex const* w = twiddles + p * (R - 1); + for (std::size_t q = 0; q < s; ++q) + { + for (std::size_t t = 0; t < R; ++t) + { + a[t] = x[q + s * (p + t * m)]; + } + butterfly::apply(a, c, sn); + y[q + s * R * p] = a[0]; + for (std::size_t u = 1; u < R; ++u) + { + y[q + s * (R * p + u)] = mul(a[u], w[u - 1]); + } + } + } +} + +// The odd-prime butterfly of butterfly for a radix R known only at run time. +// sum and diff hold (R + 1)/2 values each. c[k] = cos(2 pi k/R), s[k] = sin(2 pi k/R). +template +void generic_butterfly(Complex* a, std::size_t R, real_type_t const* c, real_type_t const* sn, + Complex* sum, Complex* diff) +{ + using Real = real_type_t; + std::size_t h = (R - 1) / 2; + Complex y0 = a[0]; + for (std::size_t t = 1; t <= h; ++t) + { + sum[t] = a[t] + a[R - t]; + diff[t] = a[t] - a[R - t]; + y0 += sum[t]; + } + for (std::size_t u = 1; u <= h; ++u) + { + Real even_re = a[0].real(); + Real even_im = a[0].imag(); + Real odd_re = 0; + Real odd_im = 0; + // k = t*u mod R, updated without a division. + std::size_t k = 0; + for (std::size_t t = 1; t <= h; ++t) + { + k += u; + if (k >= R) + { + k -= R; + } + even_re += sum[t].real() * c[k]; + even_im += sum[t].imag() * c[k]; + odd_re += diff[t].real() * sn[k]; + odd_im += diff[t].imag() * sn[k]; + } + a[u] = Complex(even_re + odd_im, even_im - odd_re); + a[R - u] = Complex(even_re - odd_im, even_im + odd_re); + } + a[0] = y0; +} + +// stockham_stage for an odd prime radix R known only at run time; work holds 2R + 2 values. +template +void generic_stage(Complex const* x, Complex* y, std::size_t R, std::size_t m, std::size_t s, Complex const* twiddles, + real_type_t const* c, real_type_t const* sn, Complex* work) +{ + Complex* a = work; + Complex* sum = work + R; + Complex* diff = sum + (R + 1) / 2; + for (std::size_t p = 0; p < m; ++p) + { + Complex const* w = twiddles + p * (R - 1); + for (std::size_t q = 0; q < s; ++q) + { + for (std::size_t t = 0; t < R; ++t) + { + a[t] = x[q + s * (p + t * m)]; + } + generic_butterfly(a, R, c, sn, sum, diff); + y[q + s * R * p] = a[0]; + for (std::size_t u = 1; u < R; ++u) + { + y[q + s * (R * p + u)] = p == 0 ? a[u] : mul(a[u], w[u - 1]); + } + } + } +} + +// A forward FFT of a length whose prime factors are all at most max_prime_radix, done by Stockham +// stages that ping-pong between the data and a scratch buffer, so no digit reversal is needed. +template +class smooth_fft +{ +public: + using Real = real_type_t; + + smooth_fft() = default; + + explicit smooth_fft(std::size_t n) : m_n(n) + { + // Every twiddle is a power of w = exp(-2*pi*i/n); compute the powers we need directly, + // using exp(-2*pi*i*(n-k)/n) = conj(exp(-2*pi*i*k/n)), which is exact. + std::vector roots(n); + for (std::size_t k = 0; 2 * k <= n; ++k) + { + roots[k] = conj(cis_pi(2 * k, n)); + if (k != 0 && 2 * k != n) + { + roots[n - k] = conj(roots[k]); + } + } + // Radices: 4s, then a 2, then the odd primes in increasing order. + std::vector f = prime_factors(n); + std::size_t twos = static_cast(std::count(f.begin(), f.end(), std::size_t(2))); + for (std::size_t i = 0; i < twos / 2; ++i) + { + m_radices.push_back(4); + } + if (twos % 2 != 0) + { + m_radices.push_back(2); + } + for (std::size_t p : f) + { + BOOST_MATH_ASSERT(p <= max_prime_radix); + if (p != 2) + { + m_radices.push_back(p); + } + } + // Stage i has s = product of the earlier radices, L = n/s and m = L/R; its twiddle for (p, u) is + // w_L^{p*u} = roots[p*u*s], with p*u*s < n. + std::size_t s = 1; + for (std::size_t R : m_radices) + { + std::size_t m = n / (s * R); + m_offsets.push_back(m_twiddles.size()); + for (std::size_t p = 0; p < m; ++p) + { + for (std::size_t u = 1; u < R; ++u) + { + m_twiddles.push_back(roots[p * u * s]); + } + } + s *= R; + } + // cos(2*pi*k/R) and sin(2*pi*k/R) for each odd radix R, one table per distinct radix. + for (std::size_t i = 0; i < m_radices.size(); ++i) + { + std::size_t R = m_radices[i]; + std::size_t offset = 0; + if (R % 2 != 0) + { + auto earlier = std::find(m_radices.begin(), m_radices.begin() + static_cast(i), R); + if (earlier != m_radices.begin() + static_cast(i)) + { + offset = m_trig_offsets[static_cast(earlier - m_radices.begin())]; + } + else + { + offset = m_cos.size(); + for (std::size_t k = 0; k < R; ++k) + { + Complex z = cis_pi(2 * k, R); + m_cos.push_back(z.real()); + m_sin.push_back(z.imag()); + } + } + if (R > 7) + { + m_generic_work = (std::max)(m_generic_work, 2 * R + 2); + } + } + m_trig_offsets.push_back(offset); + } + } + + std::size_t size() const noexcept { return m_n; } + + // The scratch space execute needs: m_n values (none for n = 1), and room for a generic butterfly. + std::size_t scratch_size() const noexcept { return m_radices.empty() ? 0 : m_n + m_generic_work; } + + // Transforms the m_n contiguous values at data in place, using scratch_size() values at scratch, + // which must not overlap data. + void execute(Complex* data, Complex* scratch) const + { + if (m_radices.empty()) + { + return; + } + Complex* x = data; + Complex* y = scratch; + std::size_t s = 1; + for (std::size_t i = 0; i < m_radices.size(); ++i) + { + std::size_t R = m_radices[i]; + stage(i, x, y, R, m_n / (s * R), s, scratch + m_n); + std::swap(x, y); + s *= R; + } + if (x != data) + { + std::copy(x, x + m_n, data); + } + } + + // Transforms in into out, leaving in unchanged; in, out and scratch must not overlap. + // The stages alternate between out and scratch so that the last one writes out. + void execute(Complex const* in, Complex* out, Complex* scratch) const + { + std::size_t stages = m_radices.size(); + if (stages == 0) + { + std::copy(in, in + m_n, out); + return; + } + Complex const* x = in; + std::size_t s = 1; + for (std::size_t i = 0; i < stages; ++i) + { + std::size_t R = m_radices[i]; + Complex* y = (stages - 1 - i) % 2 == 0 ? out : scratch; + stage(i, x, y, R, m_n / (s * R), s, scratch + m_n); + x = y; + s *= R; + } + } + +private: + // Stage i, of radix R; work is room for a generic butterfly. + void stage(std::size_t i, Complex const* x, Complex* y, std::size_t R, std::size_t m, std::size_t s, Complex* work) const + { + Complex const* w = m_twiddles.data() + m_offsets[i]; + Real const* c = m_cos.data() + m_trig_offsets[i]; + Real const* sn = m_sin.data() + m_trig_offsets[i]; + switch (R) + { + case 2: + stockham_stage(x, y, m, s, w, c, sn); + break; + case 3: + stockham_stage(x, y, m, s, w, c, sn); + break; + case 4: + stockham_stage(x, y, m, s, w, c, sn); + break; + case 5: + stockham_stage(x, y, m, s, w, c, sn); + break; + case 7: + stockham_stage(x, y, m, s, w, c, sn); + break; + // Compile-time butterflies for 11 and 13 are 5 to 15% faster than the generic one. + case 11: + stockham_stage(x, y, m, s, w, c, sn); + break; + case 13: + stockham_stage(x, y, m, s, w, c, sn); + break; + default: + generic_stage(x, y, R, m, s, w, c, sn, work); + break; + } + } + + std::size_t m_n = 0; + std::vector m_radices; + std::vector m_offsets; + std::vector m_twiddles; + std::vector m_cos; + std::vector m_sin; + // Where stage i's cos/sin table starts in m_cos and m_sin. + std::vector m_trig_offsets; + // Workspace for a generic (radix > 7) butterfly, after the ping-pong buffer. + std::size_t m_generic_work = 0; +}; + +// The documented requirement is a size() member, not iterators: +template +inline std::size_t container_size(Container const& v) +{ + return static_cast(v.size()); +} + +} // namespace fft_detail + +BOOST_MATH_EXPORT template +class real_fft; + +// Discrete Fourier transform of a fixed length n, templated on the complex type +// (std::complex, std::complex, std::complex, or a Boost.Multiprecision +// complex type such as cpp_complex_50): +// +// X[k] = sum_{j=0}^{n-1} x[j] exp(-2*pi*i*j*k/n), +// +// with the inverse normalised by 1/n, so that inverse_transform(transform(x)) == x. +// Lengths whose prime factors are all at most 97 use a mixed-radix Stockham FFT (radix 4 where possible). +// Every other length uses Bluestein's algorithm, with a convolution whose length is 2^a 3^b 5^c. +// The constructor builds all the tables and allocates all the workspace, so transforms never allocate. +// Like an FFTW plan with its buffers, an object is used by one thread at a time: give each thread its own. +BOOST_MATH_EXPORT template +class fft +{ +public: + using value_type = Complex; + using real_type = fft_detail::real_type_t; + + explicit fft(std::size_t n) : m_n(n) + { + if (n == 0) + { + throw std::domain_error("The length of the transform must be positive."); + } + if (fft_detail::is_smooth(n)) + { + m_plan = fft_detail::smooth_fft(n); + m_work.resize(m_plan.scratch_size()); + } + else + { + m_plan = fft_detail::smooth_fft(fft_detail::convolution_length(2 * n - 1)); + // The convolution buffer, then the scratch space of its FFTs. + m_work.resize(m_plan.size() + m_plan.scratch_size()); + build_chirp(); + } + } + + std::size_t size() const noexcept { return m_n; } + + // Transforms v in place. v is a contiguous container of n values of type Complex, + // such as std::vector or std::array. + template + void transform(ContiguousContainer& v) + { + Complex* x = data_of(v); + forward(x, x); + } + + template + void inverse_transform(ContiguousContainer& v) + { + Complex* x = data_of(v); + inverse(x, x); + } + + // Out of place: out receives the transform of in, which is left unchanged. + // Both hold n values of type Complex contiguously, and they must not overlap. + template + void transform(InputContainer const& in, OutputContainer& out) + { + forward(data_of(in), data_of(out)); + } + + template + void inverse_transform(InputContainer const& in, OutputContainer& out) + { + inverse(data_of(in), data_of(out)); + } + +private: + template friend class real_fft; + + template + auto data_of(ContiguousContainer& v) const -> decltype(v.data()) + { + static_assert(std::is_same::type, Complex>::value, + "The container's elements must be of the transform's complex type."); + if (fft_detail::container_size(v) != m_n) + { + throw std::domain_error("The length of the data does not match the length of the transform."); + } + return v.data(); + } + + // Bluestein: with c[j] = exp(-i*pi*j^2/n), jk = (j^2 + k^2 - (k-j)^2)/2 gives + // X[k] = c[k] * sum_j (x[j] c[j]) conj(c[k-j]), + // a linear convolution that is computed as a cyclic one of length m >= 2n - 1. + void build_chirp() + { + std::size_t len = m_plan.size(); + m_chirp.resize(m_n); + // j^2 mod 2n, updated exactly so that j^2 never overflows. + std::size_t two_n = 2 * m_n; + std::size_t r = 0; + for (std::size_t j = 0; j < m_n; ++j) + { + m_chirp[j] = fft_detail::conj(fft_detail::cis_pi(r, m_n)); + // (j+1)^2 = j^2 + 2j + 1 + r = (r + (2 * j + 1) % two_n) % two_n; + } + std::vector b(len, Complex(0, 0)); + for (std::size_t j = 0; j < m_n; ++j) + { + b[j] = fft_detail::conj(m_chirp[j]); + if (j != 0) + { + b[len - j] = b[j]; + } + } + m_plan.execute(b.data(), m_work.data() + len); + // Store B/m: the convolution's inverse FFT is done as conj(F(conj(A)*conj(B/m))). + real_type m = real_type(len); + for (std::size_t k = 0; k < len; ++k) + { + b[k] = Complex(b[k].real() / m, b[k].imag() / m); + } + m_kernel = std::move(b); + } + + // out = F(in). in and out are either the same array or don't overlap. + void forward(Complex const* in, Complex* out) + { + if (m_chirp.empty()) + { + if (in == out) + { + m_plan.execute(out, m_work.data()); + } + else + { + m_plan.execute(in, out, m_work.data()); + } + return; + } + std::size_t m = m_plan.size(); + Complex* a = m_work.data(); + Complex* scratch = a + m; + for (std::size_t j = 0; j < m_n; ++j) + { + a[j] = fft_detail::mul(in[j], m_chirp[j]); + } + std::fill(a + m_n, a + m, Complex(0, 0)); + m_plan.execute(a, scratch); + for (std::size_t k = 0; k < m; ++k) + { + a[k] = fft_detail::mul_conj(a[k], m_kernel[k]); + } + m_plan.execute(a, scratch); + for (std::size_t k = 0; k < m_n; ++k) + { + out[k] = fft_detail::mul(fft_detail::conj(a[k]), m_chirp[k]); + } + } + + // out = conj(F(conj(in)))/n; in and out are either the same array or don't overlap. + void inverse(Complex const* in, Complex* out) + { + for (std::size_t j = 0; j < m_n; ++j) + { + out[j] = fft_detail::conj(in[j]); + } + forward(out, out); + real_type n = real_type(m_n); + for (std::size_t j = 0; j < m_n; ++j) + { + out[j] = Complex(out[j].real() / n, -out[j].imag() / n); + } + } + + std::size_t m_n; + // The FFT that does the work: of length n itself, or of the Bluestein convolution length. + fft_detail::smooth_fft m_plan; + std::vector m_chirp; + std::vector m_kernel; + // Workspace: the Stockham ping-pong buffer, or Bluestein's convolution buffer followed by that. + std::vector m_work; +}; + +// Transform of n real samples, templated on the complex type of the result. The input holds n values +// of the real type of Complex; the output must hold exactly n/2 + 1 values of type Complex, and receives +// X[0], ..., X[n/2]. The rest follow from X[n-k] = conj(X[k]). Even n packs the input into a complex FFT +// of length n/2; odd n uses a complex FFT of length n. +BOOST_MATH_EXPORT template +class real_fft +{ +public: + using value_type = Complex; + using real_type = fft_detail::real_type_t; + + explicit real_fft(std::size_t n) : m_n(n), m_fft(n % 2 == 0 && n > 0 ? n / 2 : n) + { + if (n % 2 != 0) + { + m_z.resize(n); + } + else + { + // exp(-2*pi*i*k/n) for k in [0, n/2]. + m_twiddles.resize(n / 2 + 1); + for (std::size_t k = 0; k <= n / 2; ++k) + { + m_twiddles[k] = fft_detail::conj(fft_detail::cis_pi(2 * k, n)); + } + } + } + + std::size_t size() const noexcept { return m_n; } + + // input: n real values; output: exactly n/2 + 1 complex values, which are overwritten. + // Any container with operator[] works for the input; the output must be contiguous (data() and size()). + // As with fft, the constructor allocates all the workspace, and an object is used by one thread at a time. + template + void transform(RealContainer const& input, ComplexContainer& output) + { + static_assert(std::is_same::type, Complex>::value, + "The output container's elements must be of the transform's complex type."); + if (fft_detail::container_size(input) != m_n) + { + throw std::domain_error("The length of the input does not match the length of the transform."); + } + if (fft_detail::container_size(output) != m_n / 2 + 1) + { + throw std::domain_error("The output must hold n/2 + 1 values."); + } + Complex* out = output.data(); + if (m_n % 2 != 0) + { + Complex* z = m_z.data(); + for (std::size_t j = 0; j < m_n; ++j) + { + z[j] = Complex(real_type(input[j]), real_type(0)); + } + m_fft.forward(z, z); + std::copy(z, z + (m_n / 2 + 1), out); + return; + } + // Pack the input into the first n/2 output slots and transform it there. + std::size_t h = m_n / 2; + for (std::size_t j = 0; j < h; ++j) + { + out[j] = Complex(real_type(input[2 * j]), real_type(input[2 * j + 1])); + } + m_fft.forward(out, out); + // With Z = DFT(z): E[k] = (Z[k] + conj(Z[h-k]))/2 is the transform of the even samples, + // O[k] = (Z[k] - conj(Z[h-k]))/(2i) that of the odd ones, and X[k] = E[k] + exp(-2*pi*i*k/n) O[k]. + // X[k] and X[h-k] use the same two values of Z, so compute them together, in place. + Complex z0 = out[0]; + out[0] = combine(z0, z0, 0); + out[h] = combine(z0, z0, h); + for (std::size_t k = 1; 2 * k < h; ++k) + { + Complex zk = out[k]; + Complex zh = out[h - k]; + out[k] = combine(zk, zh, k); + out[h - k] = combine(zh, zk, h - k); + } + if (h % 2 == 0) + { + out[h / 2] = combine(out[h / 2], out[h / 2], h / 2); + } + } + +private: + // X[k] from zk = Z[k] and zh = Z[h-k]. + Complex combine(Complex const& zk, Complex const& zh, std::size_t k) const + { + Complex zc = fft_detail::conj(zh); + Complex e((zk.real() + zc.real()) / 2, (zk.imag() + zc.imag()) / 2); + Complex d((zk.real() - zc.real()) / 2, (zk.imag() - zc.imag()) / 2); + Complex o(d.imag(), -d.real()); + Complex t = fft_detail::mul(m_twiddles[k], o); + return Complex(e.real() + t.real(), e.imag() + t.imag()); + } + + std::size_t m_n; + fft m_fft; + std::vector m_twiddles; + // Odd n: the input as complex values, transformed in place. + std::vector m_z; +}; + +} BOOST_MATH_NAMESPACE_END + +#endif diff --git a/include/boost/math/tools/fraction.hpp b/include/boost/math/tools/fraction.hpp index f36d024c40..546f4aa611 100644 --- a/include/boost/math/tools/fraction.hpp +++ b/include/boost/math/tools/fraction.hpp @@ -19,16 +19,16 @@ #include #include -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail { template - struct is_pair : public boost::math::false_type{}; + struct is_pair : public BOOST_MATH_NAMESPACE::false_type{}; template - struct is_pair> : public boost::math::true_type{}; + struct is_pair> : public BOOST_MATH_NAMESPACE::true_type{}; template struct fraction_traits_simple @@ -64,7 +64,7 @@ namespace detail template struct fraction_traits - : public boost::math::conditional< + : public BOOST_MATH_NAMESPACE::conditional< is_pair::value, fraction_traits_pair, fraction_traits_simple>::type @@ -110,7 +110,7 @@ namespace detail { // template -BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_b_impl(Gen& g, const U& factor, boost::math::uintmax_t& max_terms) +BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_b_impl(Gen& g, const U& factor, BOOST_MATH_NAMESPACE::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT // SYCL can not handle this condition so we only check float on that platform @@ -140,7 +140,7 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type C = f; D = 0; - boost::math::uintmax_t counter(max_terms); + BOOST_MATH_NAMESPACE::uintmax_t counter(max_terms); do{ v = g(); D = traits::b(v) + traits::a(v) * D; @@ -161,8 +161,8 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type } // namespace detail -template -BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_b(Gen& g, const U& factor, boost::math::uintmax_t& max_terms) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_b(Gen& g, const U& factor, BOOST_MATH_NAMESPACE::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) @@ -172,7 +172,7 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type return detail::continued_fraction_b_impl(g, factor, max_terms); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_b(Gen& g, const U& factor) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT @@ -180,11 +180,11 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type #endif ) { - boost::math::uintmax_t max_terms = (boost::math::numeric_limits::max)(); + BOOST_MATH_NAMESPACE::uintmax_t max_terms = (BOOST_MATH_NAMESPACE::numeric_limits::max)(); return detail::continued_fraction_b_impl(g, factor, max_terms); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_b(Gen& g, int bits) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT @@ -198,12 +198,12 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type using result_type = typename traits::result_type; result_type factor = ldexp(1.0f, 1 - bits); // 1 / pow(result_type(2), bits); - boost::math::uintmax_t max_terms = (boost::math::numeric_limits::max)(); + BOOST_MATH_NAMESPACE::uintmax_t max_terms = (BOOST_MATH_NAMESPACE::numeric_limits::max)(); return detail::continued_fraction_b_impl(g, factor, max_terms); } -template -BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_b(Gen& g, int bits, boost::math::uintmax_t& max_terms) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_b(Gen& g, int bits, BOOST_MATH_NAMESPACE::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) @@ -236,7 +236,7 @@ namespace detail { // Note that the first a1 and b1 returned by generator Gen are both used. // template -BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_a_impl(Gen& g, const U& factor, boost::math::uintmax_t& max_terms) +BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_a_impl(Gen& g, const U& factor, BOOST_MATH_NAMESPACE::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) @@ -266,7 +266,7 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type C = f; D = 0; - boost::math::uintmax_t counter(max_terms); + BOOST_MATH_NAMESPACE::uintmax_t counter(max_terms); do{ v = g(); @@ -288,8 +288,8 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type } // namespace detail -template -BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_a(Gen& g, const U& factor, boost::math::uintmax_t& max_terms) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_a(Gen& g, const U& factor, BOOST_MATH_NAMESPACE::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) @@ -299,7 +299,7 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type return detail::continued_fraction_a_impl(g, factor, max_terms); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_a(Gen& g, const U& factor) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT @@ -307,11 +307,11 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type #endif ) { - boost::math::uintmax_t max_iter = (boost::math::numeric_limits::max)(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = (BOOST_MATH_NAMESPACE::numeric_limits::max)(); return detail::continued_fraction_a_impl(g, factor, max_iter); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_a(Gen& g, int bits) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT @@ -325,13 +325,13 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type typedef typename traits::result_type result_type; result_type factor = ldexp(1.0f, 1-bits); // 1 / pow(result_type(2), bits); - boost::math::uintmax_t max_iter = (boost::math::numeric_limits::max)(); + BOOST_MATH_NAMESPACE::uintmax_t max_iter = (BOOST_MATH_NAMESPACE::numeric_limits::max)(); return detail::continued_fraction_a_impl(g, factor, max_iter); } -template -BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_a(Gen& g, int bits, boost::math::uintmax_t& max_terms) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type continued_fraction_a(Gen& g, int bits, BOOST_MATH_NAMESPACE::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) @@ -348,7 +348,6 @@ BOOST_MATH_GPU_ENABLED inline typename detail::fraction_traits::result_type } } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_FRACTION_INCLUDED diff --git a/include/boost/math/tools/is_constant_evaluated.hpp b/include/boost/math/tools/is_constant_evaluated.hpp index eb903dbd71..28524df560 100644 --- a/include/boost/math/tools/is_constant_evaluated.hpp +++ b/include/boost/math/tools/is_constant_evaluated.hpp @@ -10,9 +10,13 @@ #ifdef __has_include # if __has_include() +#ifndef BOOST_MATH_BUILD_MODULE # include +#endif # ifdef __cpp_lib_is_constant_evaluated +#ifndef BOOST_MATH_BUILD_MODULE # include +#endif # define BOOST_MATH_HAS_IS_CONSTANT_EVALUATED # endif # endif diff --git a/include/boost/math/tools/is_detected.hpp b/include/boost/math/tools/is_detected.hpp index 93fa96f60b..00480d1b8d 100644 --- a/include/boost/math/tools/is_detected.hpp +++ b/include/boost/math/tools/is_detected.hpp @@ -10,7 +10,7 @@ #include -namespace boost { namespace math { namespace tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { template using void_t = void; @@ -20,14 +20,14 @@ namespace detail { template class Op, typename... Args> struct detector { - using value_t = boost::math::false_type; + using value_t = BOOST_MATH_NAMESPACE::false_type; using type = Default; }; template class Op, typename... Args> struct detector>, Op, Args...> { - using value_t = boost::math::true_type; + using value_t = BOOST_MATH_NAMESPACE::true_type; using type = Op; }; @@ -51,6 +51,6 @@ using detected_t = typename detail::detector::type; template class Op, typename... Args> using detected_or = detail::detector; -}}} // Namespaces boost math tools +} BOOST_MATH_NAMESPACE_END // Namespaces boost math tools #endif // BOOST_MATH_TOOLS_IS_DETECTED_HPP diff --git a/include/boost/math/tools/luroth_expansion.hpp b/include/boost/math/tools/luroth_expansion.hpp index 583b227d7a..69885bde12 100644 --- a/include/boost/math/tools/luroth_expansion.hpp +++ b/include/boost/math/tools/luroth_expansion.hpp @@ -6,6 +6,9 @@ #ifndef BOOST_MATH_TOOLS_LUROTH_EXPANSION_HPP #define BOOST_MATH_TOOLS_LUROTH_EXPANSION_HPP +#include + +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -13,6 +16,7 @@ #include #include #include +#endif #include #ifndef BOOST_MATH_STANDALONE @@ -22,9 +26,9 @@ #endif #endif -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { -template +BOOST_MATH_EXPORT template class luroth_expansion { public: luroth_expansion(Real x) : x_{x} @@ -75,10 +79,10 @@ class luroth_expansion { x = dn*(dn+1)*(x - tmp); } - for (size_t i = 1; i < d_.size(); ++i) + for (size_t k = 1; k < d_.size(); ++k) { // Sanity check: - if (d_[i] <= 0) + if (d_[k] <= 0) { throw std::domain_error("Found a digit <= 0; this is an error."); } @@ -115,7 +119,7 @@ class luroth_expansion { }; -template +BOOST_MATH_EXPORT template std::ostream& operator<<(std::ostream& out, luroth_expansion& luroth) { constexpr const int p = std::numeric_limits::max_digits10; @@ -143,5 +147,5 @@ std::ostream& operator<<(std::ostream& out, luroth_expansion& luroth) } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/minima.hpp b/include/boost/math/tools/minima.hpp index a6be94cb2b..3c468bc05d 100644 --- a/include/boost/math/tools/minima.hpp +++ b/include/boost/math/tools/minima.hpp @@ -19,10 +19,10 @@ #include #include -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ -template -BOOST_MATH_GPU_ENABLED boost::math::pair brent_find_minima(F f, T min, T max, int bits, boost::math::uintmax_t& max_iter) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::pair brent_find_minima(F f, T min, T max, int bits, BOOST_MATH_NAMESPACE::uintmax_t& max_iter) noexcept(BOOST_MATH_IS_FLOAT(T) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()(std::declval())) @@ -30,7 +30,7 @@ BOOST_MATH_GPU_ENABLED boost::math::pair brent_find_minima(F f, T min, T m ) { BOOST_MATH_STD_USING - bits = (boost::math::min)(policies::digits >() / 2, bits); + bits = (BOOST_MATH_NAMESPACE::min)(policies::digits >() / 2, bits); T tolerance = static_cast(ldexp(1.0, 1-bits)); T x; // minima so far T w; // second best point @@ -48,7 +48,7 @@ BOOST_MATH_GPU_ENABLED boost::math::pair brent_find_minima(F f, T min, T m fw = fv = fx = f(x); delta2 = delta = 0; - boost::math::uintmax_t count = max_iter; + BOOST_MATH_NAMESPACE::uintmax_t count = max_iter; do{ // get midpoint @@ -140,22 +140,22 @@ BOOST_MATH_GPU_ENABLED boost::math::pair brent_find_minima(F f, T min, T m max_iter -= count; - return boost::math::make_pair(x, fx); + return BOOST_MATH_NAMESPACE::make_pair(x, fx); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair brent_find_minima(F f, T min, T max, int digits) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair brent_find_minima(F f, T min, T max, int digits) noexcept(BOOST_MATH_IS_FLOAT(T) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()(std::declval())) #endif ) { - boost::math::uintmax_t m = (boost::math::numeric_limits::max)(); + BOOST_MATH_NAMESPACE::uintmax_t m = (BOOST_MATH_NAMESPACE::numeric_limits::max)(); return brent_find_minima(f, min, max, digits, m); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/mp.hpp b/include/boost/math/tools/mp.hpp index 560ae8b500..8f92fcebc7 100644 --- a/include/boost/math/tools/mp.hpp +++ b/include/boost/math/tools/mp.hpp @@ -15,7 +15,7 @@ #include #include -namespace boost { namespace math { namespace tools { namespace meta_programming { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace meta_programming { // Types: // Typelist @@ -23,12 +23,12 @@ template struct mp_list {}; // Size_t -template -using mp_size_t = boost::math::integral_constant; +template +using mp_size_t = BOOST_MATH_NAMESPACE::integral_constant; // Boolean template -using mp_bool = boost::math::integral_constant; +using mp_bool = BOOST_MATH_NAMESPACE::integral_constant; // Identity template @@ -53,7 +53,7 @@ struct mp_size_impl {}; template class L, typename... T> // Template template parameter must use class struct mp_size_impl> { - using type = boost::math::integral_constant; + using type = BOOST_MATH_NAMESPACE::integral_constant; }; } @@ -79,7 +79,7 @@ namespace detail { // At // TODO - Use tree based lookup for larger typelists // http://odinthenerd.blogspot.com/2017/04/tree-based-lookup-why-kvasirmpl-is.html -template +template struct mp_at_c {}; template class L, typename T0, typename... T> @@ -168,7 +168,7 @@ struct mp_at_c, 1 }; } -template +template using mp_at_c = typename detail::mp_at_c::type; template @@ -339,8 +339,8 @@ using mp_remove_if_q = mp_remove_if; template struct integer_sequence {}; -template -using index_sequence = integer_sequence; +template +using index_sequence = integer_sequence; namespace detail { @@ -412,12 +412,12 @@ struct make_integer_sequence_impl template using make_integer_sequence = typename detail::make_integer_sequence_impl::type; -template -using make_index_sequence = make_integer_sequence; +template +using make_index_sequence = make_integer_sequence; template -using index_sequence_for = make_integer_sequence; +using index_sequence_for = make_integer_sequence; -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_MP diff --git a/include/boost/math/tools/norms.hpp b/include/boost/math/tools/norms.hpp index 3be45f14c4..2fffbbb602 100644 --- a/include/boost/math/tools/norms.hpp +++ b/include/boost/math/tools/norms.hpp @@ -5,10 +5,12 @@ #ifndef BOOST_MATH_TOOLS_NORMS_HPP #define BOOST_MATH_TOOLS_NORMS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #include #include @@ -21,10 +23,10 @@ #endif -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { // Mallat, "A Wavelet Tour of Signal Processing", equation 2.60: -template +BOOST_MATH_EXPORT template auto total_variation(ForwardIterator first, ForwardIterator last) { using T = typename std::iterator_traits::value_type; @@ -74,20 +76,20 @@ auto total_variation(ForwardIterator first, ForwardIterator last) } } -template +BOOST_MATH_EXPORT template inline auto total_variation(Container const & v) { return total_variation(v.cbegin(), v.cend()); } -template +BOOST_MATH_EXPORT template auto sup_norm(ForwardIterator first, ForwardIterator last) { BOOST_MATH_ASSERT_MSG(first != last, "At least one value is required to compute the sup norm."); using T = typename std::iterator_traits::value_type; using std::abs; - if constexpr (boost::math::tools::is_complex_type::value) + if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { auto it = std::max_element(first, last, [](T a, T b) { return abs(b) > abs(a); }); return abs(*it); @@ -110,13 +112,13 @@ auto sup_norm(ForwardIterator first, ForwardIterator last) } } -template +BOOST_MATH_EXPORT template inline auto sup_norm(Container const & v) { return sup_norm(v.cbegin(), v.cend()); } -template +BOOST_MATH_EXPORT template auto l1_norm(ForwardIterator first, ForwardIterator last) { using T = typename std::iterator_traits::value_type; @@ -152,14 +154,14 @@ auto l1_norm(ForwardIterator first, ForwardIterator last) } -template +BOOST_MATH_EXPORT template inline auto l1_norm(Container const & v) { return l1_norm(v.cbegin(), v.cend()); } -template +BOOST_MATH_EXPORT template auto l2_norm(ForwardIterator first, ForwardIterator last) { using T = typename std::iterator_traits::value_type; @@ -168,7 +170,7 @@ auto l2_norm(ForwardIterator first, ForwardIterator last) using std::sqrt; using std::is_floating_point; using std::isfinite; - if constexpr (boost::math::tools::is_complex_type::value) + if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { typedef typename T::value_type Real; Real l2 = 0; @@ -228,13 +230,13 @@ auto l2_norm(ForwardIterator first, ForwardIterator last) } } -template +BOOST_MATH_EXPORT template inline auto l2_norm(Container const & v) { return l2_norm(v.cbegin(), v.cend()); } -template +BOOST_MATH_EXPORT template size_t l0_pseudo_norm(ForwardIterator first, ForwardIterator last) { using RealOrComplex = typename std::iterator_traits::value_type; @@ -249,13 +251,13 @@ size_t l0_pseudo_norm(ForwardIterator first, ForwardIterator last) return count; } -template +BOOST_MATH_EXPORT template inline size_t l0_pseudo_norm(Container const & v) { return l0_pseudo_norm(v.cbegin(), v.cend()); } -template +BOOST_MATH_EXPORT template size_t hamming_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator first2) { size_t count = 0; @@ -271,13 +273,13 @@ size_t hamming_distance(ForwardIterator first1, ForwardIterator last1, ForwardIt return count; } -template +BOOST_MATH_EXPORT template inline size_t hamming_distance(Container const & v, Container const & w) { return hamming_distance(v.cbegin(), v.cend(), w.cbegin()); } -template +BOOST_MATH_EXPORT template auto lp_norm(ForwardIterator first, ForwardIterator last, unsigned p) { using std::abs; @@ -285,7 +287,7 @@ auto lp_norm(ForwardIterator first, ForwardIterator last, unsigned p) using std::is_floating_point; using std::isfinite; using RealOrComplex = typename std::iterator_traits::value_type; - if constexpr (boost::math::tools::is_complex_type::value) + if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { using std::norm; using Real = typename RealOrComplex::value_type; @@ -298,8 +300,8 @@ auto lp_norm(ForwardIterator first, ForwardIterator last, unsigned p) auto result = pow(lp, Real(1)/Real(p)); if (!isfinite(result)) { - auto a = boost::math::tools::sup_norm(first, last); - Real lp = 0; + auto a = BOOST_MATH_NAMESPACE::tools::sup_norm(first, last); + lp = 0; for (auto it = first; it != last; ++it) { lp += pow(abs(*it)/a, p); @@ -321,7 +323,7 @@ auto lp_norm(ForwardIterator first, ForwardIterator last, unsigned p) RealOrComplex result = pow(lp, RealOrComplex(1)/RealOrComplex(p)); if (!isfinite(result)) { - RealOrComplex a = boost::math::tools::sup_norm(first, last); + RealOrComplex a = BOOST_MATH_NAMESPACE::tools::sup_norm(first, last); lp = 0; for (auto it = first; it != last; ++it) { @@ -343,7 +345,7 @@ auto lp_norm(ForwardIterator first, ForwardIterator last, unsigned p) double result = pow(lp, 1.0/static_cast(p)); if (!isfinite(result)) { - double a = boost::math::tools::sup_norm(first, last); + double a = BOOST_MATH_NAMESPACE::tools::sup_norm(first, last); lp = 0; for (auto it = first; it != last; ++it) { @@ -356,14 +358,14 @@ auto lp_norm(ForwardIterator first, ForwardIterator last, unsigned p) } } -template +BOOST_MATH_EXPORT template inline auto lp_norm(Container const & v, unsigned p) { return lp_norm(v.cbegin(), v.cend(), p); } -template +BOOST_MATH_EXPORT template auto lp_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator first2, unsigned p) { using std::pow; @@ -374,7 +376,7 @@ auto lp_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator auto it1 = first1; auto it2 = first2; - if constexpr (boost::math::tools::is_complex_type::value) + if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { using Real = typename RealOrComplex::value_type; using std::norm; @@ -412,14 +414,14 @@ auto lp_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator } } -template +BOOST_MATH_EXPORT template inline auto lp_distance(Container const & v, Container const & w, unsigned p) { return lp_distance(v.cbegin(), v.cend(), w.cbegin(), p); } -template +BOOST_MATH_EXPORT template auto l1_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator first2) { using std::abs; @@ -428,7 +430,7 @@ auto l1_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator using T = typename std::iterator_traits::value_type; auto it1 = first1; auto it2 = first2; - if constexpr (boost::math::tools::is_complex_type::value) + if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { using Real = typename T::value_type; Real sum = 0; @@ -482,7 +484,7 @@ auto l1_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator } -template +BOOST_MATH_EXPORT template auto l1_distance(Container const & v, Container const & w) { using std::size; @@ -491,7 +493,7 @@ auto l1_distance(Container const & v, Container const & w) return l1_distance(v.cbegin(), v.cend(), w.begin()); } -template +BOOST_MATH_EXPORT template auto l2_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator first2) { using std::abs; @@ -502,7 +504,7 @@ auto l2_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator using T = typename std::iterator_traits::value_type; auto it1 = first1; auto it2 = first2; - if constexpr (boost::math::tools::is_complex_type::value) + if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { using Real = typename T::value_type; Real sum = 0; @@ -555,7 +557,7 @@ auto l2_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator } } -template +BOOST_MATH_EXPORT template auto l2_distance(Container const & v, Container const & w) { using std::size; @@ -564,7 +566,7 @@ auto l2_distance(Container const & v, Container const & w) return l2_distance(v.cbegin(), v.cend(), w.begin()); } -template +BOOST_MATH_EXPORT template auto sup_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator first2) { using std::abs; @@ -575,7 +577,7 @@ auto sup_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator using T = typename std::iterator_traits::value_type; auto it1 = first1; auto it2 = first2; - if constexpr (boost::math::tools::is_complex_type::value) + if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { using Real = typename T::value_type; Real sup_sq = 0; @@ -624,7 +626,7 @@ auto sup_distance(ForwardIterator first1, ForwardIterator last1, ForwardIterator } } -template +BOOST_MATH_EXPORT template auto sup_distance(Container const & v, Container const & w) { using std::size; @@ -634,5 +636,5 @@ auto sup_distance(Container const & v, Container const & w) } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/numeric_limits.hpp b/include/boost/math/tools/numeric_limits.hpp index 87a7802363..5ec211ebe0 100644 --- a/include/boost/math/tools/numeric_limits.hpp +++ b/include/boost/math/tools/numeric_limits.hpp @@ -19,17 +19,18 @@ #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif #endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -template +BOOST_MATH_EXPORT template struct numeric_limits #ifndef BOOST_MATH_HAS_NVRTC : public std::numeric_limits {}; @@ -882,7 +883,6 @@ struct numeric_limits #endif // BOOST_MATH_HAS_GPU_SUPPORT -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/polynomial.hpp b/include/boost/math/tools/polynomial.hpp index 5d395cdbed..560601899f 100644 --- a/include/boost/math/tools/polynomial.hpp +++ b/include/boost/math/tools/polynomial.hpp @@ -22,16 +22,18 @@ #include #include +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include #include #include +#endif -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T chebyshev_coefficient(unsigned n, unsigned m) { BOOST_MATH_STD_USING @@ -50,12 +52,12 @@ BOOST_MATH_GPU_ENABLED T chebyshev_coefficient(unsigned n, unsigned m) if(r & 1) result = -result; result /= n - r; - result *= boost::math::binomial_coefficient(n - r, r); + result *= BOOST_MATH_NAMESPACE::binomial_coefficient(n - r, r); result *= ldexp(1.0f, m); return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED Seq polynomial_to_chebyshev(const Seq& s) { // Converts a Polynomial into Chebyshev form: @@ -91,7 +93,7 @@ BOOST_MATH_GPU_ENABLED Seq polynomial_to_chebyshev(const Seq& s) return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED T evaluate_chebyshev(const Seq& a, const T& x) { // Clenshaw's formula: @@ -109,7 +111,7 @@ BOOST_MATH_GPU_ENABLED T evaluate_chebyshev(const Seq& a, const T& x) } -template +BOOST_MATH_EXPORT template class polynomial; namespace detail { @@ -247,13 +249,13 @@ struct minus /** * Returns the zero element for multiplication of polynomials. */ -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED polynomial zero_element(std::multiplies< polynomial >) { return polynomial(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED polynomial identity_element(std::multiplies< polynomial >) { return polynomial(T(1)); @@ -263,7 +265,7 @@ BOOST_MATH_GPU_ENABLED polynomial identity_element(std::multiplies< polynomia * because the same amount of computation yields both. * This function is not defined for division by zero: user beware. */ -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED std::pair< polynomial, polynomial > quotient_remainder(const polynomial& dividend, const polynomial& divisor) { @@ -274,7 +276,7 @@ quotient_remainder(const polynomial& dividend, const polynomial& divisor) } -template +BOOST_MATH_EXPORT template class polynomial { public: @@ -286,6 +288,7 @@ class polynomial BOOST_MATH_GPU_ENABLED polynomial()= default; template + [[deprecated("Please use the move constructor instead, or pass the order instead of number of terms")]] BOOST_MATH_GPU_ENABLED polynomial(const U* data, unsigned order) : m_data(data, data + order + 1) { @@ -332,11 +335,11 @@ class polynomial m_data.resize(p.size()); for(unsigned i = 0; i < p.size(); ++i) { - m_data[i] = boost::math::tools::real_cast(p[i]); + m_data[i] = BOOST_MATH_NAMESPACE::tools::real_cast(p[i]); } } #ifdef BOOST_MATH_HAS_IS_CONST_ITERABLE - template ::value, bool>::type = true> + template ::value, bool>::type = true> BOOST_MATH_GPU_ENABLED explicit polynomial(const Range& r) : polynomial(r.begin(), r.end()) { @@ -379,7 +382,7 @@ class polynomial BOOST_MATH_GPU_ENABLED T operator()(T z) const { - return m_data.size() > 0 ? boost::math::tools::evaluate_polynomial((m_data).data(), z, m_data.size()) : T(0); + return m_data.size() > 0 ? BOOST_MATH_NAMESPACE::tools::evaluate_polynomial((m_data).data(), z, m_data.size()) : T(0); } BOOST_MATH_GPU_ENABLED std::vector chebyshev() const { @@ -476,10 +479,10 @@ class polynomial } template - BOOST_MATH_GPU_ENABLED typename std::enable_if::value, polynomial&>::type operator %=(const U& /*value*/) + BOOST_MATH_GPU_ENABLED typename std::enable_if::value, polynomial&>::type operator %=(const U& value) { - // We can always divide by a scalar, so there is no remainder: - this->set_zero(); + scalar_remainder(value, std::integral_constant::is_integer>()); + normalize(); return *this; } @@ -537,7 +540,7 @@ class polynomial template BOOST_MATH_GPU_ENABLED polynomial& operator >>=(U const &n) { - BOOST_MATH_ASSERT(n <= m_data.size()); + BOOST_MATH_ASSERT(static_cast(n) <= m_data.size()); m_data.erase(m_data.begin(), m_data.begin() + n); return *this; } @@ -633,11 +636,26 @@ class polynomial return *this; } + template + BOOST_MATH_GPU_ENABLED void scalar_remainder(const U& value, std::true_type) + { + // Copy in case value aliases one of our coefficients: + const U v = value; + std::transform(m_data.begin(), m_data.end(), m_data.begin(), [&](const T& x)->T { return static_cast(x % v); }); + } + + template + BOOST_MATH_GPU_ENABLED void scalar_remainder(const U&, std::false_type) + { + // Over a field we can always divide by a scalar, so there is no remainder: + this->set_zero(); + } + std::vector m_data; }; -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator + (const polynomial& a, const polynomial& b) { polynomial result(a); @@ -645,26 +663,26 @@ BOOST_MATH_GPU_ENABLED inline polynomial operator + (const polynomial& a, return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator + (polynomial&& a, const polynomial& b) { a += b; return std::move(a); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator + (const polynomial& a, polynomial&& b) { b += a; return b; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator + (polynomial&& a, polynomial&& b) { a += b; return a; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator - (const polynomial& a, const polynomial& b) { polynomial result(a); @@ -672,26 +690,26 @@ BOOST_MATH_GPU_ENABLED inline polynomial operator - (const polynomial& a, return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator - (polynomial&& a, const polynomial& b) { a -= b; return a; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator - (const polynomial& a, polynomial&& b) { b -= a; return -b; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator - (polynomial&& a, polynomial&& b) { a -= b; return a; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator * (const polynomial& a, const polynomial& b) { polynomial result; @@ -699,94 +717,94 @@ BOOST_MATH_GPU_ENABLED inline polynomial operator * (const polynomial& a, return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator / (const polynomial& a, const polynomial& b) { return quotient_remainder(a, b).first; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline polynomial operator % (const polynomial& a, const polynomial& b) { return quotient_remainder(a, b).second; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename std::enable_if::value, polynomial >::type operator + (polynomial a, const U& b) { a += b; return a; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename std::enable_if::value, polynomial >::type operator - (polynomial a, const U& b) { a -= b; return a; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename std::enable_if::value, polynomial >::type operator * (polynomial a, const U& b) { a *= b; return a; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename std::enable_if::value, polynomial >::type operator / (polynomial a, const U& b) { a /= b; return a; } -template -BOOST_MATH_GPU_ENABLED inline typename std::enable_if::value, polynomial >::type operator % (const polynomial&, const U&) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename std::enable_if::value, polynomial >::type operator % (polynomial a, const U& b) { - // Since we can always divide by a scalar, result is always an empty polynomial: - return polynomial(); + a %= b; + return a; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename std::enable_if::value, polynomial >::type operator + (const U& a, polynomial b) { b += a; return b; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename std::enable_if::value, polynomial >::type operator - (const U& a, polynomial b) { b -= a; return -b; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename std::enable_if::value, polynomial >::type operator * (const U& a, polynomial b) { b *= a; return b; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED bool operator == (const polynomial &a, const polynomial &b) { return a.data() == b.data(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED bool operator != (const polynomial &a, const polynomial &b) { return a.data() != b.data(); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED polynomial operator >> (polynomial a, const U& b) { a >>= b; return a; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED polynomial operator << (polynomial a, const U& b) { a <<= b; @@ -794,26 +812,26 @@ BOOST_MATH_GPU_ENABLED polynomial operator << (polynomial a, const U& b) } // Unary minus (negate). -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED polynomial operator - (polynomial a) { std::transform(a.data().begin(), a.data().end(), a.data().begin(), detail::negate()); return a; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED bool odd(polynomial const &a) { return a.size() > 0 && a[0] != static_cast(0); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED bool even(polynomial const &a) { return !odd(a); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED polynomial pow(polynomial base, int exp) { if (exp < 0) @@ -837,7 +855,7 @@ BOOST_MATH_GPU_ENABLED polynomial pow(polynomial base, int exp) return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline std::basic_ostream& operator << (std::basic_ostream& os, const polynomial& poly) { os << "{ "; @@ -851,8 +869,7 @@ BOOST_MATH_GPU_ENABLED inline std::basic_ostream& operator << (st } } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END // // Polynomial specific overload of gcd algorithm: diff --git a/include/boost/math/tools/polynomial_gcd.hpp b/include/boost/math/tools/polynomial_gcd.hpp index 4a213e127a..03010f28e0 100644 --- a/include/boost/math/tools/polynomial_gcd.hpp +++ b/include/boost/math/tools/polynomial_gcd.hpp @@ -11,8 +11,10 @@ #pragma once #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include @@ -20,9 +22,11 @@ #include #else +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include @@ -83,17 +87,18 @@ namespace boost{ struct gcd_traits; template - struct gcd_traits > + struct gcd_traits > { - inline static const boost::math::tools::polynomial& abs(const boost::math::tools::polynomial& val) { return val; } + inline static const BOOST_MATH_NAMESPACE::tools::polynomial& abs(const BOOST_MATH_NAMESPACE::tools::polynomial& val) { return val; } static const method_type method = method_euclid; }; } } +} -namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools { /* From Knuth, 4.6.1: * @@ -251,18 +256,18 @@ gcd(polynomial const &u, polynomial const &v) // // Using declaration so we overload the default implementation in this namespace: // -using boost::math::tools::gcd; +using BOOST_MATH_NAMESPACE::tools::gcd; -} +BOOST_MATH_NAMESPACE_END +namespace boost { namespace integer { // // Using declaration so we overload the default implementation in this namespace: // - using boost::math::tools::gcd; + using BOOST_MATH_NAMESPACE::tools::gcd; +} } - -} // namespace boost::math::tools #endif diff --git a/include/boost/math/tools/polynomial_roots.hpp b/include/boost/math/tools/polynomial_roots.hpp new file mode 100644 index 0000000000..8d28463276 --- /dev/null +++ b/include/boost/math/tools/polynomial_roots.hpp @@ -0,0 +1,1101 @@ +// Copyright Nick Thompson 2026. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_TOOLS_POLYNOMIAL_ROOTS_HPP +#define BOOST_MATH_TOOLS_POLYNOMIAL_ROOTS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +BOOST_MATH_NAMESPACE_BEGIN namespace tools { +namespace polynomial_roots_detail { + + +template +inline Real log2_abs(Real x) +{ + using std::abs; + using std::log2; + return x == 0 ? std::numeric_limits::infinity() : -log2(abs(x)); +} + +template +struct hull_point +{ + std::size_t index; + Real height; +}; + +template +inline Real slope(hull_point const& a, hull_point const& b) +{ + return (b.height - a.height) / Real(b.index - a.index); +} + +template +std::vector > lower_newton_hull(std::vector const& a) +{ + std::vector > hull; + hull.reserve(a.size()); + for(std::size_t j = 0; j < a.size(); ++j) + { + if(a[j] == 0) + continue; + hull_point p{j, log2_abs(a[j])}; + while(hull.size() >= 2 && + slope(hull[hull.size() - 2], hull.back()) >= slope(hull.back(), p)) + hull.pop_back(); + hull.push_back(p); + } + return hull; +} + +template +std::vector hull_heights(std::vector > const& hull, + std::size_t degree) +{ + std::vector heights(degree + 1); + std::size_t edge = 0; + for(std::size_t j = 0; j <= degree; ++j) + { + while(edge + 1 < hull.size() && j > hull[edge + 1].index) + ++edge; + if(j == hull[edge].index || edge + 1 == hull.size()) + heights[j] = hull[edge].height; + else + { + Real t = Real(j - hull[edge].index) / + Real(hull[edge + 1].index - hull[edge].index); + heights[j] = hull[edge].height + + t * (hull[edge + 1].height - hull[edge].height); + } + } + return heights; +} + +template +struct radial_piece +{ + Real log2_inner; + Real log2_outer; + std::size_t lower; + std::size_t upper; +}; + +template +std::vector > make_radial_pieces(std::vector const& a, + unsigned precision) +{ + std::size_t d = a.size() - 1; + if(d == 1) + return {{radial_piece{-std::numeric_limits::infinity(), + std::numeric_limits::infinity(), 0, 1}}}; + auto hull = lower_newton_hull(a); + auto heights = hull_heights(hull, d); + Real m = static_cast(precision); + std::vector lower_slope(d + 1), upper_slope(d + 1); + upper_slope[0] = -std::numeric_limits::infinity(); + lower_slope[d] = std::numeric_limits::infinity(); + for(std::size_t j = 0; j <= d; ++j) + { + // The two supporting lines through (j, H(j)-m) touch the Newton + // polygon on opposite sides of j. Computing them from hull vertices + // also handles absent coefficients without manufacturing finite + // logarithms for them. + Real shifted = heights[j] - m; + if(j != 0) + { + Real high = -std::numeric_limits::infinity(); + for(auto const& p : hull) + if(p.index < j) + high = (std::max)(high, (shifted - p.height) / + Real(j - p.index)); + upper_slope[j] = high; + } + if(j != d) + { + Real low = std::numeric_limits::infinity(); + for(auto const& p : hull) + if(p.index > j) + low = (std::min)(low, (p.height - shifted) / + Real(p.index - j)); + lower_slope[j] = low; + } + } + + // Finite Fujiwara bounds avoid the degenerate start == end sweep for + // sparse polynomials such as x^d-1. + using std::abs; + using std::log2; + Real log_a0 = log2(abs(a[0])); + Real log_ad = log2(abs(a[d])); + Real start = std::numeric_limits::infinity(); + Real finish = -std::numeric_limits::infinity(); + for(std::size_t i = 1; i <= d; ++i) + { + if(a[i] != 0) + start = (std::min)(start, + (log_a0 - log2(abs(a[i]))) / Real(i)); + if(a[d - i] != 0) + finish = (std::max)(finish, + (log2(abs(a[d - i])) - log_ad) / Real(i)); + } + start -= Real(1); + finish += Real(1); + std::vector > pieces; + std::size_t first_upper = 1; + while(first_upper <= d && start > upper_slope[first_upper]) + ++first_upper; + first_upper = (std::min)(first_upper, d); + pieces.push_back({-std::numeric_limits::infinity(), start, 0, first_upper}); + Real s = start; + std::size_t previous_lower = 0; + std::size_t previous_upper = first_upper; + std::size_t guard = 0; + while(s < finish && guard++ < 66 * d + 16) + { + std::size_t l = previous_lower; + while(l < d && !(lower_slope[l] > s)) + ++l; + std::size_t u = (std::max)(l, previous_upper); + while(u < d && (upper_slope[u] - s) < m / Real(u - l + 1)) + ++u; + Real next = s + m / Real(u - l + 1); + if(!(next > s)) + next = BOOST_MATH_NAMESPACE::float_next(s); + pieces.push_back({s, next, l, u}); + previous_lower = l; + previous_upper = u; + s = next; + } + std::size_t last_lower = previous_lower; + while(last_lower < d && !(lower_slope[last_lower] > s)) + ++last_lower; + pieces.push_back({s, std::numeric_limits::infinity(), last_lower, d}); + return pieces; +} + +// The Newton correction p(z)/p'(z). For |z| > 1 Horner would overflow at high degree, so it uses the +// reversed polynomial q(w) = w^n p(1/w), w = 1/z: p/p' = z / (n - w q'(w) / q(w)). Returns zero where +// p'(z) vanishes and p(z) does not, so callers take no step there. +template +Complex newton_correction(std::vector const& a, Complex z) +{ + using std::abs; + using complex_type = Complex; + using Real = detail::real_from_complex_t; + std::size_t n = a.size() - 1; + if(abs(z) <= 1) + { + complex_type f(a[n]), df(0, 0); + for(std::size_t i = n; i-- > 0;) + { + df = df * z + f; + f = f * z + complex_type(a[i]); + } + if(f == complex_type(0, 0)) + return f; + return df == complex_type(0, 0) ? complex_type(0, 0) : f / df; + } + complex_type w = Real(1) / z; + complex_type q(a[0]), dq(0, 0); + for(std::size_t i = 1; i <= n; ++i) + { + dq = dq * w + q; + q = q * w + complex_type(a[i]); + } + if(q == complex_type(0, 0)) + return q; + complex_type denominator = Real(n) - w * dq / q; + return denominator == complex_type(0, 0) ? complex_type(0, 0) : z / denominator; +} + +// All roots of the polynomial a by Aberth's method. Only the roots inside |z| <= interest are wanted +// (the default wants all): a root still moving well outside that disc after a sweep is a root of a +// truncated Taylor polynomial that the caller will discard, so it is frozen rather than iterated. +// |p(z)| / sum |a_i| |z|^i, the backward error of z as a root. For |z| > 1 the same ratio is formed from +// the reversed polynomial in w = 1/z, so that neither sum overflows. +template +detail::real_from_complex_t scaled_residual(std::vector const& a, Complex z) +{ + using std::abs; + using Real = detail::real_from_complex_t; + std::size_t n = a.size() - 1; + bool reversed = abs(z) > 1; + Complex x = reversed ? Complex(Real(1) / z) : z; + Real ax = abs(x); + Complex f(reversed ? a[0] : a[n]); + Real scale = abs(f); + for(std::size_t i = 1; i <= n; ++i) + { + Coefficient c = reversed ? a[i] : a[n - i]; + f = f * x + c; + scale = scale * ax + abs(c); + } + return abs(f) / ((std::max)(scale, tools::min_value())); +} + +template +std::vector aberth(std::vector a, + detail::real_from_complex_t interest = std::numeric_limits >::infinity()) +{ + using std::abs; + using std::log; + using std::log2; + using std::exp; + using std::exp2; + using std::fmod; + using std::cos; + using std::sin; + using Real = detail::real_from_complex_t; + while(a.size() > 1 && abs(a.back()) == 0) + a.pop_back(); + std::size_t n = a.size() - 1; + if(n == 0) + return {}; + if(n == 1) + return {-a[0] / a[1]}; + Complex leading = a.back(); + Real log_leading = log(abs(leading)); + Real log_radius = -std::numeric_limits::infinity(); + for(std::size_t i = 0; i < n; ++i) + if(a[i] != Complex(0, 0)) + log_radius = (std::max)(log_radius, + (log(abs(a[i])) - log_leading) / Real(n - i)); + // Fujiwara's bound is far tighter than 1+max|a_i/a_n| for a + // translated high-degree polynomial, and computing it logarithmically + // prevents the initial circle itself from overflowing. + Real radius = Real(2) * exp(log_radius); + if(!(radius > 0) || !(BOOST_MATH_NAMESPACE::isfinite)(radius)) + radius = Real(1); + Real pi = BOOST_MATH_NAMESPACE::constants::pi(); + std::vector roots(n); + std::vector > polygon; + for(std::size_t i = 0; i <= n; ++i) + if(a[i] != Complex(0, 0)) + { + hull_point p{i, -log2(abs(a[i]))}; + while(polygon.size() >= 2 && + slope(polygon[polygon.size() - 2], polygon.back()) >= + slope(polygon.back(), p)) + polygon.pop_back(); + polygon.push_back(p); + } + std::size_t root_index = 0; + for(std::size_t edge = 1; edge < polygon.size(); ++edge) + { + std::size_t count = polygon[edge].index - polygon[edge - 1].index; + Real edge_radius = exp2(slope(polygon[edge - 1], polygon[edge])); + if(!(edge_radius > 0) || !(BOOST_MATH_NAMESPACE::isfinite)(edge_radius)) + edge_radius = radius; + for(std::size_t k = 0; k < count; ++k, ++root_index) + { + Real scramble = fmod(Real(root_index + 1) * Real(0.6180339887498948482), Real(1)); + Real angle = Real(2) * pi * + (Real(k) + Real(0.25) + Real(edge) / Real(polygon.size()) + + Real(0.2) * scramble) / Real(count); + Real radial_jitter = Real(0.95) + Real(0.1) * scramble; + roots[root_index] = radial_jitter * edge_radius * + Complex(cos(angle), sin(angle)); + } + } + Real eps = tools::epsilon(); + // A root whose last correction was negligible is frozen: it still repels the others but is no longer + // updated. Each sweep then costs O(n * active) instead of O(n^2). + const bool global = !(BOOST_MATH_NAMESPACE::isfinite)(interest); + const Real acceptable = Real(16) * Real(n) * eps; + std::vector last_acceptable(global ? n : 0); + std::vector has_acceptable(global ? n : 0, 0); + std::vector active(n, 1); + std::size_t remaining = n; + // Simple roots converge in a few sweeps; a cluster of multiplicity m only linearly, at a rate of about + // 1 - 1/m. The global fallback (no disc of interest) is what such clusters reach, so it gets a far + // larger budget, which costs little because converged roots are frozen. + unsigned max_iterations = 20 + static_cast(log2(Real(n))); + if(!(BOOST_MATH_NAMESPACE::isfinite)(interest)) + max_iterations = 400 + static_cast(log2(Real(n))); + for(unsigned iteration = 0; iteration < max_iterations && remaining; ++iteration) + { + for(std::size_t i = 0; i < n; ++i) + { + if(!active[i]) + continue; + Complex newton = newton_correction(a, roots[i]); + // sum 1/(z_i - z_j) in real arithmetic: 1/d = conj(d)/|d|^2, without the library's slow + // general-purpose complex division. + Real repulsion_re = 0, repulsion_im = 0; + Real xi = roots[i].real(), yi = roots[i].imag(); + for(std::size_t j = 0; j < n; ++j) + { + Real dx = xi - roots[j].real(), dy = yi - roots[j].imag(); + Real norm = dx * dx + dy * dy; + if(j != i && norm > 0) + { + repulsion_re += dx / norm; + repulsion_im -= dy / norm; + } + } + Complex repulsion(repulsion_re, repulsion_im); + Complex denominator = Real(1) - newton * repulsion; + Complex correction = denominator == Complex(0, 0) + ? newton : newton / denominator; + // One non-finite root would poison every other root through the repulsion sum. + if(!(BOOST_MATH_NAMESPACE::isfinite)(correction.real()) || !(BOOST_MATH_NAMESPACE::isfinite)(correction.imag())) + correction = newton; + if(!(BOOST_MATH_NAMESPACE::isfinite)(correction.real()) || !(BOOST_MATH_NAMESPACE::isfinite)(correction.imag())) + continue; + roots[i] -= correction; + // A root stops once its step is negligible. In the global fallback, which is where multiple roots + // end up, a small step can be noise long before z is acceptable, so there it must also pass the + // backward-error test the caller accepts roots by; the last iterate that passed is kept in case the + // noise carries the root out again. + bool converged = abs(correction) <= Real(4) * eps * abs(roots[i]); + if(global) + { + bool acceptable_now = scaled_residual(a, roots[i]) <= acceptable; + if(acceptable_now) + { + last_acceptable[i] = roots[i]; + has_acceptable[i] = 1; + } + converged = converged && acceptable_now; + } + if(converged || (iteration >= 2 && abs(roots[i]) > Real(2) * interest)) + { + active[i] = 0; + --remaining; + } + } + // Done once every root still moving lies well outside the disc of interest. + if(iteration >= 2 && (BOOST_MATH_NAMESPACE::isfinite)(interest)) + { + bool wanted_moving = false; + for(std::size_t i = 0; i < n && !wanted_moving; ++i) + wanted_moving = active[i] && abs(roots[i]) <= Real(1.25) * interest; + if(!wanted_moving) + break; + } + } + if(global) + for(std::size_t i = 0; i < n; ++i) + if(has_acceptable[i] && !(scaled_residual(a, roots[i]) <= acceptable)) + roots[i] = last_acceptable[i]; + return roots; +} + +template +detail::complex_from_real_t root_of_unity(std::size_t k, std::size_t n) +{ + using std::cos; + using std::sin; + Real angle = Real(2) * BOOST_MATH_NAMESPACE::constants::pi() * Real(k) / Real(n); + return detail::complex_from_real_t(cos(angle), sin(angle)); +} + + +// The radius n max(|p(z)|, eps sum |a_i| |z|^i) / |p'(z)| of a disc about z that contains a root of p: +// the Newton inclusion radius, floored at the rounding error of evaluating p, which is eps cond(z) |z|. +// Copies of one root found in overlapping sectors have overlapping discs; distinct roots have disjoint +// ones unless they are closer than the data can resolve. For |z| > 1 it uses the reversed polynomial +// q(w) = w^n p(1/w), w = 1/z, where p'(z) = z^(n-1) (n q - w q'). +template +Real inclusion_radius(std::vector const& a, Complex z) +{ + using std::abs; + using complex_type = Complex; + std::size_t n = a.size() - 1; + Real eps = tools::epsilon(); + bool reversed = abs(z) > 1; + complex_type x = reversed ? complex_type(Real(1) / z) : z; + Real ax = abs(x); + complex_type f(reversed ? a[0] : a[n]), df(0, 0); + Real scale = abs(f); + for(std::size_t i = 1; i <= n; ++i) + { + Real c = reversed ? a[i] : a[n - i]; + df = df * x + f; + f = f * x + c; + scale = scale * ax + abs(c); + } + // In the reversed case f, df and scale are q(w), q'(w) and |z|^-n sum |a_i||z|^i, and |p'(z)| is + // |z|^(n-1) |n q - w q'|, so the radius is |z| max(|q|, eps scale) / |n q - w q'|. + Real derivative = reversed ? abs(Real(n) * f - x * df) : abs(df); + Real numerator = (std::max)(Real(abs(f)), Real(eps * scale)) * (reversed ? Real(abs(z)) : Real(1)); + if(!(derivative > 0)) + return std::numeric_limits::infinity(); + return Real(n) * numerator / derivative; +} + +} // namespace polynomial_roots_detail + +namespace polynomial_roots_detail { + +// The piecewise method, with local Taylor expansions to the full precision of Real. +template +std::vector > piecewise(std::vector coefficients) +{ + const unsigned precision = static_cast(tools::digits()); + static_assert(!std::is_integral::value, "polynomial_roots requires a floating-point coefficient type"); + using std::abs; + using std::log2; + using std::exp2; + using std::ceil; + using std::sqrt; + using std::conj; + while(!coefficients.empty() && coefficients.back() == 0) + coefficients.pop_back(); + if(coefficients.empty()) + throw std::domain_error("polynomial_roots: the zero polynomial has no finite root set"); + for(auto coefficient : coefficients) + if(!(BOOST_MATH_NAMESPACE::isfinite)(coefficient)) + throw std::domain_error("polynomial_roots: coefficients must be finite"); + if(coefficients.size() == 1) + return {}; + std::size_t zero_roots = 0; + while(zero_roots + 1 < coefficients.size() && coefficients[zero_roots] == 0) + ++zero_roots; + if(zero_roots) + coefficients.erase(coefficients.begin(), coefficients.begin() + zero_roots); + + using complex_type = detail::complex_from_real_t; + using namespace polynomial_roots_detail; + std::size_t degree = coefficients.size() - 1; + auto pieces = make_radial_pieces(coefficients, precision); + // A local root mapped back to z, with a merge radius (a few Newton steps on the local Taylor polynomial, + // floored at its rounding and truncation error) and its local backward error. + struct candidate { complex_type z; Real radius; Real residual; }; + std::vector candidates; + std::size_t taylor_degree = (std::min)(degree, std::size_t(4) * precision); + Real log_min = log2(tools::min_value()); + Real log_max = log2(tools::max_value()); + + for(auto const& piece : pieces) + { + if(piece.upper <= piece.lower || !(BOOST_MATH_NAMESPACE::isfinite)(piece.log2_inner) || + !(BOOST_MATH_NAMESPACE::isfinite)(piece.log2_outer)) + continue; + Real inner = exp2(piece.log2_inner); + Real outer = exp2(piece.log2_outer); + Real gamma = (inner + outer) / Real(2); + Real rho = Real(0.75) * (outer - inner); + if(!(gamma > 0) || !(rho > 0) || !(BOOST_MATH_NAMESPACE::isfinite)(gamma + rho)) + continue; + std::size_t delta = piece.upper - piece.lower; + std::size_t sectors = static_cast(ceil( + Real(2) * BOOST_MATH_NAMESPACE::constants::pi() * gamma / rho)); + sectors = (std::max)(std::size_t(1), sectors); + std::size_t local_degree = (std::min)(delta, taylor_degree); + + Real log_gamma = log2(gamma); + Real common_log = -std::numeric_limits::infinity(); + for(std::size_t j = piece.lower; j <= piece.upper; ++j) + if(coefficients[j] != 0) + common_log = (std::max)(common_log, + log2(abs(coefficients[j])) + Real(j) * log_gamma); + + std::vector > local( + sectors, std::vector(local_degree + 1)); + std::vector > residues( + local_degree + 1, std::vector(sectors)); + for(std::size_t exponent = piece.lower; exponent <= piece.upper; ++exponent) + { + if(coefficients[exponent] == 0) + continue; + Real log_term = log2(abs(coefficients[exponent])) + + Real(exponent) * log_gamma - common_log; + if(log_term < log_min) + continue; + Real term = BOOST_MATH_NAMESPACE::copysign(Real(exp2((std::min)(log_term, log_max))), + coefficients[exponent]); + std::size_t limit = (std::min)(exponent, local_degree); + for(std::size_t derivative = 0; derivative <= limit; ++derivative) + { + residues[derivative][exponent % sectors] += term; + if(derivative != limit) + term *= (Real(exponent - derivative) / Real(derivative + 1)) * + (rho / gamma); + } + } + // Positive-sign DFT of each derivative's residues, as conj(F(conj(x))). + fft dft(sectors); + for(std::size_t derivative = 0; derivative <= local_degree; ++derivative) + { + auto& values = residues[derivative]; + for(auto& v : values) + v = conj(v); + dft.transform(values); + for(std::size_t k = 0; k < sectors; ++k) + local[k][derivative] = conj(values[k]); + } + for(std::size_t k = 0; k < sectors; ++k) + { + Real coefficient_norm = 0; + for(auto const& coefficient : local[k]) + coefficient_norm += abs(coefficient); + Real discarded = 0; + std::size_t effective_size = local[k].size(); + Real discard_limit = Real(8) * tools::epsilon() * coefficient_norm; + while(effective_size > 1 && + discarded + abs(local[k][effective_size - 1]) <= discard_limit) + { + discarded += abs(local[k][effective_size - 1]); + --effective_size; + } + local[k].resize(effective_size); + auto local_roots = aberth(local[k], Real(1.05)); + complex_type phase = root_of_unity(k, sectors); + for(auto t : local_roots) + { + if(abs(t) > Real(1.05)) + continue; + complex_type local_value = local[k].back(), local_derivative(0, 0); + Real local_scale = abs(local[k].back()); + for(std::size_t q = local[k].size() - 1; q-- > 0;) + { + local_derivative = local_derivative * t + local_value; + local_value = local_value * t + local[k][q]; + local_scale = local_scale * abs(t) + abs(local[k][q]); + } + local_scale = (std::max)(local_scale, tools::min_value()); + if(!(BOOST_MATH_NAMESPACE::isfinite)(local_value.real()) || !(BOOST_MATH_NAMESPACE::isfinite)(local_value.imag()) || + abs(local_value) > sqrt(tools::epsilon()) * local_scale) + continue; + complex_type z = phase * (gamma + rho * t); + Real modulus = abs(z); + if(modulus >= inner * (Real(1) - Real(32) * tools::epsilon()) && + modulus <= outer * (Real(1) + Real(32) * tools::epsilon())) + { + Real error = abs(local_value) + Real(8) * tools::epsilon() * local_scale; + // A few Newton steps' worth: copies of one root agree to about the local accuracy, and the + // guaranteed radius (degree times the step) would also merge neighbouring roots. Copies + // this misses are merged after polishing, with the guaranteed radius on the full polynomial. + Real radius = abs(local_derivative) > 0 + ? Real(4) * error / abs(local_derivative) * rho + : std::numeric_limits::infinity(); + candidates.push_back({z, radius, abs(local_value) / local_scale}); + } + } + } + } + + // Overlapping rings and sectors find most roots many times. Merge two copies when each lies within the + // other's radius (sorted by real part, so there is no branch cut to split a pair), keeping the one with + // the smaller local backward error, so that each root is polished against the full polynomial only + // once. Using the smaller radius keeps a poor candidate from absorbing a good one for a different root. + Real eps = tools::epsilon(); + auto by_real = [](complex_type a, complex_type b) { return a.real() < b.real() || (a.real() == b.real() && a.imag() < b.imag()); }; + candidates.erase(std::remove_if(candidates.begin(), candidates.end(), [](candidate const& c) { + return !(BOOST_MATH_NAMESPACE::isfinite)(c.z.real()) || !(BOOST_MATH_NAMESPACE::isfinite)(c.z.imag()) || !(c.radius < std::numeric_limits::infinity()); }), + candidates.end()); + std::sort(candidates.begin(), candidates.end(), [&](candidate const& a, candidate const& b) { return by_real(a.z, b.z); }); + std::vector representatives; + { + std::vector kept; + for(auto const& c : candidates) + { + bool copy = false; + for(std::size_t k = kept.size(); k-- > 0 && c.z.real() - kept[k].z.real() <= c.radius;) + if(abs(c.z - kept[k].z) <= (std::min)(c.radius, kept[k].radius)) + { + if(c.residual < kept[k].residual) + kept[k] = c; + copy = true; + break; + } + if(!copy) + kept.push_back(c); + } + for(auto const& c : kept) + representatives.push_back(c.z); + } + std::vector& polished = representatives; + + // Polish against the input polynomial, while Newton's steps keep shrinking: near a close neighbour + // a rough local estimate can need more than a handful of iterations. A candidate on which Newton is + // only converging linearly after a few steps is not near a simple root (it is a spurious root of a + // truncated Taylor polynomial); it is left for the residual test below to reject. + auto polish = [&](complex_type& z) + { + Real previous = std::numeric_limits::infinity(); + for(unsigned i = 0; i < 64; ++i) + { + complex_type step = newton_correction(coefficients, z); + Real size = abs(step); + if(!(size < previous)) + break; + z -= step; + if(size <= Real(4) * eps * abs(z) || (i >= 8 && size > previous / 2)) + break; + previous = size; + } + }; + for(auto& z : polished) + polish(z); + + // A root of a truncated local Taylor polynomial need not be a root of the input polynomial: Algorithm 3 + // validates local factors against f and f', and scaled backward error is the floating-point analogue. + // A polished root has a backward error of a few eps even in a cluster; a larger one means Newton has + // not converged, and such a candidate can sit a long way from the root it was headed for. + // Copies of one root are then merged when their Newton inclusion discs overlap, which separates + // distinct roots as finely as their conditioning allows. + struct accepted_root { complex_type z; Real radius; Real residual; }; + std::vector found; + for(auto z : polished) + { + Real residual = scaled_residual(coefficients, z); + if((BOOST_MATH_NAMESPACE::isfinite)(z.real()) && (BOOST_MATH_NAMESPACE::isfinite)(z.imag()) && (BOOST_MATH_NAMESPACE::isfinite)(residual) && + residual <= Real(16) * Real(degree) * eps) + found.push_back({z, inclusion_radius(coefficients, z), residual}); + } + std::sort(found.begin(), found.end(), [&](accepted_root const& a, accepted_root const& b) { return by_real(a.z, b.z); }); + std::vector unique; + Real largest_radius = 0; + for(auto const& c : found) + { + bool copy = false; + for(std::size_t k = unique.size(); k-- > 0 && + c.z.real() - unique[k].z.real() <= c.radius + largest_radius;) + if(abs(c.z - unique[k].z) <= c.radius + unique[k].radius) + { + if(c.residual < unique[k].residual) + unique[k] = c; + copy = true; + break; + } + if(!copy) + { + unique.push_back(c); + largest_radius = (std::max)(largest_radius, c.radius); + } + } + std::vector roots; + roots.reserve(degree + zero_roots); + for(auto const& c : unique) + roots.push_back(c.z); + + // The piecewise algorithm resolves only roots meaningful at the precision of Real. Fall back to a + // global factorization when an ill-conditioned cluster leaves a different number of roots than the degree. + if(roots.size() != degree) + { + roots = aberth(std::vector(coefficients.begin(), coefficients.end())); + // Polish each root, but keep the result only if it is still acceptable or no worse: near a multiple + // root Newton's steps are noise and can move an acceptable root to an unacceptable place. (Comparing + // residuals alone would discard good polishing of simple roots, whose residuals are both rounding.) + const Real acceptable = Real(16) * Real(degree) * eps; + for(auto& z : roots) + { + complex_type candidate = z; + polish(candidate); + Real after = scaled_residual(coefficients, candidate); + if(after <= acceptable || after <= scaled_residual(coefficients, z)) + z = candidate; + } + } + + // The coefficients are real, so the roots are closed under conjugation: an inclusion disc that reaches + // the real axis and overlaps no other root's disc can't hold a non-real root without its conjugate, so + // that root is real. In a cluster the discs overlap and nothing is snapped: a complex pair there would + // otherwise become two reals. + std::vector radii(roots.size()); + for(std::size_t k = 0; k < roots.size(); ++k) + radii[k] = inclusion_radius(coefficients, roots[k]); + std::vector snapped = roots; + for(std::size_t k = 0; k < roots.size(); ++k) + { + complex_type z = roots[k]; + if(z.imag() == 0 || !(abs(z.imag()) <= radii[k])) + continue; + // An imaginary part below the rounding of the real part is noise; a conjugate pair that close + // snaps together. + if(abs(z.imag()) <= eps * abs(z.real())) + { + snapped[k] = complex_type(z.real(), Real(0)); + continue; + } + bool isolated = true; + for(std::size_t j = 0; j < roots.size() && isolated; ++j) + if(j != k && abs(roots[j] - z) <= radii[j] + radii[k]) + isolated = false; + if(isolated && scaled_residual(coefficients, complex_type(z.real(), Real(0))) <= scaled_residual(coefficients, z)) + snapped[k] = complex_type(z.real(), Real(0)); + } + roots.swap(snapped); + roots.insert(roots.end(), zero_roots, complex_type(0, 0)); + return roots; +} + +} // namespace polynomial_roots_detail + + +// Roots of a polynomial as the eigenvalues of its companion matrix, by the companion QR algorithm of +// Aurentz, Mach, Vandebril and Watkins ("Fast and backward stable computation of roots of polynomials", +// SIAM J. Matrix Anal. Appl. 36 (2015); Part II with Robol, SIMAX 39 (2018)): O(n^2) time, O(n) memory, +// backward stable. This is the complex single-shift variant. +// +// The monic companion matrix is A = QR, Q = Q_1 ... Q_{n-1} a product of core transformations (2x2 unitary +// matrices acting on rows i, i+1) and R upper triangular, unitary plus rank one, stored through its +// (n+1)x(n+1) extension Rbar = C^* (B + alpha e_1 y^T) as the core sequences C = C_1 ... C_n and +// B = B_1 ... B_n; y is implied by the zero last row of Rbar and is never formed. All cores are in SU(2), +// [[a, -conj(b)], [b, conj(a)]]. +namespace companion_detail { + + +// The std overloads for the built-in types; argument-dependent lookup finds the multiprecision ones. +using std::abs; +using std::conj; +using std::cos; +using std::exp; +using std::hypot; +using std::log; +using std::sin; +using std::sqrt; + +template +struct core +{ + detail::complex_from_real_t a, b; +}; + +template +inline core > normalized(Complex a, Complex b) +{ + using Real = detail::real_from_complex_t; + Real r = hypot(abs(a), abs(b)); + return r == 0 ? core{Complex(1, 0), Complex(0, 0)} : core{a / r, b / r}; +} + +// The core U with U^* (x1, x2) = (|x|, 0). +template +inline core > eliminating(Complex x1, Complex x2) +{ + return normalized(x1, x2); +} + +template +inline core adjoint(core const& c) +{ + return {conj(c.a), -c.b}; +} + +// c1 c2, both acting on the same rows. +template +inline core fuse(core const& c1, core const& c2) +{ + using complex_type = detail::complex_from_real_t; + return normalized(complex_type(c1.a * c2.a - conj(c1.b) * c2.b), complex_type(c1.b * c2.a + conj(c1.a) * c2.b)); +} + +// F_i G_{i+1} H_i = F'_{i+1} G'_i H'_{i+1}. +template +inline void turnover(core const& F, core const& G, core const& H, + core& Fp, core& Gp, core& Hp) +{ + using C = detail::complex_from_real_t; + // M = F (rows 1,2) * G (rows 2,3) * H (rows 1,2), 3x3. + C f[2][2] = {{F.a, -conj(F.b)}, {F.b, conj(F.a)}}; + C g[2][2] = {{G.a, -conj(G.b)}, {G.b, conj(G.a)}}; + C h[2][2] = {{H.a, -conj(H.b)}, {H.b, conj(H.a)}}; + // FG = F * G + C fg[3][3] = {{f[0][0], f[0][1] * g[0][0], f[0][1] * g[0][1]}, + {f[1][0], f[1][1] * g[0][0], f[1][1] * g[0][1]}, + {C(0), g[1][0], g[1][1]}}; + C m[3][3]; + for(int i = 0; i < 3; ++i) + { + m[i][0] = fg[i][0] * h[0][0] + fg[i][1] * h[1][0]; + m[i][1] = fg[i][0] * h[0][1] + fg[i][1] * h[1][1]; + m[i][2] = fg[i][2]; + } + // F' on rows (2,3) zeroes m[2][0]; G' on rows (1,2) zeroes m[1][0]; what remains is H' on rows (2,3). + Fp = eliminating(m[1][0], m[2][0]); + C fa = conj(Fp.a), fb = conj(Fp.b); + C m1[3][3]; + for(int j = 0; j < 3; ++j) + { + m1[0][j] = m[0][j]; + m1[1][j] = fa * m[1][j] + fb * m[2][j]; + m1[2][j] = -Fp.b * m[1][j] + Fp.a * m[2][j]; + } + Gp = eliminating(m1[0][0], m1[1][0]); + // Column 2 of G'^* m1, rows 2 and 3, is H' e_1. + C h11 = -Gp.b * m1[0][1] + Gp.a * m1[1][1]; + C h21 = m1[2][1]; + Hp = normalized(h11, h21); +} + +template +class companion +{ +public: + using complex_type = detail::complex_from_real_t; + + // Coefficients of a monic polynomial, a_0 ... a_{n-1} (a_n = 1 implied), n >= 2. + explicit companion(std::vector const& a) : n_(a.size()) + { + std::size_t n = n_; + Q_.assign(n - 1, core{complex_type(0, 0), complex_type(1, 0)}); + // R = I except its last column r: r_k = -a_k (k < n), r_n = -a_0 (-1)^(n-1). With Rbar = Y + z e_n^T + // (Y swaps columns n and n+1, with a sign to stay in SU(2)), z = (r, -1); C zeroes z from the bottom. + std::vector z(n + 1); + for(std::size_t k = 1; k < n; ++k) + z[k - 1] = -a[k]; + z[n - 1] = (n % 2 == 1) ? -a[0] : a[0]; + z[n] = complex_type(-1, 0); + C_.resize(n); + for(std::size_t m = n; m-- > 0;) + { + complex_type vm = z[m], vn = z[m + 1]; + Real rho = hypot(abs(vm), abs(vn)); + if(rho == 0) + C_[m] = {complex_type(1, 0), complex_type(0, 0)}; + else + C_[m] = {conj(vm) / rho, -vn / rho}; + z[m] = rho; + z[m + 1] = 0; + } + B_ = C_; + core cn = C_[n - 1]; + B_[n - 1] = {-conj(cn.b), conj(cn.a)}; + } + + std::vector eigenvalues() + { + std::size_t n = n_; + Real eps = tools::epsilon(); + std::size_t hi = n - 1; + unsigned its = 0, restarts = 0; + while(hi > 0) + { + for(std::size_t i = hi; i-- > 0;) + if(abs(Q_[i].b) < eps) + { + Real m = abs(Q_[i].a); + Q_[i] = {m > 0 ? Q_[i].a / m : complex_type(1, 0), complex_type(0, 0)}; + } + std::size_t lo = hi; + while(lo > 0 && Q_[lo - 1].b != complex_type(0, 0)) + --lo; + if(lo == hi) + { + --hi; + its = 0; + continue; + } + if(++its > 30 * (hi - lo + 1)) + throw std::runtime_error("polynomial_roots_companion_matrix: the companion QR iteration did not converge"); + complex_type mu = shift(lo, hi, its, restarts); + step(lo, hi, mu); + } + std::vector lambda(n); + for(std::size_t k = 0; k < n; ++k) + { + complex_type ak = k + 1 < n ? Q_[k].a : complex_type(1, 0); + complex_type akm1 = k > 0 ? Q_[k - 1].a : complex_type(1, 0); + complex_type rkk[3]; + r_column(k, 1, rkk); + lambda[k] = ak * conj(akm1) * rkk[0]; + } + return lambda; + } + +private: + // Entries R_{k,k}, R_{k-1,k}, ... (depth of them) of column k, by back substitution in + // C Rbar e_k = B e_k + alpha y_k e_1, whose rows below the first involve only the cores. + void r_column(std::size_t k, std::size_t depth, complex_type* out) const + { + complex_type beta[4]; + complex_type w = B_[k].a; + beta[0] = B_[k].b; // row k+1 + std::size_t d = 1; + for(std::size_t m = k; m-- > 0 && d < depth;) + { + beta[d++] = conj(B_[m].a) * w; // row m+1 + w = -conj(B_[m].b) * w; + } + complex_type u(0, 0); + for(std::size_t j = 0; j < depth && j <= k; ++j) + { + std::size_t m = k - j; + complex_type v = (beta[j] - conj(C_[m].a) * u) / C_[m].b; + out[j] = v; + u = C_[m].a * v - conj(C_[m].b) * u; + } + } + + // R G_i = G'_i R', i <= n - 2. + core pass_through(std::size_t i, core const& G) + { + core Gt, Gp, c1, c0; + turnover(B_[i], B_[i + 1], G, Gt, B_[i], B_[i + 1]); + turnover(adjoint(C_[i + 1]), adjoint(C_[i]), Gt, Gp, c1, c0); + C_[i + 1] = adjoint(c1); + C_[i] = adjoint(c0); + return Gp; + } + + complex_type shift(std::size_t lo, std::size_t hi, unsigned its, unsigned& restarts) const + { + complex_type col_hi[3] = {}, col_h1[3] = {}; + r_column(hi, 3, col_hi); + r_column(hi - 1, 2, col_h1); + // R entries by (row, column) relative to hi: col_hi[j] = R_{hi-j, hi}, col_h1[j] = R_{hi-1-j, hi-1}. + complex_type dq = hi + 1 < n_ ? Q_[hi].a : complex_type(1, 0); + core q1 = Q_[hi - 1]; + auto rows = [&](complex_type x_hm2, complex_type x_hm1, complex_type x_hi, complex_type& y_hm1, complex_type& y_hi) + { + x_hi *= dq; + y_hm1 = q1.a * x_hm1 - conj(q1.b) * x_hi; + y_hi = q1.b * x_hm1 + conj(q1.a) * x_hi; + if(hi >= 2) + { + core q2 = Q_[hi - 2]; + y_hm1 = hi - 2 >= lo ? complex_type(q2.b * x_hm2 + conj(q2.a) * y_hm1) : complex_type(conj(q2.a) * y_hm1); + } + }; + complex_type p, q, s, t; + rows(hi >= 2 ? col_h1[1] : complex_type(0), col_h1[0], complex_type(0), p, q); + rows(hi >= 2 ? col_hi[2] : complex_type(0), col_hi[1], col_hi[0], s, t); + if(its % 10 == 0) + { + // Exceptional shift, nonzero even when the trailing block is nilpotent (as for x^n - 1). + ++restarts; + Real theta = Real(2.4) * Real(restarts); + Real scale = (std::max)((std::max)(abs(q), abs(t)), Real(1e-3)); + return t + Real(0.75) * scale * complex_type(cos(theta), sin(theta)); + } + // Wilkinson: the eigenvalue of [[p, s], [q, t]] nearer t. + complex_type half_trace = (p + t) / Real(2); + complex_type disc = sqrt(half_trace * half_trace - (p * t - s * q)); + complex_type l1 = half_trace + disc, l2 = half_trace - disc; + return abs(l1 - t) < abs(l2 - t) ? l1 : l2; + } + + void step(std::size_t lo, std::size_t hi, complex_type mu) + { + complex_type rlo[3]; + r_column(lo, 1, rlo); + complex_type dlo = lo > 0 ? conj(Q_[lo - 1].a) : complex_type(1, 0); + complex_type x1 = dlo * Q_[lo].a * rlo[0] - mu, x2 = Q_[lo].b * rlo[0]; + core U = eliminating(x1, x2); + core Ustar = adjoint(U); + // U^* passes the deflated core Q_{lo-1} = diag(a, conj(a)), which multiplies its b by conj(a). + if(lo > 0) + Ustar.b *= conj(Q_[lo - 1].a); + Q_[lo] = fuse(Ustar, Q_[lo]); + core X = U; + for(std::size_t i = lo; i < hi; ++i) + { + core Xp = pass_through(i, X); + if(i + 1 == hi) + { + // Xp passes the deflated core Q_hi = diag(a, conj(a)), which multiplies its b by a. + if(hi + 1 < n_) + Xp.b *= Q_[hi].a; + Q_[i] = fuse(Q_[i], Xp); + } + else + { + core q0, q1; + turnover(Q_[i], Q_[i + 1], Xp, X, q0, q1); + Q_[i] = q0; + Q_[i + 1] = q1; + } + } + } + + std::size_t n_; + std::vector > Q_, C_, B_; +}; + +} // namespace companion_detail + +namespace polynomial_roots_detail { + +// All roots of a_0 + a_1 x + ... + a_n x^n, as eigenvalues of the companion matrix. +template +std::vector > companion_qr(std::vector coefficients) +{ + using std::abs; + using std::exp; + using std::log; + using complex_type = detail::complex_from_real_t; + while(!coefficients.empty() && coefficients.back() == 0) + coefficients.pop_back(); + if(coefficients.empty()) + throw std::domain_error("polynomial_roots_companion_matrix: the zero polynomial has no finite root set"); + for(Real c : coefficients) + if(!(BOOST_MATH_NAMESPACE::isfinite)(c)) + throw std::domain_error("polynomial_roots_companion_matrix: coefficients must be finite"); + std::size_t zero_roots = 0; + while(zero_roots + 1 < coefficients.size() && coefficients[zero_roots] == 0) + ++zero_roots; + std::vector roots; + std::size_t n = coefficients.size() - 1 - zero_roots; + if(n == 1) + roots.push_back(complex_type(-coefficients[zero_roots] / coefficients.back(), Real(0))); + else if(n >= 2) + { + // The companion QR is normwise backward stable, so scale the variable, x = s w, to make the + // constant and leading coefficients equal in magnitude: s = |a_0 / a_n|^(1/n), formed in logs so + // that neither it nor the scaled coefficients a_k s^(k-n) / a_n overflow. + Real const* a = coefficients.data() + zero_roots; + Real log_s = (log(abs(a[0])) - log(abs(a[n]))) / Real(n); + std::vector monic(n); + for(std::size_t k = 0; k < n; ++k) + monic[k] = a[k] == 0 ? complex_type(0, 0) + : complex_type(Real((a[k] < 0) != (a[n] < 0) ? -1 : 1), Real(0)) * + exp(log(abs(a[k])) - log(abs(a[n])) + (Real(k) - Real(n)) * log_s); + roots = companion_detail::companion(monic).eigenvalues(); + Real s = exp(log_s); + for(auto& z : roots) + z *= s; + } + roots.insert(roots.end(), zero_roots, complex_type(0, 0)); + return roots; +} + + +} // namespace polynomial_roots_detail + +// All roots of a_0 + a_1 x + ... + a_n x^n, coefficients in ascending order, by the piecewise method. +// RandomAccessContainer is std::vector, std::array, std::span, ...; the roots come back as +// std::vector> for built-in Real, or of the matching Boost.Multiprecision complex type. +BOOST_MATH_EXPORT template +auto polynomial_roots(RandomAccessContainer const& coefficients) +{ + using Real = typename std::remove_cv::type; + return polynomial_roots_detail::piecewise(std::vector(coefficients.begin(), coefficients.end())); +} + +// The same roots as the eigenvalues of the companion matrix, by the companion QR algorithm of Aurentz, Mach, +// Vandebril and Watkins: O(n^2), and normwise backward stable. +BOOST_MATH_EXPORT template +auto polynomial_roots_companion_matrix(RandomAccessContainer const& coefficients) +{ + using Real = typename std::remove_cv::type; + return polynomial_roots_detail::companion_qr(std::vector(coefficients.begin(), coefficients.end())); +} + +} BOOST_MATH_NAMESPACE_END + +#endif diff --git a/include/boost/math/tools/precision.hpp b/include/boost/math/tools/precision.hpp index 6e863401d9..e7c02bb379 100644 --- a/include/boost/math/tools/precision.hpp +++ b/include/boost/math/tools/precision.hpp @@ -17,6 +17,7 @@ #include #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -24,9 +25,9 @@ #include #include // LDBL_MANT_DIG #endif +#endif -namespace boost{ namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools { // If T is not specialized, the functions digits, max_value and min_value, @@ -41,31 +42,31 @@ namespace tools // template <> NTL::RR max_value ... // See Conceptual Requirements for Real Number Types. -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) noexcept { - static_assert( ::boost::math::numeric_limits::is_specialized, "Type T must be specialized"); - static_assert( ::boost::math::numeric_limits::radix == 2 || ::boost::math::numeric_limits::radix == 10, "Type T must have a radix of 2 or 10"); + static_assert( ::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized, "Type T must be specialized"); + static_assert( ::BOOST_MATH_NAMESPACE::numeric_limits::radix == 2 || ::BOOST_MATH_NAMESPACE::numeric_limits::radix == 10, "Type T must have a radix of 2 or 10"); - return boost::math::numeric_limits::radix == 2 - ? boost::math::numeric_limits::digits - : ((boost::math::numeric_limits::digits + 1) * 1000L) / 301L; + return BOOST_MATH_NAMESPACE::numeric_limits::radix == 2 + ? BOOST_MATH_NAMESPACE::numeric_limits::digits + : ((BOOST_MATH_NAMESPACE::numeric_limits::digits + 1) * 1000L) / 301L; } -template -BOOST_MATH_GPU_ENABLED inline constexpr T max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline constexpr T max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { - static_assert( ::boost::math::numeric_limits::is_specialized, "Type T must be specialized"); - return (boost::math::numeric_limits::max)(); + static_assert( ::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized, "Type T must be specialized"); + return (BOOST_MATH_NAMESPACE::numeric_limits::max)(); } // Also used as a finite 'infinite' value for - and +infinity, for example: // -max_value = -1.79769e+308, max_value = 1.79769e+308. -template -BOOST_MATH_GPU_ENABLED inline constexpr T min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline constexpr T min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { - static_assert( ::boost::math::numeric_limits::is_specialized, "Type T must be specialized"); + static_assert( ::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized, "Type T must be specialized"); - return (boost::math::numeric_limits::min)(); + return (BOOST_MATH_NAMESPACE::numeric_limits::min)(); } namespace detail{ @@ -78,13 +79,13 @@ namespace detail{ // For type float first: // template -BOOST_MATH_GPU_ENABLED constexpr T log_max_value(const boost::math::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED constexpr T log_max_value(const BOOST_MATH_NAMESPACE::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return 88.0f; } template -BOOST_MATH_GPU_ENABLED constexpr T log_min_value(const boost::math::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED constexpr T log_min_value(const BOOST_MATH_NAMESPACE::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return -87.0f; } @@ -92,13 +93,13 @@ BOOST_MATH_GPU_ENABLED constexpr T log_min_value(const boost::math::integral_con // Now double: // template -BOOST_MATH_GPU_ENABLED constexpr T log_max_value(const boost::math::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED constexpr T log_max_value(const BOOST_MATH_NAMESPACE::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return 709.0; } template -BOOST_MATH_GPU_ENABLED constexpr T log_min_value(const boost::math::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED constexpr T log_min_value(const BOOST_MATH_NAMESPACE::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return -708.0; } @@ -106,52 +107,52 @@ BOOST_MATH_GPU_ENABLED constexpr T log_min_value(const boost::math::integral_con // 80 and 128-bit long doubles: // template -BOOST_MATH_GPU_ENABLED inline constexpr T log_max_value(const boost::math::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T log_max_value(const BOOST_MATH_NAMESPACE::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return 11356.0L; } template -BOOST_MATH_GPU_ENABLED inline constexpr T log_min_value(const boost::math::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T log_min_value(const BOOST_MATH_NAMESPACE::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return -11355.0L; } template -BOOST_MATH_GPU_ENABLED inline T log_max_value(const boost::math::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) +BOOST_MATH_GPU_ENABLED inline T log_max_value(const BOOST_MATH_NAMESPACE::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) { BOOST_MATH_STD_USING #ifdef __SUNPRO_CC - static const T m = boost::math::tools::max_value(); + static const T m = BOOST_MATH_NAMESPACE::tools::max_value(); static const T val = log(m); #else - static const T val = log(boost::math::tools::max_value()); + static const T val = log(BOOST_MATH_NAMESPACE::tools::max_value()); #endif return val; } template -BOOST_MATH_GPU_ENABLED inline T log_min_value(const boost::math::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) +BOOST_MATH_GPU_ENABLED inline T log_min_value(const BOOST_MATH_NAMESPACE::integral_constant& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) { BOOST_MATH_STD_USING #ifdef __SUNPRO_CC - static const T m = boost::math::tools::min_value(); + static const T m = BOOST_MATH_NAMESPACE::tools::min_value(); static const T val = log(m); #else - static const T val = log(boost::math::tools::min_value()); + static const T val = log(BOOST_MATH_NAMESPACE::tools::min_value()); #endif return val; } template -BOOST_MATH_GPU_ENABLED constexpr T epsilon(const boost::math::true_type& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED constexpr T epsilon(const BOOST_MATH_NAMESPACE::true_type& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { - return boost::math::numeric_limits::epsilon(); + return BOOST_MATH_NAMESPACE::numeric_limits::epsilon(); } #if defined(__GNUC__) && ((LDBL_MANT_DIG == 106) || (__LDBL_MANT_DIG__ == 106)) template <> -BOOST_MATH_GPU_ENABLED inline constexpr long double epsilon(const boost::math::true_type& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(long double)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr long double epsilon(const BOOST_MATH_NAMESPACE::true_type& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(long double)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { // numeric_limits on Darwin (and elsewhere) tells lies here: // the issue is that long double on a few platforms is @@ -170,7 +171,7 @@ BOOST_MATH_GPU_ENABLED inline constexpr long double epsilon(const b #endif template -BOOST_MATH_GPU_ENABLED inline T epsilon(const boost::math::false_type& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) +BOOST_MATH_GPU_ENABLED inline T epsilon(const BOOST_MATH_NAMESPACE::false_type& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) { // Note: don't cache result as precision may vary at runtime: BOOST_MATH_STD_USING // for ADL of std names @@ -180,27 +181,27 @@ BOOST_MATH_GPU_ENABLED inline T epsilon(const boost::math::false_type& BOOST_MAT template struct log_limit_traits { - typedef typename boost::math::conditional< - (boost::math::numeric_limits::radix == 2) && + typedef typename BOOST_MATH_NAMESPACE::conditional< + (BOOST_MATH_NAMESPACE::numeric_limits::radix == 2) && ( - ( boost::math::numeric_limits::max_exponent == 128 - || boost::math::numeric_limits::max_exponent == 1024 - || boost::math::numeric_limits::max_exponent == 16384 + ( BOOST_MATH_NAMESPACE::numeric_limits::max_exponent == 128 + || BOOST_MATH_NAMESPACE::numeric_limits::max_exponent == 1024 + || BOOST_MATH_NAMESPACE::numeric_limits::max_exponent == 16384 ) - && (-boost::math::numeric_limits::min_exponent10 + 1 == boost::math::numeric_limits::max_exponent10) + && (-BOOST_MATH_NAMESPACE::numeric_limits::min_exponent10 + 1 == BOOST_MATH_NAMESPACE::numeric_limits::max_exponent10) ), - boost::math::integral_constant::max_exponent > (boost::math::numeric_limits::max)() ? (boost::math::numeric_limits::max)() : static_cast(boost::math::numeric_limits::max_exponent))>, - boost::math::integral_constant + BOOST_MATH_NAMESPACE::integral_constant::max_exponent > (BOOST_MATH_NAMESPACE::numeric_limits::max)() ? (BOOST_MATH_NAMESPACE::numeric_limits::max)() : static_cast(BOOST_MATH_NAMESPACE::numeric_limits::max_exponent))>, + BOOST_MATH_NAMESPACE::integral_constant >::type tag_type; static constexpr bool value = (tag_type::value != 0); - static_assert(::boost::math::numeric_limits::is_specialized || !value, "Type T must be specialized or equal to 0"); + static_assert(::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized || !value, "Type T must be specialized or equal to 0"); }; template struct log_limit_noexcept_traits_imp : public log_limit_traits {}; -template struct log_limit_noexcept_traits_imp : public boost::math::integral_constant {}; +template struct log_limit_noexcept_traits_imp : public BOOST_MATH_NAMESPACE::integral_constant {}; template -struct log_limit_noexcept_traits : public log_limit_noexcept_traits_imp::value> {}; +struct log_limit_noexcept_traits : public log_limit_noexcept_traits_imp::value> {}; } // namespace detail @@ -209,37 +210,37 @@ struct log_limit_noexcept_traits : public log_limit_noexcept_traits_imp +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(detail::log_limit_noexcept_traits::value) { #ifndef BOOST_MATH_HAS_NVRTC #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS return detail::log_max_value(typename detail::log_limit_traits::tag_type()); #else - BOOST_MATH_ASSERT(::boost::math::numeric_limits::is_specialized); + BOOST_MATH_ASSERT(::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized); BOOST_MATH_STD_USING - static const T val = log((boost::math::numeric_limits::max)()); + static const T val = log((BOOST_MATH_NAMESPACE::numeric_limits::max)()); return val; #endif #else - return log((boost::math::numeric_limits::max)()); + return log((BOOST_MATH_NAMESPACE::numeric_limits::max)()); #endif } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(detail::log_limit_noexcept_traits::value) { #ifndef BOOST_MATH_HAS_NVRTC #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS return detail::log_min_value(typename detail::log_limit_traits::tag_type()); #else - BOOST_MATH_ASSERT(::boost::math::numeric_limits::is_specialized); + BOOST_MATH_ASSERT(::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized); BOOST_MATH_STD_USING - static const T val = log((boost::math::numeric_limits::min)()); + static const T val = log((BOOST_MATH_NAMESPACE::numeric_limits::min)()); return val; #endif #else - return log((boost::math::numeric_limits::min)()); + return log((BOOST_MATH_NAMESPACE::numeric_limits::min)()); #endif } @@ -247,45 +248,45 @@ BOOST_MATH_GPU_ENABLED inline T log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE( #pragma warning(pop) #endif -template -BOOST_MATH_GPU_ENABLED constexpr T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED constexpr T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { // NVRTC does not like this dispatching method so we just skip to where we want to go #ifndef BOOST_MATH_HAS_NVRTC #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - return detail::epsilon(boost::math::integral_constant::is_specialized>()); + return detail::epsilon(BOOST_MATH_NAMESPACE::integral_constant::is_specialized>()); #else - return ::boost::math::numeric_limits::is_specialized ? - detail::epsilon(boost::math::true_type()) : - detail::epsilon(boost::math::false_type()); + return ::BOOST_MATH_NAMESPACE::numeric_limits::is_specialized ? + detail::epsilon(BOOST_MATH_NAMESPACE::true_type()) : + detail::epsilon(BOOST_MATH_NAMESPACE::false_type()); #endif #else - return boost::math::numeric_limits::epsilon(); + return BOOST_MATH_NAMESPACE::numeric_limits::epsilon(); #endif } namespace detail{ template -BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon_imp(const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon_imp(const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(0.00034526698300124390839884978618400831996329879769945L); } template -BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(0.1490116119384765625e-7L); } template -BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(0.32927225399135962333569506281281311031656150598474e-9L); } template -BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(0.1387778780781445675529539585113525390625e-16L); } @@ -299,32 +300,32 @@ BOOST_MATH_GPU_ENABLED inline T root_epsilon_imp(const T*, const Tag&) } template -BOOST_MATH_GPU_ENABLED inline T root_epsilon_imp(const T*, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline T root_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING return sqrt(tools::epsilon()); } template -BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon_imp(const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon_imp(const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(0.0049215666011518482998719164346805794944150447839903L); } template -BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(6.05545445239333906078989272793696693569753008995e-6L); } template -BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(4.76837158203125e-7L); } template -BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(5.7749313854154005630396773604745549542403508090496e-12L); } @@ -338,32 +339,32 @@ BOOST_MATH_GPU_ENABLED inline T cbrt_epsilon_imp(const T*, const Tag&) } template -BOOST_MATH_GPU_ENABLED inline T cbrt_epsilon_imp(const T*, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline T cbrt_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING; return pow(tools::epsilon(), T(1) / 3); } template -BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(0.018581361171917516667460937040007436176452688944747L); } template -BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(0.0001220703125L); } template -BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(0.18145860519450699870567321328132261891067079047605e-4L); } template -BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon_imp(const T*, const boost::math::integral_constant&) noexcept(boost::math::is_floating_point::value) +BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value) { return static_cast(0.37252902984619140625e-8L); } @@ -377,7 +378,7 @@ BOOST_MATH_GPU_ENABLED inline T forth_root_epsilon_imp(const T*, const Tag&) } template -BOOST_MATH_GPU_ENABLED inline T forth_root_epsilon_imp(const T*, const boost::math::integral_constant&) +BOOST_MATH_GPU_ENABLED inline T forth_root_epsilon_imp(const T*, const BOOST_MATH_NAMESPACE::integral_constant&) { BOOST_MATH_STD_USING return sqrt(sqrt(tools::epsilon())); @@ -386,33 +387,32 @@ BOOST_MATH_GPU_ENABLED inline T forth_root_epsilon_imp(const T*, const boost::ma template struct root_epsilon_traits { - typedef boost::math::integral_constant::radix == 2) && (::boost::math::numeric_limits::digits != (boost::math::numeric_limits::max)()) ? boost::math::numeric_limits::digits : 0> tag_type; + typedef BOOST_MATH_NAMESPACE::integral_constant::radix == 2) && (::BOOST_MATH_NAMESPACE::numeric_limits::digits != (BOOST_MATH_NAMESPACE::numeric_limits::max)()) ? BOOST_MATH_NAMESPACE::numeric_limits::digits : 0> tag_type; static constexpr bool has_noexcept = (tag_type::value == 113) || (tag_type::value == 64) || (tag_type::value == 53) || (tag_type::value == 24); }; } -template -BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon() noexcept(boost::math::is_floating_point::value && detail::root_epsilon_traits::has_noexcept) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline constexpr T root_epsilon() noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value && detail::root_epsilon_traits::has_noexcept) { return detail::root_epsilon_imp(static_cast(nullptr), typename detail::root_epsilon_traits::tag_type()); } -template -BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon() noexcept(boost::math::is_floating_point::value && detail::root_epsilon_traits::has_noexcept) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline constexpr T cbrt_epsilon() noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value && detail::root_epsilon_traits::has_noexcept) { return detail::cbrt_epsilon_imp(static_cast(nullptr), typename detail::root_epsilon_traits::tag_type()); } -template -BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon() noexcept(boost::math::is_floating_point::value && detail::root_epsilon_traits::has_noexcept) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline constexpr T forth_root_epsilon() noexcept(BOOST_MATH_NAMESPACE::is_floating_point::value && detail::root_epsilon_traits::has_noexcept) { return detail::forth_root_epsilon_imp(static_cast(nullptr), typename detail::root_epsilon_traits::tag_type()); } } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_PRECISION_INCLUDED diff --git a/include/boost/math/tools/promotion.hpp b/include/boost/math/tools/promotion.hpp index a65f3703f4..b8dffb82ae 100644 --- a/include/boost/math/tools/promotion.hpp +++ b/include/boost/math/tools/promotion.hpp @@ -27,10 +27,7 @@ #include #include -namespace boost -{ - namespace math - { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { ///// This promotion system works as follows: @@ -72,22 +69,22 @@ namespace boost // Promotes a single argument to double if it is an integer type template struct promote_arg { - using type = typename boost::math::conditional::value, double, T>::type; + using type = typename BOOST_MATH_NAMESPACE::conditional::value, double, T>::type; }; // Promotes two arguments, neither of which is an integer type using an asymmetric // convertibility rule. - template ::value && boost::math::is_floating_point::value)> + template ::value && BOOST_MATH_NAMESPACE::is_floating_point::value)> struct pa2_integral_already_removed { - using type = typename boost::math::conditional< - !boost::math::is_floating_point::value && boost::math::is_convertible::value, + using type = typename BOOST_MATH_NAMESPACE::conditional< + !BOOST_MATH_NAMESPACE::is_floating_point::value && BOOST_MATH_NAMESPACE::is_convertible::value, T2, T1>::type; }; // For two floating point types, promotes using `std::common_type` functionality template struct pa2_integral_already_removed { - using type = boost::math::common_type_t; + using type = BOOST_MATH_NAMESPACE::common_type_t; }; @@ -97,7 +94,7 @@ namespace boost // Specialization for one argument template struct promote_args_permissive { - using type = typename promote_arg::type>::type; + using type = typename promote_arg::type>::type; }; // Specialization for two or more arguments template @@ -121,7 +118,7 @@ namespace boost // // Guard against use of long double if it's not supported: // - static_assert((0 == boost::math::is_same::value), "Sorry, but this platform does not have sufficient long double support for the special functions to be reliably implemented."); + static_assert((0 == BOOST_MATH_NAMESPACE::is_same::value), "Sorry, but this platform does not have sufficient long double support for the special functions to be reliably implemented."); #endif }; @@ -129,7 +126,6 @@ namespace boost using promote_args_t = typename promote_args::type; } // namespace tools - } // namespace math -} // namespace boost + BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_PROMOTION_HPP diff --git a/include/boost/math/tools/quartic_roots.hpp b/include/boost/math/tools/quartic_roots.hpp index 88a4f72531..2f7a9f6c46 100644 --- a/include/boost/math/tools/quartic_roots.hpp +++ b/include/boost/math/tools/quartic_roots.hpp @@ -4,11 +4,13 @@ // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_TOOLS_QUARTIC_ROOTS_HPP #define BOOST_MATH_TOOLS_QUARTIC_ROOTS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { @@ -50,7 +52,7 @@ std::array polish_and_sort(Real a, Real b, Real c, Real d, Real e, std: // Solves ax^4 + bx^3 + cx^2 + dx + e = 0. // Only returns the real roots, as these are the only roots of interest in ray intersection problems. // Follows Graphics Gems V: https://github.com/erich666/GraphicsGems/blob/master/gems/Roots3And4.c -template +BOOST_MATH_EXPORT template std::array quartic_roots(Real a, Real b, Real c, Real d, Real e) { using std::abs; using std::sqrt; @@ -153,5 +155,5 @@ std::array quartic_roots(Real a, Real b, Real c, Real d, Real e) { return detail::polish_and_sort(a, b, c, d, e, roots); } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/random_vector.hpp b/include/boost/math/tools/random_vector.hpp index 79c0af4030..9af5e0fb25 100644 --- a/include/boost/math/tools/random_vector.hpp +++ b/include/boost/math/tools/random_vector.hpp @@ -4,12 +4,16 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include + +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#endif -namespace boost { namespace math { +BOOST_MATH_NAMESPACE_BEGIN // To stress test, set global_seed = 0, global_size = huge. static constexpr std::size_t global_seed = 0; @@ -98,4 +102,4 @@ std::vector generate_random_vector(std::size_t size, std::size_t seed) return v; } -}} // Namespaces +BOOST_MATH_NAMESPACE_END diff --git a/include/boost/math/tools/rational.hpp b/include/boost/math/tools/rational.hpp index 95ec97e375..c9691914a9 100644 --- a/include/boost/math/tools/rational.hpp +++ b/include/boost/math/tools/rational.hpp @@ -16,8 +16,10 @@ #include #ifndef BOOST_MATH_HAS_NVRTC +#ifndef BOOST_MATH_BUILD_MODULE #include #endif +#endif #if BOOST_MATH_POLY_METHOD == 1 # define BOOST_HEADER() @@ -167,13 +169,13 @@ #include #endif -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ // // Forward declaration to keep two phase lookup happy: // -template -BOOST_MATH_GPU_ENABLED U evaluate_polynomial(const T* poly, U const& z, boost::math::size_t count) BOOST_MATH_NOEXCEPT(U); +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED U evaluate_polynomial(const T* poly, U const& z, BOOST_MATH_NAMESPACE::size_t count) BOOST_MATH_NOEXCEPT(U); namespace detail{ @@ -190,8 +192,8 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial_c_imp(const T* a, const V& v // This requires a for-loop which may be more expensive than // the loop expanded versions above: // -template -BOOST_MATH_GPU_ENABLED inline U evaluate_polynomial(const T* poly, U const& z, boost::math::size_t count) BOOST_MATH_NOEXCEPT(U) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline U evaluate_polynomial(const T* poly, U const& z, BOOST_MATH_NAMESPACE::size_t count) BOOST_MATH_NOEXCEPT(U) { BOOST_MATH_ASSERT(count > 0); U sum = static_cast(poly[count - 1]); @@ -206,38 +208,38 @@ BOOST_MATH_GPU_ENABLED inline U evaluate_polynomial(const T* poly, U const& z, b // Compile time sized polynomials, just inline forwarders to the // implementations above: // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial(const T(&a)[N], const V& val) BOOST_MATH_NOEXCEPT(V) { - typedef boost::math::integral_constant(N)> tag_type; + typedef BOOST_MATH_NAMESPACE::integral_constant(N)> tag_type; return detail::evaluate_polynomial_c_imp(static_cast(a), val, static_cast(nullptr)); } #ifndef BOOST_MATH_HAS_NVRTC -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline V evaluate_polynomial(const std::array& a, const V& val) BOOST_MATH_NOEXCEPT(V) { - typedef boost::math::integral_constant(N)> tag_type; + typedef BOOST_MATH_NAMESPACE::integral_constant(N)> tag_type; return detail::evaluate_polynomial_c_imp(static_cast(a.data()), val, static_cast(nullptr)); } #endif // // Even polynomials are trivial: just square the argument! // -template -BOOST_MATH_GPU_ENABLED inline U evaluate_even_polynomial(const T* poly, U z, boost::math::size_t count) BOOST_MATH_NOEXCEPT(U) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline U evaluate_even_polynomial(const T* poly, U z, BOOST_MATH_NAMESPACE::size_t count) BOOST_MATH_NOEXCEPT(U) { return evaluate_polynomial(poly, U(z*z), count); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline V evaluate_even_polynomial(const T(&a)[N], const V& z) BOOST_MATH_NOEXCEPT(V) { return evaluate_polynomial(a, V(z*z)); } #ifndef BOOST_MATH_HAS_NVRTC -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline V evaluate_even_polynomial(const std::array& a, const V& z) BOOST_MATH_NOEXCEPT(V) { return evaluate_polynomial(a, V(z*z)); @@ -246,37 +248,37 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_even_polynomial(const std::array& // // Odd polynomials come next: // -template -BOOST_MATH_GPU_ENABLED inline U evaluate_odd_polynomial(const T* poly, U z, boost::math::size_t count) BOOST_MATH_NOEXCEPT(U) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline U evaluate_odd_polynomial(const T* poly, U z, BOOST_MATH_NAMESPACE::size_t count) BOOST_MATH_NOEXCEPT(U) { return poly[0] + z * evaluate_polynomial(poly+1, U(z*z), count-1); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline V evaluate_odd_polynomial(const T(&a)[N], const V& z) BOOST_MATH_NOEXCEPT(V) { - typedef boost::math::integral_constant(N-1)> tag_type; + typedef BOOST_MATH_NAMESPACE::integral_constant(N-1)> tag_type; return a[0] + z * detail::evaluate_polynomial_c_imp(static_cast(a) + 1, V(z*z), static_cast(nullptr)); } #ifndef BOOST_MATH_HAS_NVRTC -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline V evaluate_odd_polynomial(const std::array& a, const V& z) BOOST_MATH_NOEXCEPT(V) { - typedef boost::math::integral_constant(N-1)> tag_type; + typedef BOOST_MATH_NAMESPACE::integral_constant(N-1)> tag_type; return a[0] + z * detail::evaluate_polynomial_c_imp(static_cast(a.data()) + 1, V(z*z), static_cast(nullptr)); } #endif -template -BOOST_MATH_GPU_ENABLED V evaluate_rational(const T* num, const U* denom, const V& z_, boost::math::size_t count) BOOST_MATH_NOEXCEPT(V); +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED V evaluate_rational(const T* num, const U* denom, const V& z_, BOOST_MATH_NAMESPACE::size_t count) BOOST_MATH_NOEXCEPT(V); namespace detail{ template BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* num, const U* denom, const V& z, const Tag*) BOOST_MATH_NOEXCEPT(V) { - return boost::math::tools::evaluate_rational(num, denom, z, Tag::value); + return BOOST_MATH_NAMESPACE::tools::evaluate_rational(num, denom, z, Tag::value); } } @@ -288,8 +290,8 @@ BOOST_MATH_GPU_ENABLED inline V evaluate_rational_c_imp(const T* num, const U* d // occur in polynomial evaluation, if z is large. This is important // in our Lanczos code for example. // -template -BOOST_MATH_GPU_ENABLED V evaluate_rational(const T* num, const U* denom, const V& z_, boost::math::size_t count) BOOST_MATH_NOEXCEPT(V) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED V evaluate_rational(const T* num, const U* denom, const V& z_, BOOST_MATH_NAMESPACE::size_t count) BOOST_MATH_NOEXCEPT(V) { V z(z_); V s1, s2; @@ -321,23 +323,22 @@ BOOST_MATH_GPU_ENABLED V evaluate_rational(const T* num, const U* denom, const V return s1 / s2; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline V evaluate_rational(const T(&a)[N], const U(&b)[N], const V& z) BOOST_MATH_NOEXCEPT(V) { - return detail::evaluate_rational_c_imp(a, b, z, static_cast(N)>*>(nullptr)); + return detail::evaluate_rational_c_imp(a, b, z, static_cast(N)>*>(nullptr)); } #ifndef BOOST_MATH_HAS_NVRTC -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline V evaluate_rational(const std::array& a, const std::array& b, const V& z) BOOST_MATH_NOEXCEPT(V) { - return detail::evaluate_rational_c_imp(a.data(), b.data(), z, static_cast(N)>*>(nullptr)); + return detail::evaluate_rational_c_imp(a.data(), b.data(), z, static_cast(N)>*>(nullptr)); } #endif } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_RATIONAL_HPP diff --git a/include/boost/math/tools/real_cast.hpp b/include/boost/math/tools/real_cast.hpp index a68738b347..b4e8180c48 100644 --- a/include/boost/math/tools/real_cast.hpp +++ b/include/boost/math/tools/real_cast.hpp @@ -12,8 +12,7 @@ #pragma once #endif -namespace boost{ namespace math -{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools { template @@ -22,8 +21,7 @@ namespace boost{ namespace math return static_cast(t); } } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_REAL_CAST_HPP diff --git a/include/boost/math/tools/recurrence.hpp b/include/boost/math/tools/recurrence.hpp index b08988d4bf..0bfc7cb7b4 100644 --- a/include/boost/math/tools/recurrence.hpp +++ b/include/boost/math/tools/recurrence.hpp @@ -6,9 +6,11 @@ #ifndef BOOST_MATH_TOOLS_RECURRENCE_HPP_ #define BOOST_MATH_TOOLS_RECURRENCE_HPP_ +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include #include @@ -18,8 +20,7 @@ #include #include -namespace boost { - namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail{ @@ -37,7 +38,7 @@ namespace boost { { typedef typename std::remove_reference(std::declval()(0)))>::type value_type; typedef std::pair result_type; - function_ratio_from_backwards_recurrence_fraction(const Recurrence& r) : r(r), k(0) {} + function_ratio_from_backwards_recurrence_fraction(const Recurrence& r_) : r(r_), k(0) {} result_type operator()() { @@ -61,7 +62,7 @@ namespace boost { template struct recurrence_reverser { - recurrence_reverser(const R& r) : r(r) {} + recurrence_reverser(const R& r_) : r(r_) {} std::tuple operator()(int i) { using std::swap; @@ -99,11 +100,11 @@ namespace boost { // factor: Convergence criteria, should be no less than machine epsilon. // max_iter: Maximum iterations to use solving the continued fraction. // - template + BOOST_MATH_EXPORT template T function_ratio_from_backwards_recurrence(const Recurrence& r, const T& factor, std::uintmax_t& max_iter) { detail::function_ratio_from_backwards_recurrence_fraction f(r); - return boost::math::tools::continued_fraction_a(f, factor, max_iter); + return BOOST_MATH_NAMESPACE::tools::continued_fraction_a(f, factor, max_iter); } // @@ -120,11 +121,11 @@ namespace boost { // factor: Convergence criteria, should be no less than machine epsilon. // max_iter: Maximum iterations to use solving the continued fraction. // - template + BOOST_MATH_EXPORT template T function_ratio_from_forwards_recurrence(const Recurrence& r, const T& factor, std::uintmax_t& max_iter) { - boost::math::tools::detail::function_ratio_from_backwards_recurrence_fraction > f(r); - return boost::math::tools::continued_fraction_a(f, factor, max_iter); + BOOST_MATH_NAMESPACE::tools::detail::function_ratio_from_backwards_recurrence_fraction > f(r); + return BOOST_MATH_NAMESPACE::tools::continued_fraction_a(f, factor, max_iter); } @@ -140,7 +141,7 @@ namespace boost { // first: w(-1); // second: w(0); // - template + BOOST_MATH_EXPORT template inline T apply_recurrence_relation_forward(const NextCoefs& get_coefs, unsigned number_of_steps, T first, T second, long long* log_scaling = nullptr, T* previous = nullptr) { BOOST_MATH_STD_USING @@ -172,7 +173,7 @@ namespace boost { } // scale each part separately to avoid spurious overflow: third = (a / -c) * first + (b / -c) * second; - BOOST_MATH_ASSERT((boost::math::isfinite)(third)); + BOOST_MATH_ASSERT((BOOST_MATH_NAMESPACE::isfinite)(third)); swap(first, second); @@ -196,7 +197,7 @@ namespace boost { // first: w(1); // second: w(0); // - template + BOOST_MATH_EXPORT template inline T apply_recurrence_relation_backward(const NextCoefs& get_coefs, unsigned number_of_steps, T first, T second, long long* log_scaling = nullptr, T* previous = nullptr) { BOOST_MATH_STD_USING @@ -227,7 +228,7 @@ namespace boost { } // scale each part separately to avoid spurious overflow: next = (b / -a) * second + (c / -a) * first; - BOOST_MATH_ASSERT((boost::math::isfinite)(next)); + BOOST_MATH_ASSERT((BOOST_MATH_NAMESPACE::isfinite)(next)); swap(first, second); swap(second, next); @@ -239,20 +240,37 @@ namespace boost { return second; } - template + // + // The index at which a recurrence iterator starts: the recurrence is called with k0, k0 + 1, ... (forwards) + // or k0, k0 - 1, ... (backwards) rather than starting from 0. Recurrences whose coefficients depend on + // v + k then see each order with a single rounding, rather than stepping from a rounded v + k0. + // + BOOST_MATH_EXPORT struct recurrence_offset + { + explicit recurrence_offset(int k) : value(k) {} + int value; + }; + + BOOST_MATH_EXPORT template struct forward_recurrence_iterator { typedef typename std::remove_reference(std::declval()(0)))>::type value_type; - forward_recurrence_iterator(const Recurrence& r, value_type f_n_minus_1, value_type f_n) - : f_n_minus_1(f_n_minus_1), f_n(f_n), coef(r), k(0) {} + forward_recurrence_iterator(const Recurrence& r, value_type f_n_minus_1_, value_type f_n_) + : f_n_minus_1(f_n_minus_1_), f_n(f_n_), coef(r), k(0) {} - forward_recurrence_iterator(const Recurrence& r, value_type f_n) - : f_n(f_n), coef(r), k(0) + forward_recurrence_iterator(const Recurrence& r, value_type f_n_) + : forward_recurrence_iterator(r, f_n_, recurrence_offset(0)) {} + + forward_recurrence_iterator(const Recurrence& r, value_type f_n_minus_1_, value_type f_n_, recurrence_offset k0) + : f_n_minus_1(f_n_minus_1_), f_n(f_n_), coef(r), k(k0.value) {} + + forward_recurrence_iterator(const Recurrence& r, value_type f_n_, recurrence_offset k0) + : f_n(f_n_), coef(r), k(k0.value) { - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations >(); - f_n_minus_1 = f_n * boost::math::tools::function_ratio_from_forwards_recurrence(detail::recurrence_offsetter(r, -1), value_type(boost::math::tools::epsilon() * 2), max_iter); - boost::math::policies::check_series_iterations("forward_recurrence_iterator<>::forward_recurrence_iterator", max_iter, boost::math::policies::policy<>()); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations >(); + f_n_minus_1 = f_n_ * BOOST_MATH_NAMESPACE::tools::function_ratio_from_forwards_recurrence(detail::recurrence_offsetter(r, k - 1), value_type(BOOST_MATH_NAMESPACE::tools::epsilon() * 2), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("forward_recurrence_iterator<>::forward_recurrence_iterator", max_iter, BOOST_MATH_NAMESPACE::policies::policy<>()); } forward_recurrence_iterator& operator++() @@ -281,20 +299,26 @@ namespace boost { int k; }; - template + BOOST_MATH_EXPORT template struct backward_recurrence_iterator { typedef typename std::remove_reference(std::declval()(0)))>::type value_type; - backward_recurrence_iterator(const Recurrence& r, value_type f_n_plus_1, value_type f_n) - : f_n_plus_1(f_n_plus_1), f_n(f_n), coef(r), k(0) {} + backward_recurrence_iterator(const Recurrence& r, value_type f_n_plus_1_, value_type f_n_) + : f_n_plus_1(f_n_plus_1_), f_n(f_n_), coef(r), k(0) {} + + backward_recurrence_iterator(const Recurrence& r, value_type f_n_) + : backward_recurrence_iterator(r, f_n_, recurrence_offset(0)) {} + + backward_recurrence_iterator(const Recurrence& r, value_type f_n_plus_1_, value_type f_n_, recurrence_offset k0) + : f_n_plus_1(f_n_plus_1_), f_n(f_n_), coef(r), k(k0.value) {} - backward_recurrence_iterator(const Recurrence& r, value_type f_n) - : f_n(f_n), coef(r), k(0) + backward_recurrence_iterator(const Recurrence& r, value_type f_n_, recurrence_offset k0) + : f_n(f_n_), coef(r), k(k0.value) { - std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations >(); - f_n_plus_1 = f_n * boost::math::tools::function_ratio_from_backwards_recurrence(detail::recurrence_offsetter(r, 1), value_type(boost::math::tools::epsilon() * 2), max_iter); - boost::math::policies::check_series_iterations("backward_recurrence_iterator<>::backward_recurrence_iterator", max_iter, boost::math::policies::policy<>()); + std::uintmax_t max_iter = BOOST_MATH_NAMESPACE::policies::get_max_series_iterations >(); + f_n_plus_1 = f_n_ * BOOST_MATH_NAMESPACE::tools::function_ratio_from_backwards_recurrence(detail::recurrence_offsetter(r, k + 1), value_type(BOOST_MATH_NAMESPACE::tools::epsilon() * 2), max_iter); + BOOST_MATH_NAMESPACE::policies::check_series_iterations("backward_recurrence_iterator<>::backward_recurrence_iterator", max_iter, BOOST_MATH_NAMESPACE::policies::policy<>()); } backward_recurrence_iterator& operator++() @@ -324,7 +348,6 @@ namespace boost { }; } - } -} // namespaces + BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_RECURRENCE_HPP_ diff --git a/include/boost/math/tools/roots.hpp b/include/boost/math/tools/roots.hpp index af9b76d998..6854410f56 100644 --- a/include/boost/math/tools/roots.hpp +++ b/include/boost/math/tools/roots.hpp @@ -26,8 +26,7 @@ #include #endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { @@ -65,13 +64,13 @@ BOOST_MATH_GPU_ENABLED inline void unpack_0(const Tuple& t, T& val) BOOST_MATH_N } template -BOOST_MATH_GPU_ENABLED inline void unpack_tuple(const boost::math::pair& p, V& a, V& b) BOOST_MATH_NOEXCEPT(T) +BOOST_MATH_GPU_ENABLED inline void unpack_tuple(const BOOST_MATH_NAMESPACE::pair& p, V& a, V& b) BOOST_MATH_NOEXCEPT(T) { a = p.first; b = p.second; } template -BOOST_MATH_GPU_ENABLED inline void unpack_0(const boost::math::pair& p, V& a) BOOST_MATH_NOEXCEPT(T) +BOOST_MATH_GPU_ENABLED inline void unpack_0(const BOOST_MATH_NAMESPACE::pair& p, V& a) BOOST_MATH_NOEXCEPT(T) { a = p.first; } @@ -131,10 +130,64 @@ BOOST_MATH_GPU_ENABLED void handle_zero_derivative(F f, } } +// +// The Newton and Halley/Schroder iterations assume that when a step leaves +// [min, max], the root lies between the current guess and the bound it +// crossed. If f is not monotone between the guess and the root that need +// not be true, and the iteration then walks onto the bound without ever +// seeing f change sign: https://github.com/boostorg/math/issues/808 +// +// Call this only once the iteration has finished without observing a sign +// change. If the result has collapsed onto one of the original endpoints +// b, we evaluate f(b) once and return true (report failure) when it looks +// as though there is no root between result and b. This is a diagnostic +// heuristic, not a proof: +// +// * If f(b) has the opposite sign to f0 (the last residual) or is zero, +// then (f being continuous, as these solvers assume throughout) there is +// certainly a root in the sliver between result and b, so the result +// stands. +// * Otherwise f(b) must also be "not close to zero" before we complain: +// not much closer than f0, and not negligible next to first_f0 (the +// residual at the initial guess). These thresholds absorb rounding +// noise at a genuine root at b, where f0 is itself noise once the +// iteration has converged. +// +// We evaluate f(b) rather than f(result): when bisection approaches a +// genuine root at b, f(result) is roughly f0 / 2 by construction, so it +// cannot tell that case apart from a function that never reaches zero. +// An interior result never evaluates f here at all. +// +template +BOOST_MATH_GPU_ENABLED bool converged_onto_endpoint_without_root(F& f, const T& result, const T& delta, const T& f0, const T& first_f0, const T& min, const T& max) +{ + BOOST_MATH_STD_USING + const T dmin = fabs(result - min); + const T dmax = fabs(max - result); + const T b = dmin <= dmax ? min : max; + if ((dmin <= dmax ? dmin : dmax) > 2 * fabs(delta)) + return false; + T fb; +#if !defined(BOOST_MATH_NO_EXCEPTIONS) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) + try +#endif + { + unpack_0(f(b), fb); + } +#if !defined(BOOST_MATH_NO_EXCEPTIONS) && !defined(BOOST_MATH_HAS_GPU_SUPPORT) + catch (const std::overflow_error&) + { + return false; // Can't tell, so keep the previous behaviour. + } +#endif + return (fb != 0) && ((fb < 0) == (f0 < 0)) && (fabs(fb) > fabs(f0) / 2) + && (fabs(fb) > fabs(first_f0) * tools::root_epsilon()); +} + } // namespace -template -BOOST_MATH_GPU_ENABLED boost::math::pair bisect(F f, T min, T max, Tol tol, boost::math::uintmax_t& max_iter, const Policy& pol) noexcept(policies::is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::pair bisect(F f, T min, T max, Tol tol, BOOST_MATH_NAMESPACE::uintmax_t& max_iter, const Policy& pol) noexcept(policies::is_noexcept_error_policy::value && BOOST_MATH_IS_FLOAT(T) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()(std::declval())) #endif @@ -145,26 +198,26 @@ BOOST_MATH_GPU_ENABLED boost::math::pair bisect(F f, T min, T max, Tol tol if (fmin == 0) { max_iter = 2; - return boost::math::make_pair(min, min); + return BOOST_MATH_NAMESPACE::make_pair(min, min); } if (fmax == 0) { max_iter = 2; - return boost::math::make_pair(max, max); + return BOOST_MATH_NAMESPACE::make_pair(max, max); } // // Error checking: // constexpr auto function = "boost::math::tools::bisect<%1%>"; - if (min >= max) + if (!(min < max)) { - return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, + return BOOST_MATH_NAMESPACE::detail::pair_from_single(policies::raise_evaluation_error(function, "Arguments in wrong order in boost::math::tools::bisect (first arg=%1%)", min, pol)); } if (fmin * fmax >= 0) { - return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, + return BOOST_MATH_NAMESPACE::detail::pair_from_single(policies::raise_evaluation_error(function, "No change of sign in boost::math::tools::bisect, either there is no root to find, or there are multiple roots in the interval (f(min) = %1%).", fmin, pol)); } @@ -206,11 +259,11 @@ BOOST_MATH_GPU_ENABLED boost::math::pair bisect(F f, T min, T max, Tol tol std::cout << "Bisection required " << max_iter << " iterations.\n"; #endif - return boost::math::make_pair(min, max); + return BOOST_MATH_NAMESPACE::make_pair(min, max); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair bisect(F f, T min, T max, Tol tol, boost::math::uintmax_t& max_iter) noexcept(policies::is_noexcept_error_policy >::value && BOOST_MATH_IS_FLOAT(T) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair bisect(F f, T min, T max, Tol tol, BOOST_MATH_NAMESPACE::uintmax_t& max_iter) noexcept(policies::is_noexcept_error_policy >::value && BOOST_MATH_IS_FLOAT(T) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()(std::declval())) #endif @@ -219,20 +272,20 @@ BOOST_MATH_GPU_ENABLED inline boost::math::pair bisect(F f, T min, T max, return bisect(f, min, max, tol, max_iter, policies::policy<>()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair bisect(F f, T min, T max, Tol tol) noexcept(policies::is_noexcept_error_policy >::value && BOOST_MATH_IS_FLOAT(T) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair bisect(F f, T min, T max, Tol tol) noexcept(policies::is_noexcept_error_policy >::value && BOOST_MATH_IS_FLOAT(T) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()(std::declval())) #endif ) { - boost::math::uintmax_t m = (boost::math::numeric_limits::max)(); + BOOST_MATH_NAMESPACE::uintmax_t m = (BOOST_MATH_NAMESPACE::numeric_limits::max)(); return bisect(f, min, max, tol, m, policies::policy<>()); } -template -BOOST_MATH_GPU_ENABLED T newton_raphson_iterate(F f, T guess, T min, T max, int digits, boost::math::uintmax_t& max_iter) noexcept(policies::is_noexcept_error_policy >::value && BOOST_MATH_IS_FLOAT(T) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED T newton_raphson_iterate(F f, T guess, T min, T max, int digits, BOOST_MATH_NAMESPACE::uintmax_t& max_iter) noexcept(policies::is_noexcept_error_policy >::value && BOOST_MATH_IS_FLOAT(T) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()(std::declval())) #endif @@ -241,9 +294,14 @@ BOOST_MATH_GPU_ENABLED T newton_raphson_iterate(F f, T guess, T min, T max, int BOOST_MATH_STD_USING constexpr auto function = "boost::math::tools::newton_raphson_iterate<%1%>"; - if (min > max) + if (!(min <= max)) + { + return policies::raise_evaluation_error(function, "Range arguments in wrong order in boost::math::tools::newton_raphson_iterate(first arg=%1%)", min, BOOST_MATH_NAMESPACE::policies::policy<>()); + } + + if (max_iter == 0) { - return policies::raise_evaluation_error(function, "Range arguments in wrong order in boost::math::tools::newton_raphson_iterate(first arg=%1%)", min, boost::math::policies::policy<>()); + return guess; } T f0(0), f1, last_f0(0); @@ -266,8 +324,12 @@ BOOST_MATH_GPU_ENABLED T newton_raphson_iterate(F f, T guess, T min, T max, int // T max_range_f = 0; T min_range_f = 0; + const T min0 = min; + const T max0 = max; + T first_f0 = 0; + bool sign_changed = false; - boost::math::uintmax_t count(max_iter); + BOOST_MATH_NAMESPACE::uintmax_t count(max_iter); #ifdef BOOST_MATH_INSTRUMENT std::cout << "Newton_raphson_iterate, guess = " << guess << ", min = " << min << ", max = " << max @@ -282,6 +344,10 @@ BOOST_MATH_GPU_ENABLED T newton_raphson_iterate(F f, T guess, T min, T max, int --count; if (0 == f0) break; + if (first_f0 == 0) + first_f0 = f0; + else if ((f0 < 0) != (first_f0 < 0)) + sign_changed = true; if (f1 == 0) { // Oops zero derivative!!! @@ -340,10 +406,15 @@ BOOST_MATH_GPU_ENABLED T newton_raphson_iterate(F f, T guess, T min, T max, int // if (max_range_f * min_range_f > 0) { - return policies::raise_evaluation_error(function, "There appears to be no root to be found in boost::math::tools::newton_raphson_iterate, perhaps we have a local minima near current best guess of %1%", guess, boost::math::policies::policy<>()); + return policies::raise_evaluation_error(function, "There appears to be no root to be found in boost::math::tools::newton_raphson_iterate, perhaps we have a local minima near current best guess of %1%", guess, BOOST_MATH_NAMESPACE::policies::policy<>()); } }while(count && (fabs(result * factor) < fabs(delta))); + if ((f0 != 0) && !sign_changed && detail::converged_onto_endpoint_without_root(f, result, delta, f0, first_f0, min0, max0)) + { + return policies::raise_evaluation_error(function, "No root was found in boost::math::tools::newton_raphson_iterate: the iteration converged onto an end of the search range without f changing sign, try a different initial guess or range. Current best guess is %1%", result, BOOST_MATH_NAMESPACE::policies::policy<>()); + } + max_iter -= count; #ifdef BOOST_MATH_INSTRUMENT @@ -353,21 +424,21 @@ BOOST_MATH_GPU_ENABLED T newton_raphson_iterate(F f, T guess, T min, T max, int return result; } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline T newton_raphson_iterate(F f, T guess, T min, T max, int digits) noexcept(policies::is_noexcept_error_policy >::value && BOOST_MATH_IS_FLOAT(T) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()(std::declval())) #endif ) { - boost::math::uintmax_t m = (boost::math::numeric_limits::max)(); + BOOST_MATH_NAMESPACE::uintmax_t m = (BOOST_MATH_NAMESPACE::numeric_limits::max)(); return newton_raphson_iterate(f, guess, min, max, digits, m); } // TODO(mborland): Disabled for now // Recursion needs to be removed, but there is no demand at this time #ifdef BOOST_MATH_HAS_NVRTC -}}} // Namespaces +} BOOST_MATH_NAMESPACE_END // Namespaces #else namespace detail { @@ -546,9 +617,9 @@ namespace detail { << ", digits = " << digits << ", max_iter = " << max_iter << "\n"; #endif static const char* function = "boost::math::tools::halley_iterate<%1%>"; - if (min >= max) + if (!(min < max)) { - return policies::raise_evaluation_error(function, "Range arguments in wrong order in boost::math::tools::halley_iterate(first arg=%1%)", min, boost::math::policies::policy<>()); + return policies::raise_evaluation_error(function, "Range arguments in wrong order in boost::math::tools::halley_iterate(first arg=%1%)", min, BOOST_MATH_NAMESPACE::policies::policy<>()); } T f0(0), f1, f2; @@ -577,6 +648,10 @@ namespace detail { // T max_range_f = 0; T min_range_f = 0; + const T min0 = min; + const T max0 = max; + T first_f0 = 0; + bool sign_changed = false; std::uintmax_t count(max_iter); @@ -605,6 +680,10 @@ namespace detail { if (0 == f0) break; + if (first_f0 == 0) + first_f0 = f0; + else if ((f0 < 0) != (first_f0 < 0)) + sign_changed = true; if (f1 == 0) { // Oops zero derivative!!! @@ -745,10 +824,15 @@ namespace detail { // if (max_range_f * min_range_f > 0) { - return policies::raise_evaluation_error(function, "There appears to be no root to be found in boost::math::tools::newton_raphson_iterate, perhaps we have a local minima near current best guess of %1%", guess, boost::math::policies::policy<>()); + return policies::raise_evaluation_error(function, "There appears to be no root to be found in boost::math::tools::newton_raphson_iterate, perhaps we have a local minima near current best guess of %1%", guess, BOOST_MATH_NAMESPACE::policies::policy<>()); } } while(count && (fabs(result * factor) < fabs(delta))); + if ((f0 != 0) && !sign_changed && detail::converged_onto_endpoint_without_root(f, result, delta, f0, first_f0, min0, max0)) + { + return policies::raise_evaluation_error(function, "No root was found in boost::math::tools::halley_iterate: the iteration converged onto an end of the search range without f changing sign, try a different initial guess or range. Current best guess is %1%", result, BOOST_MATH_NAMESPACE::policies::policy<>()); + } + max_iter -= count; #ifdef BOOST_MATH_INSTRUMENT @@ -759,13 +843,13 @@ namespace detail { } } // T second_order_root_finder -template +BOOST_MATH_EXPORT template T halley_iterate(F f, T guess, T min, T max, int digits, std::uintmax_t& max_iter) noexcept(policies::is_noexcept_error_policy >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval()(std::declval()))) { return detail::second_order_root_finder(f, guess, min, max, digits, max_iter); } -template +BOOST_MATH_EXPORT template inline T halley_iterate(F f, T guess, T min, T max, int digits) noexcept(policies::is_noexcept_error_policy >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval()(std::declval()))) { std::uintmax_t m = (std::numeric_limits::max)(); @@ -797,13 +881,13 @@ namespace detail { } -template +BOOST_MATH_EXPORT template T schroder_iterate(F f, T guess, T min, T max, int digits, std::uintmax_t& max_iter) noexcept(policies::is_noexcept_error_policy >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval()(std::declval()))) { return detail::second_order_root_finder(f, guess, min, max, digits, max_iter); } -template +BOOST_MATH_EXPORT template inline T schroder_iterate(F f, T guess, T min, T max, int digits) noexcept(policies::is_noexcept_error_policy >::value&& BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval()(std::declval()))) { std::uintmax_t m = (std::numeric_limits::max)(); @@ -832,7 +916,7 @@ inline T schroeder_iterate(F f, T guess, T min, T max, int digits) noexcept(poli * so this default should recover full precision even in this somewhat pathological case. * For isolated roots, the problem is so rapidly convergent that this doesn't matter at all. */ -template +BOOST_MATH_EXPORT template ComplexType complex_newton(F g, ComplexType guess, int max_iterations = std::numeric_limits::digits) { typedef typename ComplexType::value_type Real; @@ -941,7 +1025,7 @@ template std::pair quadratic_roots_imp(T const& a, T const& b, T const& c) { #if defined(BOOST_GNU_STDLIB) && !defined(_GLIBCXX_USE_C99_MATH_TR1) - using boost::math::copysign; + using BOOST_MATH_NAMESPACE::copysign; #else using std::copysign; #endif @@ -986,7 +1070,7 @@ std::pair quadratic_roots_imp(T const& a, T const& b, T const& c) } return std::pair(x1, x0); } - else if constexpr (boost::math::tools::is_complex_type::value) + else if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { typename T::value_type nan = std::numeric_limits::quiet_NaN(); if (a.real() == 0 && a.imag() == 0) @@ -1054,7 +1138,7 @@ std::pair quadratic_roots_imp(T const& a, T const& b, T const& c) } } // namespace detail -template +BOOST_MATH_EXPORT template inline std::pair::type, typename tools::promote_args::type> quadratic_roots(T1 const& a, T2 const& b, T3 const& c) { typedef typename tools::promote_args::type value_type; @@ -1064,8 +1148,7 @@ inline std::pair::type, typename tools: #endif } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_NVRTC diff --git a/include/boost/math/tools/series.hpp b/include/boost/math/tools/series.hpp index 4617ea3df7..9a68bb4894 100644 --- a/include/boost/math/tools/series.hpp +++ b/include/boost/math/tools/series.hpp @@ -16,13 +16,13 @@ #include #include -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ // // Simple series summation come first: // -template -BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, const U& factor, boost::math::uintmax_t& max_terms, const V& init_value) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, const U& factor, BOOST_MATH_NAMESPACE::uintmax_t& max_terms, const V& init_value) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) #endif @@ -32,9 +32,9 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& typedef typename Functor::result_type result_type; - boost::math::uintmax_t counter = max_terms; + BOOST_MATH_NAMESPACE::uintmax_t counter = max_terms; - result_type result = init_value; + result_type result = static_cast(init_value); result_type next_term; do{ next_term = func(); @@ -48,8 +48,8 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& return result; } -template -BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, const U& factor, boost::math::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, const U& factor, BOOST_MATH_NAMESPACE::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) #endif @@ -59,8 +59,8 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& return sum_series(func, factor, max_terms, init_value); } -template -BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, int bits, boost::math::uintmax_t& max_terms, const U& init_value) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, int bits, BOOST_MATH_NAMESPACE::uintmax_t& max_terms, const U& init_value) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) #endif @@ -72,7 +72,7 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& return sum_series(func, factor, max_terms, init_value); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, int bits) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) @@ -81,13 +81,13 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& { BOOST_MATH_STD_USING typedef typename Functor::result_type result_type; - boost::math::uintmax_t iters = (boost::math::numeric_limits::max)(); + BOOST_MATH_NAMESPACE::uintmax_t iters = (BOOST_MATH_NAMESPACE::numeric_limits::max)(); result_type init_val = 0; return sum_series(func, bits, iters, init_val); } -template -BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, int bits, boost::math::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, int bits, BOOST_MATH_NAMESPACE::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) #endif @@ -99,7 +99,7 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& return sum_series(func, bits, max_terms, init_val); } -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& func, int bits, const U& init_value) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) @@ -107,14 +107,14 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type sum_series(Functor& ) { BOOST_MATH_STD_USING - boost::math::uintmax_t iters = (boost::math::numeric_limits::max)(); + BOOST_MATH_NAMESPACE::uintmax_t iters = (BOOST_MATH_NAMESPACE::numeric_limits::max)(); return sum_series(func, bits, iters, init_value); } // // Checked summation: // -template -BOOST_MATH_GPU_ENABLED inline typename Functor::result_type checked_sum_series(Functor& func, const U& factor, boost::math::uintmax_t& max_terms, const V& init_value, V& norm) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename Functor::result_type checked_sum_series(Functor& func, const U& factor, BOOST_MATH_NAMESPACE::uintmax_t& max_terms, const V& init_value, V& norm) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) #endif @@ -124,7 +124,7 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type checked_sum_series(F typedef typename Functor::result_type result_type; - boost::math::uintmax_t counter = max_terms; + BOOST_MATH_NAMESPACE::uintmax_t counter = max_terms; result_type result = init_value; result_type next_term; @@ -153,7 +153,7 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type checked_sum_series(F // by the algorithm to be off by up to 1ulp. However this occurs rarely, and // in any case the result is still much better than a naive summation. // -template +BOOST_MATH_EXPORT template BOOST_MATH_GPU_ENABLED inline typename Functor::result_type kahan_sum_series(Functor& func, int bits) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) @@ -180,8 +180,8 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type kahan_sum_series(Fun return result; } -template -BOOST_MATH_GPU_ENABLED inline typename Functor::result_type kahan_sum_series(Functor& func, int bits, boost::math::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline typename Functor::result_type kahan_sum_series(Functor& func, int bits, BOOST_MATH_NAMESPACE::uintmax_t& max_terms) noexcept(BOOST_MATH_IS_FLOAT(typename Functor::result_type) #ifndef BOOST_MATH_HAS_GPU_SUPPORT && noexcept(std::declval()()) #endif @@ -191,12 +191,12 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type kahan_sum_series(Fun typedef typename Functor::result_type result_type; - boost::math::uintmax_t counter = max_terms; + BOOST_MATH_NAMESPACE::uintmax_t counter = max_terms; result_type factor = ldexp(result_type(1), bits); result_type result = func(); result_type next_term, y, t; - result_type carry = 0; + result_type carry = static_cast(0); do{ next_term = func(); y = next_term - carry; @@ -214,8 +214,7 @@ BOOST_MATH_GPU_ENABLED inline typename Functor::result_type kahan_sum_series(Fun } } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_SERIES_INCLUDED diff --git a/include/boost/math/tools/signal_statistics.hpp b/include/boost/math/tools/signal_statistics.hpp index 419e55f60a..7696e53a33 100644 --- a/include/boost/math/tools/signal_statistics.hpp +++ b/include/boost/math/tools/signal_statistics.hpp @@ -6,8 +6,10 @@ #ifndef BOOST_MATH_TOOLS_SIGNAL_STATISTICS_HPP #define BOOST_MATH_TOOLS_SIGNAL_STATISTICS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include #include #include @@ -24,7 +26,7 @@ BOOST_MATH_HEADER_DEPRECATED(""); -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { template auto absolute_gini_coefficient(ForwardIterator first, ForwardIterator last) @@ -59,20 +61,20 @@ auto absolute_gini_coefficient(ForwardIterator first, ForwardIterator last) template inline auto absolute_gini_coefficient(RandomAccessContainer & v) { - return boost::math::tools::absolute_gini_coefficient(v.begin(), v.end()); + return BOOST_MATH_NAMESPACE::tools::absolute_gini_coefficient(v.begin(), v.end()); } template auto sample_absolute_gini_coefficient(ForwardIterator first, ForwardIterator last) { size_t n = std::distance(first, last); - return n*boost::math::tools::absolute_gini_coefficient(first, last)/(n-1); + return n*BOOST_MATH_NAMESPACE::tools::absolute_gini_coefficient(first, last)/(n-1); } template inline auto sample_absolute_gini_coefficient(RandomAccessContainer & v) { - return boost::math::tools::sample_absolute_gini_coefficient(v.begin(), v.end()); + return BOOST_MATH_NAMESPACE::tools::sample_absolute_gini_coefficient(v.begin(), v.end()); } @@ -130,7 +132,7 @@ auto hoyer_sparsity(const ForwardIterator first, const ForwardIterator last) template inline auto hoyer_sparsity(Container const & v) { - return boost::math::tools::hoyer_sparsity(v.cbegin(), v.cend()); + return BOOST_MATH_NAMESPACE::tools::hoyer_sparsity(v.cbegin(), v.cend()); } @@ -159,7 +161,7 @@ auto oracle_snr(Container const & signal, Container const & noisy_signal) } return numerator/denominator; } - else if constexpr (boost::math::tools::is_complex_type::value) + else if constexpr (BOOST_MATH_NAMESPACE::tools::is_complex_type::value) { using std::norm; @@ -209,7 +211,7 @@ auto mean_invariant_oracle_snr(Container const & signal, Container const & noisy using Real = typename Container::value_type; BOOST_MATH_ASSERT_MSG(signal.size() == noisy_signal.size(), "Signal and noisy signal must be have the same number of elements."); - Real mu = boost::math::tools::mean(signal); + Real mu = BOOST_MATH_NAMESPACE::tools::mean(signal); Real numerator = 0; Real denominator = 0; for (size_t i = 0; i < signal.size(); ++i) @@ -235,7 +237,7 @@ template auto mean_invariant_oracle_snr_db(Container const & signal, Container const & noisy_signal) { using std::log10; - return 10*log10(boost::math::tools::mean_invariant_oracle_snr(signal, noisy_signal)); + return 10*log10(BOOST_MATH_NAMESPACE::tools::mean_invariant_oracle_snr(signal, noisy_signal)); } @@ -244,7 +246,7 @@ template auto oracle_snr_db(Container const & signal, Container const & noisy_signal) { using std::log10; - return 10*log10(boost::math::tools::oracle_snr(signal, noisy_signal)); + return 10*log10(BOOST_MATH_NAMESPACE::tools::oracle_snr(signal, noisy_signal)); } // A good reference on the M2M4 estimator: @@ -269,7 +271,7 @@ auto m2m4_snr_estimator(ForwardIterator first, ForwardIterator last, decltype(*f // However, I can't prove that, so there is a chance that this does unnecessary work. // Future improvements: There are algorithms which can solve quadratics much more effectively than the naive implementation found here. // See: https://stackoverflow.com/questions/48979861/numerically-stable-method-for-solving-quadratic-equations/50065711#50065711 - auto [M1, M2, M3, M4] = boost::math::tools::first_four_moments(first, last); + auto [M1, M2, M3, M4] = BOOST_MATH_NAMESPACE::tools::first_four_moments(first, last); if (M4 == 0) { // The signal is constant. There is no noise: @@ -284,7 +286,7 @@ auto m2m4_snr_estimator(ForwardIterator first, ForwardIterator last, decltype(*f Real cs = kw*M2*M2 - M4; Real bn = 2*M2*(3-ka); Real cn = ka*M2*M2 - M4; - auto [S0, S1] = boost::math::tools::quadratic_roots(a, bs, cs); + auto [S0, S1] = BOOST_MATH_NAMESPACE::tools::quadratic_roots(a, bs, cs); if (S1 > 0) { auto N = M2 - S1; @@ -301,7 +303,7 @@ auto m2m4_snr_estimator(ForwardIterator first, ForwardIterator last, decltype(*f } } } - auto [N0, N1] = boost::math::tools::quadratic_roots(a, bn, cn); + auto [N0, N1] = BOOST_MATH_NAMESPACE::tools::quadratic_roots(a, bn, cn); if (N1 > 0) { auto S = M2 - N1; @@ -349,5 +351,5 @@ inline auto m2m4_snr_estimator_db(Container const & noisy_signal, typename Cont return 10*log10(m2m4_snr_estimator(noisy_signal, estimated_signal_kurtosis, estimated_noise_kurtosis)); } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/simple_continued_fraction.hpp b/include/boost/math/tools/simple_continued_fraction.hpp index daf2c3c657..da86d65e24 100644 --- a/include/boost/math/tools/simple_continued_fraction.hpp +++ b/include/boost/math/tools/simple_continued_fraction.hpp @@ -6,21 +6,24 @@ #ifndef BOOST_MATH_TOOLS_SIMPLE_CONTINUED_FRACTION_HPP #define BOOST_MATH_TOOLS_SIMPLE_CONTINUED_FRACTION_HPP +#include + +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include -#include #include #include #include #include #include +#endif #include #ifndef BOOST_MATH_STANDALONE #include #ifdef BOOST_MATH_NO_CXX17_IF_CONSTEXPR -#error "The header can only be used in C++17 and later." +#error "The header can only be used in C++17 and later." #endif #endif @@ -28,12 +31,12 @@ #include #endif -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { -template +BOOST_MATH_EXPORT template class simple_continued_fraction { public: - simple_continued_fraction(Real x) : x_{x} { + simple_continued_fraction(Real x) { using std::floor; using std::abs; using std::sqrt; @@ -41,6 +44,7 @@ class simple_continued_fraction { if (!isfinite(x)) { throw std::domain_error("Cannot convert non-finites into continued fractions."); } + const Real x0 = x; b_.reserve(50); Real bj = floor(x); b_.push_back(static_cast(bj)); @@ -59,7 +63,7 @@ class simple_continued_fraction { // the "1 + i++" lets the error bound grow slowly with the number of convergents. // I have not worked out the error propagation of the Modified Lentz's method to see if it does indeed grow at this rate. // Numerical Recipes claims that no one has worked out the error analysis of the modified Lentz's method. - while (abs(f - x_) >= (1 + i++)*std::numeric_limits::epsilon()*abs(x_)) + while (abs(f - x0) >= (1 + i++)*std::numeric_limits::epsilon()*abs(x0)) { bj = floor(x); b_.push_back(static_cast(bj)); @@ -77,17 +81,20 @@ class simple_continued_fraction { } // Deal with non-uniqueness of continued fractions: [a0; a1, ..., an, 1] = a0; a1, ..., an + 1]. // The shorter representation is considered the canonical representation, - // so if we compute a non-canonical representation, change it to canonical: - if (b_.size() > 2 && b_.back() == 1) { + // so if we compute a non-canonical representation, change it to canonical. + // This includes [a0; 1] = [a0 + 1]. If the increment would overflow Z, + // keep the longer representation, which is still valid: + if (b_.size() >= 2 && b_.back() == 1 + && (!std::numeric_limits::is_bounded || b_[b_.size() - 2] < (std::numeric_limits::max)())) { b_[b_.size() - 2] += 1; b_.resize(b_.size() - 1); } b_.shrink_to_fit(); - for (size_t i = 1; i < b_.size(); ++i) { - if (b_[i] <= 0) { + for (size_t k = 1; k < b_.size(); ++k) { + if (b_[k] <= 0) { std::ostringstream oss; - oss << "Found a negative partial denominator: b[" << i << "] = " << b_[i] << "." + oss << "Found a negative partial denominator: b[" << k << "] = " << b_[k] << "." #ifndef BOOST_MATH_STANDALONE << " This means the integer type '" << boost::core::demangle(typeid(Z).name()) #else @@ -141,23 +148,15 @@ class simple_continued_fraction { } template - friend std::ostream& operator<<(std::ostream& out, simple_continued_fraction& scf); + friend std::ostream& operator<<(std::ostream& out, const simple_continued_fraction& scf); private: - const Real x_; std::vector b_; }; -template -std::ostream& operator<<(std::ostream& out, simple_continued_fraction& scf) { - constexpr const int p = std::numeric_limits::max_digits10; - if constexpr (p == 2147483647) { - out << std::setprecision(scf.x_.backend().precision()); - } else { - out << std::setprecision(p); - } - +BOOST_MATH_EXPORT template +std::ostream& operator<<(std::ostream& out, const simple_continued_fraction& scf) { out << "[" << scf.b_.front(); if (scf.b_.size() > 1) { @@ -173,5 +172,5 @@ std::ostream& operator<<(std::ostream& out, simple_continued_fraction& } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/stats.hpp b/include/boost/math/tools/stats.hpp index b57cc7951d..dff5102448 100644 --- a/include/boost/math/tools/stats.hpp +++ b/include/boost/math/tools/stats.hpp @@ -10,11 +10,13 @@ #pragma once #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ template class stats @@ -80,8 +82,7 @@ class stats }; } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/test_value.hpp b/include/boost/math/tools/test_value.hpp index c44fe05289..f9a4b42da5 100644 --- a/include/boost/math/tools/test_value.hpp +++ b/include/boost/math/tools/test_value.hpp @@ -30,8 +30,10 @@ #ifndef BOOST_MATH_STANDALONE #include #endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE // global int create_type(0); must be defined before including this file. @@ -87,6 +89,7 @@ inline T create_test_value(largest_float, const char* str, const std::false_type create_type = 3; #endif #if defined(BOOST_MATH_STANDALONE) + static_cast(str); static_assert(sizeof(T) == 0, "Can not create a test value using lexical cast of string in standalone mode"); return T(); #else diff --git a/include/boost/math/tools/toms748_solve.hpp b/include/boost/math/tools/toms748_solve.hpp index ed2d09444a..14661ab4d2 100644 --- a/include/boost/math/tools/toms748_solve.hpp +++ b/include/boost/math/tools/toms748_solve.hpp @@ -27,9 +27,9 @@ # define BOOST_MATH_LOG_COUNT(count) #endif -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ -template +BOOST_MATH_EXPORT template class eps_tolerance { public: @@ -65,7 +65,7 @@ struct equal_floor BOOST_MATH_GPU_ENABLED bool operator()(const T& a, const T& b) { BOOST_MATH_STD_USING - return (floor(a) == floor(b)) || (fabs((b-a)/b) < boost::math::tools::epsilon() * 2); + return (floor(a) == floor(b)) || (fabs((b-a)/b) < BOOST_MATH_NAMESPACE::tools::epsilon() * 2); } }; @@ -77,7 +77,7 @@ struct equal_ceil BOOST_MATH_GPU_ENABLED bool operator()(const T& a, const T& b) { BOOST_MATH_STD_USING - return (ceil(a) == ceil(b)) || (fabs((b - a) / b) < boost::math::tools::epsilon() * 2); + return (ceil(a) == ceil(b)) || (fabs((b - a) / b) < BOOST_MATH_NAMESPACE::tools::epsilon() * 2); } }; @@ -89,7 +89,7 @@ struct equal_nearest_integer BOOST_MATH_GPU_ENABLED bool operator()(const T& a, const T& b) { BOOST_MATH_STD_USING - return (floor(a + 0.5f) == floor(b + 0.5f)) || (fabs((b - a) / b) < boost::math::tools::epsilon() * 2); + return (floor(a + 0.5f) == floor(b + 0.5f)) || (fabs((b - a) / b) < BOOST_MATH_NAMESPACE::tools::epsilon() * 2); } }; @@ -147,7 +147,7 @@ BOOST_MATH_GPU_ENABLED void bracket(F f, T& a, T& b, T c, T& fa, T& fb, T& d, T& // // Non-zero fc, update the interval: // - if(boost::math::sign(fa) * boost::math::sign(fc) < 0) + if(BOOST_MATH_NAMESPACE::sign(fa) * BOOST_MATH_NAMESPACE::sign(fc) < 0) { d = b; fd = fb; @@ -233,7 +233,7 @@ BOOST_MATH_GPU_ENABLED T quadratic_interpolate(const T& a, const T& b, T const& // Determine the starting point of the Newton steps: // T c; - if(boost::math::sign(A) * boost::math::sign(fa) > 0) + if(BOOST_MATH_NAMESPACE::sign(A) * BOOST_MATH_NAMESPACE::sign(fa) > 0) { c = a; } @@ -306,8 +306,8 @@ BOOST_MATH_GPU_ENABLED T cubic_interpolate(const T& a, const T& b, const T& d, } // namespace detail -template -BOOST_MATH_GPU_ENABLED boost::math::pair toms748_solve(F f, const T& ax, const T& bx, const T& fax, const T& fbx, Tol tol, boost::math::uintmax_t& max_iter, const Policy& pol) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::pair toms748_solve(F f, const T& ax, const T& bx, const T& fax, const T& fbx, Tol tol, BOOST_MATH_NAMESPACE::uintmax_t& max_iter, const Policy& pol) { // // Main entry point and logic for Toms Algorithm 748 @@ -321,9 +321,9 @@ BOOST_MATH_GPU_ENABLED boost::math::pair toms748_solve(F f, const T& ax, c // Sanity check - are we allowed to iterate at all? // if (max_iter == 0) - return boost::math::make_pair(ax, bx); + return BOOST_MATH_NAMESPACE::make_pair(ax, bx); - boost::math::uintmax_t count = max_iter; + BOOST_MATH_NAMESPACE::uintmax_t count = max_iter; T a, b, fa, fb, c, u, fu, a0, b0, d, fd, e, fe; static const T mu = 0.5f; @@ -331,7 +331,7 @@ BOOST_MATH_GPU_ENABLED boost::math::pair toms748_solve(F f, const T& ax, c a = ax; b = bx; if(a >= b) - return boost::math::detail::pair_from_single(policies::raise_domain_error( + return BOOST_MATH_NAMESPACE::detail::pair_from_single(policies::raise_domain_error( function, "Parameters a and b out of order: a=%1%", a, pol)); fa = fax; @@ -344,11 +344,11 @@ BOOST_MATH_GPU_ENABLED boost::math::pair toms748_solve(F f, const T& ax, c b = a; else if(fb == 0) a = b; - return boost::math::make_pair(a, b); + return BOOST_MATH_NAMESPACE::make_pair(a, b); } - if(boost::math::sign(fa) * boost::math::sign(fb) > 0) - return boost::math::detail::pair_from_single(policies::raise_domain_error( + if(BOOST_MATH_NAMESPACE::sign(fa) * BOOST_MATH_NAMESPACE::sign(fb) > 0) + return BOOST_MATH_NAMESPACE::detail::pair_from_single(policies::raise_domain_error( function, "Parameters a and b do not bracket the root: a=%1%", a, pol)); // dummy value for fd, e and fe: @@ -486,34 +486,34 @@ BOOST_MATH_GPU_ENABLED boost::math::pair toms748_solve(F f, const T& ax, c a = b; } BOOST_MATH_LOG_COUNT(max_iter) - return boost::math::make_pair(a, b); + return BOOST_MATH_NAMESPACE::make_pair(a, b); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair toms748_solve(F f, const T& ax, const T& bx, const T& fax, const T& fbx, Tol tol, boost::math::uintmax_t& max_iter) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair toms748_solve(F f, const T& ax, const T& bx, const T& fax, const T& fbx, Tol tol, BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { return toms748_solve(f, ax, bx, fax, fbx, tol, max_iter, policies::policy<>()); } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair toms748_solve(F f, const T& ax, const T& bx, Tol tol, boost::math::uintmax_t& max_iter, const Policy& pol) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair toms748_solve(F f, const T& ax, const T& bx, Tol tol, BOOST_MATH_NAMESPACE::uintmax_t& max_iter, const Policy& pol) { if (max_iter <= 2) - return boost::math::make_pair(ax, bx); + return BOOST_MATH_NAMESPACE::make_pair(ax, bx); max_iter -= 2; - boost::math::pair r = toms748_solve(f, ax, bx, f(ax), f(bx), tol, max_iter, pol); + BOOST_MATH_NAMESPACE::pair r = toms748_solve(f, ax, bx, f(ax), f(bx), tol, max_iter, pol); max_iter += 2; return r; } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair toms748_solve(F f, const T& ax, const T& bx, Tol tol, boost::math::uintmax_t& max_iter) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair toms748_solve(F f, const T& ax, const T& bx, Tol tol, BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { return toms748_solve(f, ax, bx, tol, max_iter, policies::policy<>()); } -template -BOOST_MATH_GPU_ENABLED boost::math::pair bracket_and_solve_root(F f, const T& guess, T factor, bool rising, Tol tol, boost::math::uintmax_t& max_iter, const Policy& pol) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED BOOST_MATH_NAMESPACE::pair bracket_and_solve_root(F f, const T& guess, T factor, bool rising, Tol tol, BOOST_MATH_NAMESPACE::uintmax_t& max_iter, const Policy& pol) { BOOST_MATH_STD_USING constexpr auto function = "boost::math::tools::bracket_and_solve_root<%1%>"; @@ -527,7 +527,7 @@ BOOST_MATH_GPU_ENABLED boost::math::pair bracket_and_solve_root(F f, const // // Set up invocation count: // - boost::math::uintmax_t count = max_iter - 1; + BOOST_MATH_NAMESPACE::uintmax_t count = max_iter - 1; int step = 32; @@ -537,10 +537,10 @@ BOOST_MATH_GPU_ENABLED boost::math::pair bracket_and_solve_root(F f, const // Zero is to the right of b, so walk upwards // until we find it: // - while((boost::math::sign)(fb) == (boost::math::sign)(fa)) + while((BOOST_MATH_NAMESPACE::sign)(fb) == (BOOST_MATH_NAMESPACE::sign)(fa)) { if(count == 0) - return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol)); + return BOOST_MATH_NAMESPACE::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol)); // // Heuristic: normally it's best not to increase the step sizes as we'll just end up // with a really wide range to search for the root. However, if the initial guess was *really* @@ -570,17 +570,17 @@ BOOST_MATH_GPU_ENABLED boost::math::pair bracket_and_solve_root(F f, const // Zero is to the left of a, so walk downwards // until we find it: // - while((boost::math::sign)(fb) == (boost::math::sign)(fa)) + while((BOOST_MATH_NAMESPACE::sign)(fb) == (BOOST_MATH_NAMESPACE::sign)(fa)) { if(fabs(a) < tools::min_value()) { // Escape route just in case the answer is zero! max_iter -= count; max_iter += 1; - return a > 0 ? boost::math::make_pair(T(0), T(a)) : boost::math::make_pair(T(a), T(0)); + return a > 0 ? BOOST_MATH_NAMESPACE::make_pair(T(0), T(a)) : BOOST_MATH_NAMESPACE::make_pair(T(a), T(0)); } if(count == 0) - return boost::math::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol)); + return BOOST_MATH_NAMESPACE::detail::pair_from_single(policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol)); // // Heuristic: normally it's best not to increase the step sizes as we'll just end up // with a really wide range to search for the root. However, if the initial guess was *really* @@ -606,7 +606,7 @@ BOOST_MATH_GPU_ENABLED boost::math::pair bracket_and_solve_root(F f, const } max_iter -= count; max_iter += 1; - boost::math::pair r = toms748_solve( + BOOST_MATH_NAMESPACE::pair r = toms748_solve( f, (a < 0 ? b : a), (a < 0 ? a : b), @@ -621,15 +621,14 @@ BOOST_MATH_GPU_ENABLED boost::math::pair bracket_and_solve_root(F f, const return r; } -template -BOOST_MATH_GPU_ENABLED inline boost::math::pair bracket_and_solve_root(F f, const T& guess, const T& factor, bool rising, Tol tol, boost::math::uintmax_t& max_iter) +BOOST_MATH_EXPORT template +BOOST_MATH_GPU_ENABLED inline BOOST_MATH_NAMESPACE::pair bracket_and_solve_root(F f, const T& guess, const T& factor, bool rising, Tol tol, BOOST_MATH_NAMESPACE::uintmax_t& max_iter) { return bracket_and_solve_root(f, guess, factor, rising, tol, max_iter, policies::policy<>()); } } // namespace tools -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_SOLVE_ROOT_HPP diff --git a/include/boost/math/tools/traits.hpp b/include/boost/math/tools/traits.hpp index e909881e61..f9b6a9ac9b 100644 --- a/include/boost/math/tools/traits.hpp +++ b/include/boost/math/tools/traits.hpp @@ -25,9 +25,13 @@ as defined above, and has member functions "scale" and "location". #pragma once #endif +#include + +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ namespace detail{ @@ -56,13 +60,13 @@ BOOST_MATH_HAS_NAMED_TRAIT(has_backend_type, backend_type) // C++17-esque helpers #if defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304L template -constexpr bool has_value_type_v = has_value_type::value; +BOOST_MATH_INLINE_CONSTEXPR bool has_value_type_v = has_value_type::value; template -constexpr bool has_policy_type_v = has_policy_type::value; +BOOST_MATH_INLINE_CONSTEXPR bool has_policy_type_v = has_policy_type::value; template -constexpr bool has_backend_type_v = has_backend_type::value; +BOOST_MATH_INLINE_CONSTEXPR bool has_backend_type_v = has_backend_type::value; #endif template @@ -125,15 +129,15 @@ struct is_scaled_distribution_helper template struct is_scaled_distribution_imp { - static constexpr bool value = (::boost::math::tools::detail::is_scaled_distribution_helper::value>::value); + static constexpr bool value = (::BOOST_MATH_NAMESPACE::tools::detail::is_scaled_distribution_helper::value>::value); }; } // namespace detail -template struct is_distribution : public std::integral_constant::value> {}; -template struct is_scaled_distribution : public std::integral_constant::value> {}; +template struct is_distribution : public std::integral_constant::value> {}; +template struct is_scaled_distribution : public std::integral_constant::value> {}; -}}} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/tuple.hpp b/include/boost/math/tools/tuple.hpp index dcc763e37a..704aa54671 100644 --- a/include/boost/math/tools/tuple.hpp +++ b/include/boost/math/tools/tuple.hpp @@ -15,32 +15,31 @@ #include #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -using cuda::std::pair; -using cuda::std::tuple; +BOOST_MATH_EXPORT using cuda::std::pair; +BOOST_MATH_EXPORT using cuda::std::tuple; -using cuda::std::make_pair; +BOOST_MATH_EXPORT using cuda::std::make_pair; -using cuda::std::tie; -using cuda::std::get; +BOOST_MATH_EXPORT using cuda::std::tie; +BOOST_MATH_EXPORT using cuda::std::get; -using cuda::std::tuple_size; -using cuda::std::tuple_element; +BOOST_MATH_EXPORT using cuda::std::tuple_size; +BOOST_MATH_EXPORT using cuda::std::tuple_element; namespace detail { template -BOOST_MATH_GPU_ENABLED T&& forward(boost::math::remove_reference_t& arg) noexcept +BOOST_MATH_GPU_ENABLED T&& forward(BOOST_MATH_NAMESPACE::remove_reference_t& arg) noexcept { return static_cast(arg); } template -BOOST_MATH_GPU_ENABLED T&& forward(boost::math::remove_reference_t&& arg) noexcept +BOOST_MATH_GPU_ENABLED T&& forward(BOOST_MATH_NAMESPACE::remove_reference_t&& arg) noexcept { - static_assert(!boost::math::is_lvalue_reference::value, "Cannot forward an rvalue as an lvalue."); + static_assert(!BOOST_MATH_NAMESPACE::is_lvalue_reference::value, "Cannot forward an rvalue as an lvalue."); return static_cast(arg); } @@ -49,39 +48,38 @@ BOOST_MATH_GPU_ENABLED T&& forward(boost::math::remove_reference_t&& arg) noe template BOOST_MATH_GPU_ENABLED auto make_tuple(T&& t, Ts&&... ts) { - return cuda::std::tuple, boost::math::decay_t...>( - boost::math::detail::forward(t), boost::math::detail::forward(ts)... + return cuda::std::tuple, BOOST_MATH_NAMESPACE::decay_t...>( + BOOST_MATH_NAMESPACE::detail::forward(t), BOOST_MATH_NAMESPACE::detail::forward(ts)... ); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN -using ::std::tuple; -using ::std::pair; +BOOST_MATH_EXPORT using ::std::tuple; +BOOST_MATH_EXPORT using ::std::pair; // [6.1.3.2] Tuple creation functions -using ::std::ignore; -using ::std::make_tuple; -using ::std::tie; -using ::std::get; +BOOST_MATH_EXPORT using ::std::ignore; +BOOST_MATH_EXPORT using ::std::make_tuple; +BOOST_MATH_EXPORT using ::std::tie; +BOOST_MATH_EXPORT using ::std::get; // [6.1.3.3] Tuple helper classes -using ::std::tuple_size; -using ::std::tuple_element; +BOOST_MATH_EXPORT using ::std::tuple_size; +BOOST_MATH_EXPORT using ::std::tuple_element; // Pair helpers -using ::std::make_pair; +BOOST_MATH_EXPORT using ::std::make_pair; -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_ENABLE_CUDA diff --git a/include/boost/math/tools/type_traits.hpp b/include/boost/math/tools/type_traits.hpp index 951f3a1bf8..60916cd653 100644 --- a/include/boost/math/tools/type_traits.hpp +++ b/include/boost/math/tools/type_traits.hpp @@ -16,474 +16,473 @@ #include -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN // Helper classes -using cuda::std::integral_constant; -using cuda::std::true_type; -using cuda::std::false_type; +BOOST_MATH_EXPORT using cuda::std::integral_constant; +BOOST_MATH_EXPORT using cuda::std::true_type; +BOOST_MATH_EXPORT using cuda::std::false_type; // Primary type categories -using cuda::std::is_void; -using cuda::std::is_null_pointer; -using cuda::std::is_integral; -using cuda::std::is_floating_point; -using cuda::std::is_array; -using cuda::std::is_enum; -using cuda::std::is_union; -using cuda::std::is_class; -using cuda::std::is_function; -using cuda::std::is_pointer; -using cuda::std::is_lvalue_reference; -using cuda::std::is_rvalue_reference; -using cuda::std::is_member_object_pointer; -using cuda::std::is_member_function_pointer; +BOOST_MATH_EXPORT using cuda::std::is_void; +BOOST_MATH_EXPORT using cuda::std::is_null_pointer; +BOOST_MATH_EXPORT using cuda::std::is_integral; +BOOST_MATH_EXPORT using cuda::std::is_floating_point; +BOOST_MATH_EXPORT using cuda::std::is_array; +BOOST_MATH_EXPORT using cuda::std::is_enum; +BOOST_MATH_EXPORT using cuda::std::is_union; +BOOST_MATH_EXPORT using cuda::std::is_class; +BOOST_MATH_EXPORT using cuda::std::is_function; +BOOST_MATH_EXPORT using cuda::std::is_pointer; +BOOST_MATH_EXPORT using cuda::std::is_lvalue_reference; +BOOST_MATH_EXPORT using cuda::std::is_rvalue_reference; +BOOST_MATH_EXPORT using cuda::std::is_member_object_pointer; +BOOST_MATH_EXPORT using cuda::std::is_member_function_pointer; // Composite Type Categories -using cuda::std::is_fundamental; -using cuda::std::is_arithmetic; -using cuda::std::is_scalar; -using cuda::std::is_object; -using cuda::std::is_compound; -using cuda::std::is_reference; -using cuda::std::is_member_pointer; +BOOST_MATH_EXPORT using cuda::std::is_fundamental; +BOOST_MATH_EXPORT using cuda::std::is_arithmetic; +BOOST_MATH_EXPORT using cuda::std::is_scalar; +BOOST_MATH_EXPORT using cuda::std::is_object; +BOOST_MATH_EXPORT using cuda::std::is_compound; +BOOST_MATH_EXPORT using cuda::std::is_reference; +BOOST_MATH_EXPORT using cuda::std::is_member_pointer; // Type properties -using cuda::std::is_const; -using cuda::std::is_volatile; -using cuda::std::is_trivially_copyable; -using cuda::std::is_standard_layout; -using cuda::std::is_empty; -using cuda::std::is_polymorphic; -using cuda::std::is_abstract; -using cuda::std::is_final; -using cuda::std::is_signed; -using cuda::std::is_unsigned; +BOOST_MATH_EXPORT using cuda::std::is_const; +BOOST_MATH_EXPORT using cuda::std::is_volatile; +BOOST_MATH_EXPORT using cuda::std::is_trivially_copyable; +BOOST_MATH_EXPORT using cuda::std::is_standard_layout; +BOOST_MATH_EXPORT using cuda::std::is_empty; +BOOST_MATH_EXPORT using cuda::std::is_polymorphic; +BOOST_MATH_EXPORT using cuda::std::is_abstract; +BOOST_MATH_EXPORT using cuda::std::is_final; +BOOST_MATH_EXPORT using cuda::std::is_signed; +BOOST_MATH_EXPORT using cuda::std::is_unsigned; // Supported Operations -using cuda::std::is_constructible; -using cuda::std::is_trivially_constructible; -using cuda::std::is_nothrow_constructible; +BOOST_MATH_EXPORT using cuda::std::is_constructible; +BOOST_MATH_EXPORT using cuda::std::is_trivially_constructible; +BOOST_MATH_EXPORT using cuda::std::is_nothrow_constructible; -using cuda::std::is_default_constructible; -using cuda::std::is_trivially_default_constructible; -using cuda::std::is_nothrow_default_constructible; +BOOST_MATH_EXPORT using cuda::std::is_default_constructible; +BOOST_MATH_EXPORT using cuda::std::is_trivially_default_constructible; +BOOST_MATH_EXPORT using cuda::std::is_nothrow_default_constructible; -using cuda::std::is_copy_constructible; -using cuda::std::is_trivially_copy_constructible; -using cuda::std::is_nothrow_copy_constructible; +BOOST_MATH_EXPORT using cuda::std::is_copy_constructible; +BOOST_MATH_EXPORT using cuda::std::is_trivially_copy_constructible; +BOOST_MATH_EXPORT using cuda::std::is_nothrow_copy_constructible; -using cuda::std::is_move_constructible; -using cuda::std::is_trivially_move_constructible; -using cuda::std::is_nothrow_move_constructible; +BOOST_MATH_EXPORT using cuda::std::is_move_constructible; +BOOST_MATH_EXPORT using cuda::std::is_trivially_move_constructible; +BOOST_MATH_EXPORT using cuda::std::is_nothrow_move_constructible; -using cuda::std::is_assignable; -using cuda::std::is_trivially_assignable; -using cuda::std::is_nothrow_assignable; +BOOST_MATH_EXPORT using cuda::std::is_assignable; +BOOST_MATH_EXPORT using cuda::std::is_trivially_assignable; +BOOST_MATH_EXPORT using cuda::std::is_nothrow_assignable; -using cuda::std::is_copy_assignable; -using cuda::std::is_trivially_copy_assignable; -using cuda::std::is_nothrow_copy_assignable; +BOOST_MATH_EXPORT using cuda::std::is_copy_assignable; +BOOST_MATH_EXPORT using cuda::std::is_trivially_copy_assignable; +BOOST_MATH_EXPORT using cuda::std::is_nothrow_copy_assignable; -using cuda::std::is_move_assignable; -using cuda::std::is_trivially_move_assignable; -using cuda::std::is_nothrow_move_assignable; +BOOST_MATH_EXPORT using cuda::std::is_move_assignable; +BOOST_MATH_EXPORT using cuda::std::is_trivially_move_assignable; +BOOST_MATH_EXPORT using cuda::std::is_nothrow_move_assignable; -using cuda::std::is_destructible; -using cuda::std::is_trivially_destructible; -using cuda::std::is_nothrow_destructible; +BOOST_MATH_EXPORT using cuda::std::is_destructible; +BOOST_MATH_EXPORT using cuda::std::is_trivially_destructible; +BOOST_MATH_EXPORT using cuda::std::is_nothrow_destructible; -using cuda::std::has_virtual_destructor; +BOOST_MATH_EXPORT using cuda::std::has_virtual_destructor; // Property Queries -using cuda::std::alignment_of; -using cuda::std::rank; -using cuda::std::extent; +BOOST_MATH_EXPORT using cuda::std::alignment_of; +BOOST_MATH_EXPORT using cuda::std::rank; +BOOST_MATH_EXPORT using cuda::std::extent; // Type Relationships -using cuda::std::is_same; -using cuda::std::is_base_of; -using cuda::std::is_convertible; +BOOST_MATH_EXPORT using cuda::std::is_same; +BOOST_MATH_EXPORT using cuda::std::is_base_of; +BOOST_MATH_EXPORT using cuda::std::is_convertible; // Const-volatility specifiers -using cuda::std::remove_cv; -using cuda::std::remove_cv_t; -using cuda::std::remove_const; -using cuda::std::remove_const_t; -using cuda::std::remove_volatile; -using cuda::std::remove_volatile_t; -using cuda::std::add_cv; -using cuda::std::add_cv_t; -using cuda::std::add_const; -using cuda::std::add_const_t; -using cuda::std::add_volatile; -using cuda::std::add_volatile_t; +BOOST_MATH_EXPORT using cuda::std::remove_cv; +BOOST_MATH_EXPORT using cuda::std::remove_cv_t; +BOOST_MATH_EXPORT using cuda::std::remove_const; +BOOST_MATH_EXPORT using cuda::std::remove_const_t; +BOOST_MATH_EXPORT using cuda::std::remove_volatile; +BOOST_MATH_EXPORT using cuda::std::remove_volatile_t; +BOOST_MATH_EXPORT using cuda::std::add_cv; +BOOST_MATH_EXPORT using cuda::std::add_cv_t; +BOOST_MATH_EXPORT using cuda::std::add_const; +BOOST_MATH_EXPORT using cuda::std::add_const_t; +BOOST_MATH_EXPORT using cuda::std::add_volatile; +BOOST_MATH_EXPORT using cuda::std::add_volatile_t; // References -using cuda::std::remove_reference; -using cuda::std::remove_reference_t; -using cuda::std::add_lvalue_reference; -using cuda::std::add_lvalue_reference_t; -using cuda::std::add_rvalue_reference; -using cuda::std::add_rvalue_reference_t; +BOOST_MATH_EXPORT using cuda::std::remove_reference; +BOOST_MATH_EXPORT using cuda::std::remove_reference_t; +BOOST_MATH_EXPORT using cuda::std::add_lvalue_reference; +BOOST_MATH_EXPORT using cuda::std::add_lvalue_reference_t; +BOOST_MATH_EXPORT using cuda::std::add_rvalue_reference; +BOOST_MATH_EXPORT using cuda::std::add_rvalue_reference_t; // Pointers -using cuda::std::remove_pointer; -using cuda::std::remove_pointer_t; -using cuda::std::add_pointer; -using cuda::std::add_pointer_t; +BOOST_MATH_EXPORT using cuda::std::remove_pointer; +BOOST_MATH_EXPORT using cuda::std::remove_pointer_t; +BOOST_MATH_EXPORT using cuda::std::add_pointer; +BOOST_MATH_EXPORT using cuda::std::add_pointer_t; // Sign Modifiers -using cuda::std::make_signed; -using cuda::std::make_signed_t; -using cuda::std::make_unsigned; -using cuda::std::make_unsigned_t; +BOOST_MATH_EXPORT using cuda::std::make_signed; +BOOST_MATH_EXPORT using cuda::std::make_signed_t; +BOOST_MATH_EXPORT using cuda::std::make_unsigned; +BOOST_MATH_EXPORT using cuda::std::make_unsigned_t; // Arrays -using cuda::std::remove_extent; -using cuda::std::remove_extent_t; -using cuda::std::remove_all_extents; -using cuda::std::remove_all_extents_t; +BOOST_MATH_EXPORT using cuda::std::remove_extent; +BOOST_MATH_EXPORT using cuda::std::remove_extent_t; +BOOST_MATH_EXPORT using cuda::std::remove_all_extents; +BOOST_MATH_EXPORT using cuda::std::remove_all_extents_t; // Misc transformations -using cuda::std::decay; -using cuda::std::decay_t; -using cuda::std::enable_if; -using cuda::std::enable_if_t; -using cuda::std::conditional; -using cuda::std::conditional_t; -using cuda::std::common_type; -using cuda::std::common_type_t; -using cuda::std::underlying_type; -using cuda::std::underlying_type_t; +BOOST_MATH_EXPORT using cuda::std::decay; +BOOST_MATH_EXPORT using cuda::std::decay_t; +BOOST_MATH_EXPORT using cuda::std::enable_if; +BOOST_MATH_EXPORT using cuda::std::enable_if_t; +BOOST_MATH_EXPORT using cuda::std::conditional; +BOOST_MATH_EXPORT using cuda::std::conditional_t; +BOOST_MATH_EXPORT using cuda::std::common_type; +BOOST_MATH_EXPORT using cuda::std::common_type_t; +BOOST_MATH_EXPORT using cuda::std::underlying_type; +BOOST_MATH_EXPORT using cuda::std::underlying_type_t; #else // STD versions +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN // Helper classes -using std::integral_constant; -using std::true_type; -using std::false_type; +BOOST_MATH_EXPORT using std::integral_constant; +BOOST_MATH_EXPORT using std::true_type; +BOOST_MATH_EXPORT using std::false_type; // Primary type categories -using std::is_void; -using std::is_null_pointer; -using std::is_integral; -using std::is_floating_point; -using std::is_array; -using std::is_enum; -using std::is_union; -using std::is_class; -using std::is_function; -using std::is_pointer; -using std::is_lvalue_reference; -using std::is_rvalue_reference; -using std::is_member_object_pointer; -using std::is_member_function_pointer; +BOOST_MATH_EXPORT using std::is_void; +BOOST_MATH_EXPORT using std::is_null_pointer; +BOOST_MATH_EXPORT using std::is_integral; +BOOST_MATH_EXPORT using std::is_floating_point; +BOOST_MATH_EXPORT using std::is_array; +BOOST_MATH_EXPORT using std::is_enum; +BOOST_MATH_EXPORT using std::is_union; +BOOST_MATH_EXPORT using std::is_class; +BOOST_MATH_EXPORT using std::is_function; +BOOST_MATH_EXPORT using std::is_pointer; +BOOST_MATH_EXPORT using std::is_lvalue_reference; +BOOST_MATH_EXPORT using std::is_rvalue_reference; +BOOST_MATH_EXPORT using std::is_member_object_pointer; +BOOST_MATH_EXPORT using std::is_member_function_pointer; // Composite Type Categories -using std::is_fundamental; -using std::is_arithmetic; -using std::is_scalar; -using std::is_object; -using std::is_compound; -using std::is_reference; -using std::is_member_pointer; +BOOST_MATH_EXPORT using std::is_fundamental; +BOOST_MATH_EXPORT using std::is_arithmetic; +BOOST_MATH_EXPORT using std::is_scalar; +BOOST_MATH_EXPORT using std::is_object; +BOOST_MATH_EXPORT using std::is_compound; +BOOST_MATH_EXPORT using std::is_reference; +BOOST_MATH_EXPORT using std::is_member_pointer; // Type properties -using std::is_const; -using std::is_volatile; -using std::is_trivially_copyable; -using std::is_standard_layout; -using std::is_empty; -using std::is_polymorphic; -using std::is_abstract; -using std::is_final; -using std::is_signed; -using std::is_unsigned; +BOOST_MATH_EXPORT using std::is_const; +BOOST_MATH_EXPORT using std::is_volatile; +BOOST_MATH_EXPORT using std::is_trivially_copyable; +BOOST_MATH_EXPORT using std::is_standard_layout; +BOOST_MATH_EXPORT using std::is_empty; +BOOST_MATH_EXPORT using std::is_polymorphic; +BOOST_MATH_EXPORT using std::is_abstract; +BOOST_MATH_EXPORT using std::is_final; +BOOST_MATH_EXPORT using std::is_signed; +BOOST_MATH_EXPORT using std::is_unsigned; // Supported Operations -using std::is_constructible; -using std::is_trivially_constructible; -using std::is_nothrow_constructible; +BOOST_MATH_EXPORT using std::is_constructible; +BOOST_MATH_EXPORT using std::is_trivially_constructible; +BOOST_MATH_EXPORT using std::is_nothrow_constructible; -using std::is_default_constructible; -using std::is_trivially_default_constructible; -using std::is_nothrow_default_constructible; +BOOST_MATH_EXPORT using std::is_default_constructible; +BOOST_MATH_EXPORT using std::is_trivially_default_constructible; +BOOST_MATH_EXPORT using std::is_nothrow_default_constructible; -using std::is_copy_constructible; -using std::is_trivially_copy_constructible; -using std::is_nothrow_copy_constructible; +BOOST_MATH_EXPORT using std::is_copy_constructible; +BOOST_MATH_EXPORT using std::is_trivially_copy_constructible; +BOOST_MATH_EXPORT using std::is_nothrow_copy_constructible; -using std::is_move_constructible; -using std::is_trivially_move_constructible; -using std::is_nothrow_move_constructible; +BOOST_MATH_EXPORT using std::is_move_constructible; +BOOST_MATH_EXPORT using std::is_trivially_move_constructible; +BOOST_MATH_EXPORT using std::is_nothrow_move_constructible; -using std::is_assignable; -using std::is_trivially_assignable; -using std::is_nothrow_assignable; +BOOST_MATH_EXPORT using std::is_assignable; +BOOST_MATH_EXPORT using std::is_trivially_assignable; +BOOST_MATH_EXPORT using std::is_nothrow_assignable; -using std::is_copy_assignable; -using std::is_trivially_copy_assignable; -using std::is_nothrow_copy_assignable; +BOOST_MATH_EXPORT using std::is_copy_assignable; +BOOST_MATH_EXPORT using std::is_trivially_copy_assignable; +BOOST_MATH_EXPORT using std::is_nothrow_copy_assignable; -using std::is_move_assignable; -using std::is_trivially_move_assignable; -using std::is_nothrow_move_assignable; +BOOST_MATH_EXPORT using std::is_move_assignable; +BOOST_MATH_EXPORT using std::is_trivially_move_assignable; +BOOST_MATH_EXPORT using std::is_nothrow_move_assignable; -using std::is_destructible; -using std::is_trivially_destructible; -using std::is_nothrow_destructible; +BOOST_MATH_EXPORT using std::is_destructible; +BOOST_MATH_EXPORT using std::is_trivially_destructible; +BOOST_MATH_EXPORT using std::is_nothrow_destructible; -using std::has_virtual_destructor; +BOOST_MATH_EXPORT using std::has_virtual_destructor; // Property Queries -using std::alignment_of; -using std::rank; -using std::extent; +BOOST_MATH_EXPORT using std::alignment_of; +BOOST_MATH_EXPORT using std::rank; +BOOST_MATH_EXPORT using std::extent; // Type Relationships -using std::is_same; -using std::is_base_of; -using std::is_convertible; +BOOST_MATH_EXPORT using std::is_same; +BOOST_MATH_EXPORT using std::is_base_of; +BOOST_MATH_EXPORT using std::is_convertible; // Const-volatility specifiers -using std::remove_cv; -using std::remove_cv_t; -using std::remove_const; -using std::remove_const_t; -using std::remove_volatile; -using std::remove_volatile_t; -using std::add_cv; -using std::add_cv_t; -using std::add_const; -using std::add_const_t; -using std::add_volatile; -using std::add_volatile_t; +BOOST_MATH_EXPORT using std::remove_cv; +BOOST_MATH_EXPORT using std::remove_cv_t; +BOOST_MATH_EXPORT using std::remove_const; +BOOST_MATH_EXPORT using std::remove_const_t; +BOOST_MATH_EXPORT using std::remove_volatile; +BOOST_MATH_EXPORT using std::remove_volatile_t; +BOOST_MATH_EXPORT using std::add_cv; +BOOST_MATH_EXPORT using std::add_cv_t; +BOOST_MATH_EXPORT using std::add_const; +BOOST_MATH_EXPORT using std::add_const_t; +BOOST_MATH_EXPORT using std::add_volatile; +BOOST_MATH_EXPORT using std::add_volatile_t; // References -using std::remove_reference; -using std::remove_reference_t; -using std::add_lvalue_reference; -using std::add_lvalue_reference_t; -using std::add_rvalue_reference; -using std::add_rvalue_reference_t; +BOOST_MATH_EXPORT using std::remove_reference; +BOOST_MATH_EXPORT using std::remove_reference_t; +BOOST_MATH_EXPORT using std::add_lvalue_reference; +BOOST_MATH_EXPORT using std::add_lvalue_reference_t; +BOOST_MATH_EXPORT using std::add_rvalue_reference; +BOOST_MATH_EXPORT using std::add_rvalue_reference_t; // Pointers -using std::remove_pointer; -using std::remove_pointer_t; -using std::add_pointer; -using std::add_pointer_t; +BOOST_MATH_EXPORT using std::remove_pointer; +BOOST_MATH_EXPORT using std::remove_pointer_t; +BOOST_MATH_EXPORT using std::add_pointer; +BOOST_MATH_EXPORT using std::add_pointer_t; // Sign Modifiers -using std::make_signed; -using std::make_signed_t; -using std::make_unsigned; -using std::make_unsigned_t; +BOOST_MATH_EXPORT using std::make_signed; +BOOST_MATH_EXPORT using std::make_signed_t; +BOOST_MATH_EXPORT using std::make_unsigned; +BOOST_MATH_EXPORT using std::make_unsigned_t; // Arrays -using std::remove_extent; -using std::remove_extent_t; -using std::remove_all_extents; -using std::remove_all_extents_t; +BOOST_MATH_EXPORT using std::remove_extent; +BOOST_MATH_EXPORT using std::remove_extent_t; +BOOST_MATH_EXPORT using std::remove_all_extents; +BOOST_MATH_EXPORT using std::remove_all_extents_t; // Misc transformations -using std::decay; -using std::decay_t; -using std::enable_if; -using std::enable_if_t; -using std::conditional; -using std::conditional_t; -using std::common_type; -using std::common_type_t; -using std::underlying_type; -using std::underlying_type_t; +BOOST_MATH_EXPORT using std::decay; +BOOST_MATH_EXPORT using std::decay_t; +BOOST_MATH_EXPORT using std::enable_if; +BOOST_MATH_EXPORT using std::enable_if_t; +BOOST_MATH_EXPORT using std::conditional; +BOOST_MATH_EXPORT using std::conditional_t; +BOOST_MATH_EXPORT using std::common_type; +BOOST_MATH_EXPORT using std::common_type_t; +BOOST_MATH_EXPORT using std::underlying_type; +BOOST_MATH_EXPORT using std::underlying_type_t; #endif -template -using bool_constant = boost::math::integral_constant; +BOOST_MATH_EXPORT template +using bool_constant = BOOST_MATH_NAMESPACE::integral_constant; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_void_v = boost::math::is_void::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_void_v = BOOST_MATH_NAMESPACE::is_void::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_null_pointer_v = boost::math::is_null_pointer::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_null_pointer_v = BOOST_MATH_NAMESPACE::is_null_pointer::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_integral_v = boost::math::is_integral::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_integral_v = BOOST_MATH_NAMESPACE::is_integral::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_floating_point_v = boost::math::is_floating_point::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_floating_point_v = BOOST_MATH_NAMESPACE::is_floating_point::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_array_v = boost::math::is_array::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_array_v = BOOST_MATH_NAMESPACE::is_array::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_enum_v = boost::math::is_enum::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_enum_v = BOOST_MATH_NAMESPACE::is_enum::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_union_v = boost::math::is_union::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_union_v = BOOST_MATH_NAMESPACE::is_union::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_class_v = boost::math::is_class::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_class_v = BOOST_MATH_NAMESPACE::is_class::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_function_v = boost::math::is_function::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_function_v = BOOST_MATH_NAMESPACE::is_function::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_pointer_v = boost::math::is_pointer::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_pointer_v = BOOST_MATH_NAMESPACE::is_pointer::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_lvalue_reference_v = boost::math::is_lvalue_reference::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_lvalue_reference_v = BOOST_MATH_NAMESPACE::is_lvalue_reference::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_rvalue_reference_v = boost::math::is_rvalue_reference::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_rvalue_reference_v = BOOST_MATH_NAMESPACE::is_rvalue_reference::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_member_object_pointer_v = boost::math::is_member_object_pointer::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_member_object_pointer_v = BOOST_MATH_NAMESPACE::is_member_object_pointer::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_member_function_pointer_v = boost::math::is_member_function_pointer::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_member_function_pointer_v = BOOST_MATH_NAMESPACE::is_member_function_pointer::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_fundamental_v = boost::math::is_fundamental::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_fundamental_v = BOOST_MATH_NAMESPACE::is_fundamental::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_arithmetic_v = boost::math::is_arithmetic::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_arithmetic_v = BOOST_MATH_NAMESPACE::is_arithmetic::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_scalar_v = boost::math::is_scalar::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_scalar_v = BOOST_MATH_NAMESPACE::is_scalar::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_object_v = boost::math::is_object::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_object_v = BOOST_MATH_NAMESPACE::is_object::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_compound_v = boost::math::is_compound::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_compound_v = BOOST_MATH_NAMESPACE::is_compound::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_reference_v = boost::math::is_reference::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_reference_v = BOOST_MATH_NAMESPACE::is_reference::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_member_pointer_v = boost::math::is_member_pointer::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_member_pointer_v = BOOST_MATH_NAMESPACE::is_member_pointer::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_const_v = boost::math::is_const::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_const_v = BOOST_MATH_NAMESPACE::is_const::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_volatile_v = boost::math::is_volatile::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_volatile_v = BOOST_MATH_NAMESPACE::is_volatile::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_copyable_v = boost::math::is_trivially_copyable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_copyable_v = BOOST_MATH_NAMESPACE::is_trivially_copyable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_standard_layout_v = boost::math::is_standard_layout::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_standard_layout_v = BOOST_MATH_NAMESPACE::is_standard_layout::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_empty_v = boost::math::is_empty::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_empty_v = BOOST_MATH_NAMESPACE::is_empty::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_polymorphic_v = boost::math::is_polymorphic::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_polymorphic_v = BOOST_MATH_NAMESPACE::is_polymorphic::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_abstract_v = boost::math::is_abstract::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_abstract_v = BOOST_MATH_NAMESPACE::is_abstract::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_final_v = boost::math::is_final::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_final_v = BOOST_MATH_NAMESPACE::is_final::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_signed_v = boost::math::is_signed::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_signed_v = BOOST_MATH_NAMESPACE::is_signed::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_unsigned_v = boost::math::is_unsigned::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_unsigned_v = BOOST_MATH_NAMESPACE::is_unsigned::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_constructible_v = boost::math::is_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_constructible_v = BOOST_MATH_NAMESPACE::is_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_constructible_v = boost::math::is_trivially_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_constructible_v = BOOST_MATH_NAMESPACE::is_trivially_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_constructible_v = boost::math::is_nothrow_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_constructible_v = BOOST_MATH_NAMESPACE::is_nothrow_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_default_constructible_v = boost::math::is_default_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_default_constructible_v = BOOST_MATH_NAMESPACE::is_default_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_default_constructible_v = boost::math::is_trivially_default_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_default_constructible_v = BOOST_MATH_NAMESPACE::is_trivially_default_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_default_constructible_v = boost::math::is_nothrow_default_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_default_constructible_v = BOOST_MATH_NAMESPACE::is_nothrow_default_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_copy_constructible_v = boost::math::is_copy_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_copy_constructible_v = BOOST_MATH_NAMESPACE::is_copy_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_copy_constructible_v = boost::math::is_trivially_copy_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_copy_constructible_v = BOOST_MATH_NAMESPACE::is_trivially_copy_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_copy_constructible_v = boost::math::is_nothrow_copy_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_copy_constructible_v = BOOST_MATH_NAMESPACE::is_nothrow_copy_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_move_constructible_v = boost::math::is_move_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_move_constructible_v = BOOST_MATH_NAMESPACE::is_move_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_move_constructible_v = boost::math::is_trivially_move_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_move_constructible_v = BOOST_MATH_NAMESPACE::is_trivially_move_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_move_constructible_v = boost::math::is_nothrow_move_constructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_move_constructible_v = BOOST_MATH_NAMESPACE::is_nothrow_move_constructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_assignable_v = boost::math::is_assignable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_assignable_v = BOOST_MATH_NAMESPACE::is_assignable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_assignable_v = boost::math::is_trivially_assignable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_assignable_v = BOOST_MATH_NAMESPACE::is_trivially_assignable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_assignable_v = boost::math::is_nothrow_assignable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_assignable_v = BOOST_MATH_NAMESPACE::is_nothrow_assignable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_copy_assignable_v = boost::math::is_copy_assignable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_copy_assignable_v = BOOST_MATH_NAMESPACE::is_copy_assignable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_copy_assignable_v = boost::math::is_trivially_copy_assignable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_copy_assignable_v = BOOST_MATH_NAMESPACE::is_trivially_copy_assignable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_copy_assignable_v = boost::math::is_nothrow_copy_assignable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_copy_assignable_v = BOOST_MATH_NAMESPACE::is_nothrow_copy_assignable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_move_assignable_v = boost::math::is_move_assignable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_move_assignable_v = BOOST_MATH_NAMESPACE::is_move_assignable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_move_assignable_v = boost::math::is_trivially_move_assignable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_move_assignable_v = BOOST_MATH_NAMESPACE::is_trivially_move_assignable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_move_assignable_v = boost::math::is_nothrow_move_assignable::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_move_assignable_v = BOOST_MATH_NAMESPACE::is_nothrow_move_assignable::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_destructible_v = boost::math::is_destructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_destructible_v = BOOST_MATH_NAMESPACE::is_destructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_destructible_v = boost::math::is_trivially_destructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_trivially_destructible_v = BOOST_MATH_NAMESPACE::is_trivially_destructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_destructible_v = boost::math::is_nothrow_destructible::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_nothrow_destructible_v = BOOST_MATH_NAMESPACE::is_nothrow_destructible::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool has_virtual_destructor_v = boost::math::has_virtual_destructor::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool has_virtual_destructor_v = BOOST_MATH_NAMESPACE::has_virtual_destructor::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_same_v = boost::math::is_same::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_same_v = BOOST_MATH_NAMESPACE::is_same::value; -template -BOOST_MATH_INLINE_CONSTEXPR bool is_base_of_v = boost::math::is_base_of::value; +BOOST_MATH_EXPORT template +BOOST_MATH_INLINE_CONSTEXPR bool is_base_of_v = BOOST_MATH_NAMESPACE::is_base_of::value; -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_TYPE_TRAITS diff --git a/include/boost/math/tools/ulps_heatmap.hpp b/include/boost/math/tools/ulps_heatmap.hpp new file mode 100644 index 0000000000..b42b75fa1c --- /dev/null +++ b/include/boost/math/tools/ulps_heatmap.hpp @@ -0,0 +1,1214 @@ +// (C) Copyright Nick Thompson 2026. +// 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) +// +// Two-dimensional ulps plots: heatmaps of the error of a function f(x, y) of two +// variables over a rectangle, the 2D analogue of boost/math/tools/ulps_plot.hpp. +// +// Two plots can be written from the same data: +// write_ulps: max(1/2, |ulps|). A correctly rounded implementation stays at +// 1/2, whatever the conditioning of f. +// write_ulps_envelope: max(1, |ulps|/max(1/2, cond/2)), where cond = |x f_x/f| + |y f_y/f| +// is the condition number of evaluating f with both arguments +// rounded. Values above 1 are errors the arguments' rounding can't +// explain. +// Both use a sequential colormap (inferno by default), so the floor is dark and errors +// glow. Each can use a linear or a logarithmic color scale. +// +// f is sampled at the pixel centres and at random probes between them; each pixel shows the +// worst of its samples. The condition numbers come from finite differences of the reference +// values on the grid (see detail::grid_condition_numbers_2d). +// +// The heatmap is a PNG embedded in an SVG, which carries the axes, colorbar and labels. +// The PNG encoder can be set with png_encoder. The default is lodepng (https://github.com/lvandeve/lodepng; +// link lodepng.cpp) if BOOST_MATH_USE_LODEPNG is defined or lodepng.h is included first; see ulps_plot.hpp. + +#ifndef BOOST_MATH_TOOLS_ULPS_HEATMAP_HPP +#define BOOST_MATH_TOOLS_ULPS_HEATMAP_HPP +#if (__cplusplus < 201703L) && (!defined(_MSVC_LANG) || (_MSVC_LANG < 201703L)) +#error "The header can only be used in C++17 and later." +#endif +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include +#include + +BOOST_MATH_NAMESPACE_BEGIN namespace tools { + +namespace detail { + + +// The color_maps.hpp tables are already sRGB, so they need no gamma correction: +inline std::array to_8bit_rgb(std::array const & c) +{ + std::array rgb; + for (std::size_t k = 0; k < 3; ++k) + { + rgb[k] = static_cast(std::lround(255*std::clamp(c[k], 0.0, 1.0))); + } + return rgb; +} + +// A diverging map for signed data on a dark background: light blue -> dark blue -> near black (zero) -> dark red -> light orange. +// Nothing is glaringly bright, which the cool-warm maps are. Similar in spirit to Crameri's "berlin". +inline std::array dark_diverging(double t) +{ + static constexpr double stops[5][3] = {{0.45, 0.65, 0.95}, {0.10, 0.30, 0.60}, {0.06, 0.05, 0.07}, {0.55, 0.18, 0.10}, {0.95, 0.62, 0.38}}; + t = std::clamp(t, 0.0, 1.0)*4; + int i = (std::min)(3, static_cast(t)); + double u = t - i; + return {stops[i][0]*(1 - u) + stops[i + 1][0]*u, stops[i][1]*(1 - u) + stops[i + 1][1]*u, stops[i][2]*(1 - u) + stops[i + 1][2]*u}; +} + +// Renders a tick label; whole powers of ten on a logarithmic axis are written as 10^k. +inline std::string tick_label(double v, bool log_axis) +{ + std::ostringstream os; + if (log_axis && v > 0) + { + double e = std::round(std::log10(v)); + if (std::abs(v - std::pow(10.0, e)) <= 1e-9*v) + { + os << "10" << static_cast(e) << ""; + return os.str(); + } + } + os << std::setprecision(4) << v; + return os.str(); +} + +// Approximate width in pixels of a tick label at font-size 13, ignoring its SVG markup: +inline int label_width(std::string const & label) +{ + int chars = 0; + bool in_tag = false; + for (char c : label) + { + if (c == '<') { in_tag = true; } + else if (c == '>') { in_tag = false; } + else if (!in_tag) { ++chars; } + } + return 7*chars; +} + +// Labels v > 0 on a logarithmic colorbar as a power of ten, 10^2 or 10^2.45, so that every label on it reads alike. +inline std::string power_label(double v) +{ + double e = std::log10(v); + std::ostringstream os; + if (std::abs(e - std::round(e)) < 0.005) + { + os << static_cast(std::round(e)); + } + else + { + os << std::fixed << std::setprecision(2) << e; + } + return "10" + os.str() + ""; +} + +// Coarse abscissas at the centres of n pixels spanning [a, b], evenly spaced in x or log(x). +template +std::vector heatmap_abscissas(CoarseReal a, CoarseReal b, std::size_t n, bool log_axis) +{ + std::vector xs(n); + long double lo = log_axis ? std::log(static_cast(a)) : static_cast(a); + long double hi = log_axis ? std::log(static_cast(b)) : static_cast(b); + for (std::size_t i = 0; i < n; ++i) + { + long double u = lo + (hi - lo)*(i + 0.5L)/n; + xs[i] = static_cast(log_axis ? std::exp(u) : u); + } + return xs; +} + +// f_x and f_y at (qx, qy), between the nodes of the grid x (columns) by y (rows), from the bicubic through the 4 x 4 nearest +// grid derivatives dx, dy (row-major, like the values z), which must all be trusted (tx, ty). As in interpolate_derivative, +// the bicubic through z must predict f(qx, qy) = qz well enough that the condition number is good to about fd_tolerance. +template +bool interpolate_gradient(std::vector const & x, std::vector const & y, std::vector const & z, + std::vector const & dx, std::vector const & dy, + std::vector const & tx, std::vector const & ty, + Real const & qx, Real const & qy, Real const & qz, Real & gx, Real & gy) +{ + using std::abs; + using std::isfinite; + std::size_t const W = x.size(); + std::size_t const H = y.size(); + if (W < 5 || H < 5) + { + return false; + } + std::size_t const si = interpolation_window(x.data(), W, qx); + std::size_t const sj = interpolation_window(y.data(), H, qy); + Real wx[4]; + Real wy[4]; + lagrange_weights(x.data() + si, 4, qx, wx); + lagrange_weights(y.data() + sj, 4, qy, wy); + Real fi = 0; + gx = 0; + gy = 0; + for (std::size_t b = 0; b < 4; ++b) + { + for (std::size_t a = 0; a < 4; ++a) + { + std::size_t k = (sj + b)*W + si + a; + if (!tx[k] || !ty[k]) + { + return false; + } + Real w = wx[a]*wy[b]; + fi += w*z[k]; + gx += w*dx[k]; + gy += w*dy[k]; + } + } + Real const hx = abs(x[si + 2] - x[si + 1]); + Real const hy = abs(y[sj + 2] - y[sj + 1]); + Real const ax = abs(qx); + Real const ay = abs(qy); + // Each window must be narrow compared to its coordinate, as in interpolate_derivative: + bool const narrow = (ax == 0 || abs(x[si + 3] - x[si]) <= Real(fd_max_span)*ax) && (ay == 0 || abs(y[sj + 3] - y[sj]) <= Real(fd_max_span)*ay); + return narrow && isfinite(gx) && isfinite(gy) + && abs(fi - qz)*(ax/hx + ay/hy) <= Real(fd_tolerance)*(std::max)(Real(abs(qz)), Real(ax*abs(gx) + ay*abs(gy))); +} + +// The condition numbers |x f_x/f| + |y f_y/f| on the grid x (columns) by y (rows) with reference values z (row-major, row j at y[j]), +// returned in cond, and at the probes (qx, qy) with values qz, returned in qcond. The 2D analogue of grid_condition_numbers: +// finite differences along the rows and the columns, bicubic interpolation of the gradient at the probes, and local +// differences where these can't be trusted. Inf where f = 0, NaN where f is not finite. f must be thread safe. +template +void grid_condition_numbers_2d(F const & f, std::vector const & x, std::vector const & y, std::vector const & z, + std::vector const & qx, std::vector const & qy, std::vector const & qz, + std::vector & cond, std::vector & qcond, unsigned threads) +{ + using std::abs; + using std::isfinite; + std::size_t const W = x.size(); + std::size_t const H = y.size(); + std::vector dx(W*H); + std::vector dy(W*H); + std::vector tx(W*H); + std::vector ty(W*H); + parallel_for(H, threads, [&](std::size_t j) { + grid_derivatives(x.data(), z.data() + j*W, 1, W, dx.data() + j*W, tx.data() + j*W); + }); + parallel_for(W, threads, [&](std::size_t i) { + grid_derivatives(y.data(), z.data() + i, W, H, dy.data() + i, ty.data() + i); + }); + cond.assign(W*H, std::numeric_limits::quiet_NaN()); + parallel_for(H, threads, [&](std::size_t j) { + for (std::size_t i = 0; i < W; ++i) + { + std::size_t k = j*W + i; + if (!isfinite(z[k])) + { + continue; + } + Real cx = tx[k] ? Real(abs(x[i]*dx[k]/z[k])) : local_condition_number([&](Real const & t) { return f(t, y[j]); }, x[i], z[k]); + Real cy = ty[k] ? Real(abs(y[j]*dy[k]/z[k])) : local_condition_number([&](Real const & t) { return f(x[i], t); }, y[j], z[k]); + cond[k] = cx + cy; + } + }); + qcond.assign(qx.size(), std::numeric_limits::quiet_NaN()); + std::size_t const chunk = 64; + parallel_for((qx.size() + chunk - 1)/chunk, threads, [&](std::size_t c) { + for (std::size_t p = c*chunk; p < (std::min)(qx.size(), (c + 1)*chunk); ++p) + { + if (!isfinite(qz[p])) + { + continue; + } + Real gx; + Real gy; + if (interpolate_gradient(x, y, z, dx, dy, tx, ty, qx[p], qy[p], qz[p], gx, gy)) + { + qcond[p] = abs(qx[p]*gx/qz[p]) + abs(qy[p]*gy/qz[p]); + } + else + { + qcond[p] = local_condition_number([&](Real const & t) { return f(t, qy[p]); }, qx[p], qz[p]) + + local_condition_number([&](Real const & t) { return f(qx[p], t); }, qy[p], qz[p]); + } + } + }); +} + +} // namespace detail + +template +class ulps_heatmap { +public: + // Samples f at the pixel centres of a width x height grid on [x_min, x_max] x [y_min, y_max], and at + // probe_density*width*height random probes (uniform in the plotted coordinates, with a fixed seed). Each pixel + // shows the worst of its samples. A logarithmic axis is sampled evenly in log and requires a positive minimum. + // hi_acc_impl(x, y) takes PreciseReal arguments and must be safe to call from several threads. + ulps_heatmap(F hi_acc_impl, CoarseReal x_min, CoarseReal x_max, CoarseReal y_min, CoarseReal y_max, + std::size_t width = 800, std::size_t height = 500, + bool log_x = false, bool log_y = false, unsigned threads = 0, double probe_density = 0.25); + + // Computes the error of the implementation g(x, y), which takes CoarseReal arguments. Each + // function added is drawn as its own panel, side by side with the others and on the same scale. + template + ulps_heatmap& add_fn(G g, std::string const & label = ""); + + // Saturates the color scale at clip. By default the clip is chosen from the values in all + // panels: the largest on a logarithmic scale, and the 99th percentile on a linear one. + ulps_heatmap& clip(double clip); + + // The color scale runs from the floor (1/2 for ulps, 1 for ulps/envelope) to the clip, + // linearly or logarithmically. + ulps_heatmap& log_scale(bool log_scale); + + // Maps [0, 1] to sRGB in [0, 1]^3; inferno by default. Any of the color_maps.hpp maps fit. + ulps_heatmap& color_map(std::function(double)> color_map); + + // Encodes 8-bit RGB pixels, row-major from the top row, as a PNG; lodepng by default, if requested (see ulps_plot.hpp). + using png_encoder_type = detail::png_encoder_type; + ulps_heatmap& png_encoder(png_encoder_type encoder); + + ulps_heatmap& title(std::string const & title); + + ulps_heatmap& x_label(std::string const & label); + + ulps_heatmap& y_label(std::string const & label); + + ulps_heatmap& background_color(std::string const & color); + + ulps_heatmap& font_color(std::string const & color); + + // Draws the function itself (the reference values) as a heatmap below each error panel, on the same axes + // and with its own colorbar. Off by default. The color mapping is chosen from the values; see write_svg. + ulps_heatmap& show_function(bool show_function); + + // The caption of the function panels; by default the title, or f(x, y) if there is none. + ulps_heatmap& function_label(std::string const & label); + + // The function panels are colored linearly, from min(f) to max(f) (symmetric about 0, with a dark center, if f has both signs). + // If f > 0 everywhere and spans three or more decades, a logarithmic scale is used automatically; log_function(true) forces it + // when f > 0 everywhere, and log_function(false) turns it off. + ulps_heatmap& log_function(bool log_function); + + void write_ulps(std::string const & filename) const; + + void write_ulps_envelope(std::string const & filename) const; + + // The same SVGs as write_ulps and write_ulps_envelope, as strings. + std::string ulps_svg() const; + + std::string ulps_envelope_svg() const; + + // For each panel, counts of pixels without a value and outside 1/2 ulp and the envelope, + // and the worst errors and where they occur. + std::string summary() const; + +private: + struct panel + { + std::string label; + // Row-major, with row 0 at y_max (the top of the image): + std::vector ulps; + std::vector ulps_envelope; + std::vector state; + // Where the worst ulps and ulps/envelope of each pixel were found: 0 for its centre, p + 1 for probe p. + std::vector ulps_source; + std::vector ulps_envelope_source; + }; + + // The coordinates of the sample source (see panel) in pixel k: + std::pair sample_location(std::size_t k, std::size_t source) const + { + if (source == 0) + { + return {xs_[k % xs_.size()], ys_[k / xs_.size()]}; + } + return {probe_x_[source - 1], probe_y_[source - 1]}; + } + + void write_svg(std::ostream & fs, std::vector panel::* values, double floor, + std::string const & quantity) const; + + void write_file(std::string const & filename, std::vector panel::* values, double floor, + std::string const & quantity) const; + + std::vector xs_; + std::vector ys_; + // Row-major, with row 0 at y_max (the top of the image): + std::vector precise_; + std::vector envelope_; + // The random probes, the pixels they fall in, and their reference values and envelopes: + std::vector probe_x_; + std::vector probe_y_; + std::vector probe_pixel_; + std::vector probe_precise_; + std::vector probe_envelope_; + std::vector panels_; + CoarseReal x_min_; + CoarseReal x_max_; + CoarseReal y_min_; + CoarseReal y_max_; + bool log_x_; + bool log_y_; + unsigned threads_; + double clip_ = -1; + bool log_scale_ = false; + std::function(double)> color_map_ = inferno; + png_encoder_type png_encoder_ = detail::default_png_encoder(); + std::string title_; + std::string x_label_ = "x"; + std::string y_label_ = "y"; + std::string background_color_ = "black"; + std::string font_color_ = "white"; + bool show_function_ = false; + std::string function_label_; + int log_function_ = -1; +}; + +template +ulps_heatmap::ulps_heatmap(F hi_acc_impl, CoarseReal x_min, CoarseReal x_max, + CoarseReal y_min, CoarseReal y_max, std::size_t width, std::size_t height, + bool log_x, bool log_y, unsigned threads, double probe_density) + : x_min_(x_min), x_max_(x_max), y_min_(y_min), y_max_(y_max), log_x_(log_x), log_y_(log_y), threads_(threads) +{ + static_assert(std::numeric_limits::digits10 >= std::numeric_limits::digits10, "PreciseReal must have higher precision that CoarseReal"); + if (!(x_min < x_max) || !(y_min < y_max)) + { + throw std::domain_error("Require x_min < x_max and y_min < y_max."); + } + if ((log_x && !(x_min > 0)) || (log_y && !(y_min > 0))) + { + throw std::domain_error("A logarithmic axis requires a positive minimum."); + } + if (width < 2 || height < 2) + { + throw std::domain_error("The heatmap must be at least 2 x 2 pixels."); + } + xs_ = detail::heatmap_abscissas(x_min, x_max, width, log_x); + ys_ = detail::heatmap_abscissas(y_min, y_max, height, log_y); + std::reverse(ys_.begin(), ys_.end()); + + if (!(probe_density >= 0)) + { + throw std::domain_error("The probe density must be nonnegative."); + } + + // Random probes, uniform in the plotted coordinates, find the errors between the pixel centres: at integers and + // half-integers, which a grid can hit or miss and which often take their own code paths, and in narrow features. + std::size_t const probes = static_cast(probe_density*static_cast(width*height)); + std::mt19937_64 gen(20261011); + std::uniform_real_distribution unit(0.0, 1.0); + auto random_coordinate = [&](CoarseReal lo, CoarseReal hi, bool log_axis, std::size_t n, std::size_t & cell) { + double u = unit(gen); + long double t_lo = log_axis ? std::log(static_cast(lo)) : static_cast(lo); + long double t_hi = log_axis ? std::log(static_cast(hi)) : static_cast(hi); + long double t = t_lo + (t_hi - t_lo)*u; + cell = (std::min)(n - 1, static_cast(u*static_cast(n))); + return (std::min)(hi, (std::max)(lo, static_cast(log_axis ? std::exp(t) : t))); + }; + probe_x_.resize(probes); + probe_y_.resize(probes); + probe_pixel_.resize(probes); + for (std::size_t p = 0; p < probes; ++p) + { + std::size_t i; + std::size_t j; + probe_x_[p] = random_coordinate(x_min, x_max, log_x, width, i); + probe_y_[p] = random_coordinate(y_min, y_max, log_y, height, j); + // Row 0 is at the top: + probe_pixel_[p] = (height - 1 - j)*width + i; + } + + auto reference = [&](PreciseReal const & x, PreciseReal const & y) { + try + { + return static_cast(hi_acc_impl(x, y)); + } + catch (...) + { + return std::numeric_limits::quiet_NaN(); + } + }; + std::vector px(xs_.begin(), xs_.end()); + std::vector py(ys_.begin(), ys_.end()); + std::vector qx(probe_x_.begin(), probe_x_.end()); + std::vector qy(probe_y_.begin(), probe_y_.end()); + precise_.resize(width*height); + detail::parallel_for(height, threads_, [&](std::size_t j) { + for (std::size_t i = 0; i < width; ++i) + { + precise_[j*width + i] = reference(px[i], py[j]); + } + }); + probe_precise_.resize(probes); + std::size_t const chunk = 64; + detail::parallel_for((probes + chunk - 1)/chunk, threads_, [&](std::size_t c) { + for (std::size_t p = c*chunk; p < (std::min)(probes, (c + 1)*chunk); ++p) + { + probe_precise_[p] = reference(qx[p], qy[p]); + } + }); + // The condition numbers, from finite differences on the grid: + std::vector cond; + std::vector qcond; + detail::grid_condition_numbers_2d(reference, px, py, precise_, qx, qy, probe_precise_, cond, qcond, threads_); + // As in ulps_plot, the envelope never drops below the 1/2 ulp of correct rounding: + auto envelope = [](PreciseReal const & c) { + using std::isnan; + return isnan(c) ? std::numeric_limits::quiet_NaN() : (std::max)(0.5, static_cast(c/2)); + }; + envelope_.resize(width*height); + std::transform(cond.begin(), cond.end(), envelope_.begin(), envelope); + probe_envelope_.resize(probes); + std::transform(qcond.begin(), qcond.end(), probe_envelope_.begin(), envelope); +} + +template +template +ulps_heatmap& ulps_heatmap::add_fn(G g, std::string const & label) +{ + std::size_t width = xs_.size(); + std::size_t n = precise_.size(); + panel p; + p.label = label; + p.ulps.assign(n, std::numeric_limits::quiet_NaN()); + p.ulps_envelope.assign(n, std::numeric_limits::quiet_NaN()); + p.state.assign(n, detail::ulps_class::ok); + p.ulps_source.assign(n, 0); + p.ulps_envelope_source.assign(n, 0); + // The ulps of g at (x, y), against the reference value z, with the same ulp distance as ulps_plot: + auto evaluate = [&](CoarseReal x, CoarseReal y, PreciseReal const & z, double & ulps) { + using std::abs; + using std::nextafter; + // The implementation is evaluated everywhere, even where the true value is out of range, to check + // that overflow and underflow are handled correctly: + CoarseReal w = 0; + detail::ulps_class c = detail::classify_result(z, [&]() { return g(x, y); }, w); + if (c == detail::ulps_class::ok) + { + CoarseReal absz = static_cast(abs(z)); + PreciseReal dist = static_cast(nextafter(absz, (std::numeric_limits::max)()) - absz); + ulps = static_cast((static_cast(w) - z)/dist); + } + return c; + }; + detail::parallel_for(ys_.size(), threads_, [&](std::size_t j) { + for (std::size_t i = 0; i < width; ++i) + { + std::size_t k = j*width + i; + p.state[k] = evaluate(xs_[i], ys_[j], precise_[k], p.ulps[k]); + p.ulps_envelope[k] = p.ulps[k]/envelope_[k]; + } + }); + std::size_t const probes = probe_x_.size(); + std::vector probe_state(probes); + std::vector probe_ulps(probes, std::numeric_limits::quiet_NaN()); + std::size_t const chunk = 64; + detail::parallel_for((probes + chunk - 1)/chunk, threads_, [&](std::size_t c) { + for (std::size_t q = c*chunk; q < (std::min)(probes, (c + 1)*chunk); ++q) + { + probe_state[q] = evaluate(probe_x_[q], probe_y_[q], probe_precise_[q], probe_ulps[q]); + } + }); + // Each pixel shows the worst of its samples: a bug (NaN, a spurious overflow, a mishandled out-of-range value) over an + // ulps value, over a correctly handled out-of-range value; and of the ulps values, the largest. + auto rank = [](detail::ulps_class c) { + return c == detail::ulps_class::ok ? 1 : (c == detail::ulps_class::failed || c == detail::ulps_class::spurious_overflow || c == detail::ulps_class::mishandled) ? 2 : 0; + }; + for (std::size_t q = 0; q < probes; ++q) + { + std::size_t k = probe_pixel_[q]; + double ratio = probe_ulps[q]/probe_envelope_[q]; + if (rank(probe_state[q]) > rank(p.state[k])) + { + p.state[k] = probe_state[q]; + p.ulps[k] = probe_ulps[q]; + p.ulps_envelope[k] = ratio; + p.ulps_source[k] = q + 1; + p.ulps_envelope_source[k] = q + 1; + } + else if (probe_state[q] == detail::ulps_class::ok && p.state[k] == detail::ulps_class::ok) + { + if (std::abs(probe_ulps[q]) > std::abs(p.ulps[k])) + { + p.ulps[k] = probe_ulps[q]; + p.ulps_source[k] = q + 1; + } + if (std::abs(ratio) > std::abs(p.ulps_envelope[k]) || std::isnan(p.ulps_envelope[k])) + { + p.ulps_envelope[k] = ratio; + p.ulps_envelope_source[k] = q + 1; + } + } + } + panels_.push_back(std::move(p)); + return *this; +} + +template +ulps_heatmap& ulps_heatmap::clip(double clip) +{ + clip_ = clip; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::log_scale(bool log_scale) +{ + log_scale_ = log_scale; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::color_map(std::function(double)> color_map) +{ + color_map_ = color_map; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::png_encoder(png_encoder_type encoder) +{ + png_encoder_ = encoder; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::title(std::string const & title) +{ + title_ = title; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::x_label(std::string const & label) +{ + x_label_ = label; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::y_label(std::string const & label) +{ + y_label_ = label; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::background_color(std::string const & color) +{ + background_color_ = color; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::font_color(std::string const & color) +{ + font_color_ = color; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::show_function(bool show_function) +{ + show_function_ = show_function; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::log_function(bool log_function) +{ + log_function_ = log_function ? 1 : 0; + return *this; +} + +template +ulps_heatmap& ulps_heatmap::function_label(std::string const & label) +{ + function_label_ = label; + return *this; +} + +template +void ulps_heatmap::write_ulps(std::string const & filename) const +{ + write_file(filename, &panel::ulps, 0.5, "|ulps|"); +} + +template +void ulps_heatmap::write_ulps_envelope(std::string const & filename) const +{ + write_file(filename, &panel::ulps_envelope, 1, "|ulps| / max(1/2, cond/2)"); +} + +template +std::string ulps_heatmap::ulps_svg() const +{ + std::ostringstream os; + write_svg(os, &panel::ulps, 0.5, "|ulps|"); + return os.str(); +} + +template +std::string ulps_heatmap::ulps_envelope_svg() const +{ + std::ostringstream os; + write_svg(os, &panel::ulps_envelope, 1, "|ulps| / max(1/2, cond/2)"); + return os.str(); +} + +template +void ulps_heatmap::write_file(std::string const & filename, std::vector panel::* values, + double floor, std::string const & quantity) const +{ + if (!detail::ends_with(filename, ".svg")) + { + throw std::logic_error("Only svg files are supported at this time."); + } + // Render first, so that a failure leaves no partial file: + std::ostringstream os; + write_svg(os, values, floor, quantity); + std::ofstream fs(filename); + fs << os.str(); +} + +template +std::string ulps_heatmap::summary() const +{ + std::ostringstream os; + std::size_t width = xs_.size(); + for (panel const & p : panels_) + { + using detail::ulps_class; + std::size_t counts[7] = {0, 0, 0, 0, 0, 0, 0}; + std::size_t first[7] = {0, 0, 0, 0, 0, 0, 0}; + std::size_t bx0[7], bx1[7], by0[7], by1[7]; + for (int c = 0; c < 7; ++c) { bx0[c] = width; bx1[c] = 0; by0[c] = ys_.size(); by1[c] = 0; } + std::size_t over_half = 0; + std::size_t over_envelope = 0; + std::size_t worst_ulps = 0; + std::size_t worst_ratio = 0; + for (std::size_t k = 0; k < p.state.size(); ++k) + { + std::size_t c = static_cast(p.state[k]); + if (counts[c]++ == 0) { first[c] = k; } + bx0[c] = (std::min)(bx0[c], k % width); bx1[c] = (std::max)(bx1[c], k % width); + by0[c] = (std::min)(by0[c], k / width); by1[c] = (std::max)(by1[c], k / width); + if (p.state[k] != ulps_class::ok) { continue; } + if (std::abs(p.ulps[k]) > 0.5) { ++over_half; } + if (std::abs(p.ulps_envelope[k]) > 1) { ++over_envelope; } + if (!(std::abs(p.ulps[k]) <= std::abs(p.ulps[worst_ulps]))) { worst_ulps = k; } + if (!(std::abs(p.ulps_envelope[k]) <= std::abs(p.ulps_envelope[worst_ratio]))) { worst_ratio = k; } + } + if (!p.label.empty()) + { + os << p.label << ": "; + } + os << p.state.size() << " pixels (" << probe_x_.size() << " probes): ok=" << counts[0] << " undefined=" << counts[1] << " overflow_handled=" << counts[2] + << " underflow_handled=" << counts[3] << " green_nan_or_domain_error=" << counts[4] << " cyan_spurious_overflow=" << counts[5] + << " mishandled=" << counts[6] << " over_half_ulp=" << over_half << " over_envelope=" << over_envelope << "\n"; + char const * names[7] = {"", "", "", "", "Green (NaN or domain error)", "Cyan (spurious overflow)", "Mishandled out-of-range result (maximal error)"}; + for (std::size_t c = 4; c < 7; ++c) + { + if (counts[c] > 0) + { + os << " " << names[c] << ": first at (" << std::setprecision(std::numeric_limits::max_digits10) + << xs_[first[c] % width] << ", " << ys_[first[c] / width] << "); x in [" << xs_[bx0[c]] << ", " << xs_[bx1[c]] + << "], y in [" << ys_[by1[c]] << ", " << ys_[by0[c]] << "]\n"; + } + } + auto at_ulps = sample_location(worst_ulps, p.ulps_source[worst_ulps]); + auto at_ratio = sample_location(worst_ratio, p.ulps_envelope_source[worst_ratio]); + os << " Worst ulps: " << std::setprecision(4) << p.ulps[worst_ulps] + << std::setprecision(std::numeric_limits::max_digits10) + << " at (" << at_ulps.first << ", " << at_ulps.second << ")\n"; + os << " Worst ulps/envelope: " << std::setprecision(4) << p.ulps_envelope[worst_ratio] + << std::setprecision(std::numeric_limits::max_digits10) + << " at (" << at_ratio.first << ", " << at_ratio.second << ")\n"; + } + return os.str(); +} + +template +void ulps_heatmap::write_svg(std::ostream & fs, std::vector panel::* values, + double floor, std::string const & quantity) const +{ + if (panels_.empty()) + { + throw std::domain_error("No function added; call add_fn first."); + } + if (!png_encoder_) + { + throw std::logic_error("No PNG encoder: set one with png_encoder, or define BOOST_MATH_USE_LODEPNG and link lodepng."); + } + // Gray: correctly handled: the true value is undefined, or out of range and the implementation overflowed (or underflowed to zero + // or a subnormal) as it should. Green: NaN or a domain error where the true value is a finite double. + static constexpr std::array no_reference_rgb = {70, 70, 70}; + static constexpr std::array failed_rgb = {127, 255, 0}; + // Cyan: the implementation threw std::overflow_error or returned an infinity, where the true value is a finite double. + static constexpr std::array spurious_overflow_rgb = {0, 229, 255}; + + // Plot max(floor, |value|), so that log scales work: + auto magnitude = [&](double v) { return (std::max)(floor, std::abs(v)); }; + double clip = clip_; + if (clip <= 0) + { + // Choose the clip from the values of every panel, so that they share a scale: + std::vector magnitudes; + for (panel const & p : panels_) + { + for (std::size_t k = 0; k < p.state.size(); ++k) + { + if (p.state[k] == detail::ulps_class::ok && std::isfinite((p.*values)[k])) + { + magnitudes.push_back(magnitude((p.*values)[k])); + } + } + } + // A few huge errors would wash out a linear scale, so clip it at the 99th percentile: + if (!magnitudes.empty()) + { + std::size_t rank = log_scale_ ? magnitudes.size() - 1 : (99*magnitudes.size())/100; + std::nth_element(magnitudes.begin(), magnitudes.begin() + rank, magnitudes.end()); + clip = magnitudes[rank]; + } + } + // The scale needs some room above the floor: + if (!(clip > floor*1.01)) + { + clip = log_scale_ ? 10*floor : 2*floor; + } + // Maps a value to [0, 1]: + auto scale = [&](double v) { + double m = magnitude(v); + double t = log_scale_ ? std::log(m/floor)/std::log(clip/floor) : (m - floor)/(clip - floor); + return (std::min)(1.0, t); + }; + + std::size_t width = xs_.size(); + std::size_t height = ys_.size(); + bool labelled = std::any_of(panels_.begin(), panels_.end(), [](panel const & p) { return !p.label.empty(); }); + int const margin_left = 80; + int const margin_top = (title_.empty() ? 20 : 50) + (labelled ? 24 : 0); + int const margin_bottom = 60; + int const panel_gap = 30; + int const bar_gap = 25; + int const bar_width = 22; + int const margin_right = 215; + int const W = static_cast(width); + int const H = static_cast(height); + int const panels = static_cast(panels_.size()); + int const plots_width = panels*W + (panels - 1)*panel_gap; + int const total_width = margin_left + plots_width + margin_right; + // As many axis ticks as fit without their labels overlapping: + int const x_ticks = (std::max)(2, (std::min)(8, W/60)); + int const y_ticks = (std::max)(2, (std::min)(6, H/40)); + // The function heatmaps go below the error heatmaps, separated by room for the latter's x tick labels: + int const function_gap = 66; + int const function_top = margin_top + H + function_gap; + int const total_height = show_function_ ? function_top + H + margin_bottom : margin_top + H + margin_bottom; + auto x_pos = [&](double x) { + double u = log_x_ ? std::log(x/x_min_)/std::log(double(x_max_)/x_min_) : (x - x_min_)/(double(x_max_) - x_min_); + return u*W; + }; + auto y_pos = [&](double y) { + double u = log_y_ ? std::log(y/y_min_)/std::log(double(y_max_)/y_min_) : (y - y_min_)/(double(y_max_) - y_min_); + return margin_top + (1 - u)*H; + }; + auto rgb_string = [](std::array const & c) { + return "rgb(" + std::to_string(c[0]) + "," + std::to_string(c[1]) + "," + std::to_string(c[2]) + ")"; + }; + // Axis ticks; reuse ulps_plot's gridline abscissas, plus the minimum on a linear axis: + auto ticks = [](CoarseReal a, CoarseReal b, int lines, bool log_axis) { + std::vector t = detail::vertical_gridlines(a, b, lines, log_axis); + if (!log_axis) + { + t.insert(t.begin(), a); + } + return t; + }; + + // The function's color mapping: f itself, linearly from min(f) to max(f) with a sequential map (viridis); if f has both signs, + // symmetric about zero with a dark-centered diverging map. If f > 0 everywhere and spans three or more decades, color by log10(f) + // (see log_function). If f has both signs and its largest values dwarf the bulk of the plot (0F1(b, z) reaches 1e9 in a corner + // and is of order 1 elsewhere), a linear map would show only black, so color by sgn(f) ln(1 + |f|/s), with s chosen so that the + // 90th percentile of |f| falls halfway between s and max |f| on a log scale. Pixels with no finite reference in CoarseReal's range are + // drawn gray. + enum class fn_mode { log_seq, linear_seq, linear_div, symlog_div }; + fn_mode mode = fn_mode::linear_seq; + double fmin = std::numeric_limits::infinity(); + double fmax = -std::numeric_limits::infinity(); + double fsym = 0; + double fscale = 1; + std::vector fn_png; + std::vector const * fn_png_ptr = nullptr; + auto fn_ok = [&](std::size_t k) { + using std::abs; + using std::isfinite; + return isfinite(precise_[k]) && abs(precise_[k]) <= (std::numeric_limits::max)(); + }; + auto fn_t = [&](double v) { + double t = 0; + switch (mode) + { + case fn_mode::log_seq: t = (std::log10(v) - std::log10(fmin))/(std::log10(fmax) - std::log10(fmin)); break; + case fn_mode::linear_seq: t = (v - fmin)/(fmax - fmin); break; + case fn_mode::linear_div: t = 0.5 + 0.5*v/fsym; break; + case fn_mode::symlog_div: t = 0.5 + 0.5*std::copysign(std::log1p(std::abs(v)/fscale), v)/std::log1p(fsym/fscale); break; + } + return std::clamp(t, 0.0, 1.0); + }; + if (show_function_) + { + for (std::size_t k = 0; k < width*height; ++k) + { + if (fn_ok(k)) + { + double v = static_cast(precise_[k]); + fmin = (std::min)(fmin, v); + fmax = (std::max)(fmax, v); + } + } + if (!(fmin <= fmax)) + { + fmin = 0; + fmax = 1; + } + if (fmin > 0 && (log_function_ == 1 || (log_function_ == -1 && fmax >= 1000*fmin)) && fmax > fmin) + { + mode = fn_mode::log_seq; + } + else if (fmin < 0 && fmax > 0) + { + mode = fn_mode::linear_div; + fsym = (std::max)(-fmin, fmax); + std::vector fabs_values; + for (std::size_t k = 0; k < width*height; ++k) + { + if (fn_ok(k)) { fabs_values.push_back(std::abs(static_cast(precise_[k]))); } + } + auto p90 = fabs_values.begin() + static_cast(0.9*(fabs_values.size() - 1)); + std::nth_element(fabs_values.begin(), p90, fabs_values.end()); + if (*p90 > 0 && fsym > 1000 * *p90) + { + mode = fn_mode::symlog_div; + fscale = (std::max)(*p90 * (*p90 / fsym), (std::numeric_limits::min)()); + } + } + else + { + mode = fn_mode::linear_seq; + if (!(fmax > fmin)) + { + // A constant function: + fmin -= 0.5*std::abs(fmin) + 0.5; + fmax += 0.5*std::abs(fmax) + 0.5; + } + } + std::vector rgb(3*width*height); + for (std::size_t k = 0; k < width*height; ++k) + { + std::array c = no_reference_rgb; + if (fn_ok(k)) + { + double t = fn_t(static_cast(precise_[k])); + c = detail::to_8bit_rgb(mode == fn_mode::linear_div || mode == fn_mode::symlog_div ? detail::dark_diverging(t) : viridis(t)); + } + std::copy(c.begin(), c.end(), rgb.begin() + 3*k); + } + fn_png = png_encoder_(rgb, width, height); + fn_png_ptr = &fn_png; + } + + fs << "\n" + << "\n" + << "\n" + << "\n"; + if (!title_.empty()) + { + fs << "" << title_ << "\n"; + } + bool any_failed = false; + bool any_spurious = false; + bool any_no_reference = false; + for (int q = 0; q < panels; ++q) + { + panel const & p = panels_[q]; + int const left = margin_left + q*(W + panel_gap); + std::vector rgb(3*width*height); + for (std::size_t k = 0; k < width*height; ++k) + { + double v = (p.*values)[k]; + std::array c = no_reference_rgb; + switch (p.state[k]) + { + case detail::ulps_class::ok: + // An envelope can be missing (NaN) where the condition number could not be estimated; draw it at the floor. + c = detail::to_8bit_rgb(color_map_(std::isfinite(v) ? scale(v) : 0.0)); + break; + case detail::ulps_class::failed: + c = failed_rgb; + any_failed = true; + break; + case detail::ulps_class::spurious_overflow: + c = spurious_overflow_rgb; + any_spurious = true; + break; + case detail::ulps_class::mishandled: + // An out-of-range result handled wrongly is the maximal error: the top of the color scale. + c = detail::to_8bit_rgb(color_map_(1.0)); + break; + default: + any_no_reference = true; + break; + } + std::copy(c.begin(), c.end(), rgb.begin() + 3*k); + } + std::vector png = png_encoder_(rgb, width, height); + if (!p.label.empty()) + { + fs << "" << p.label << "\n"; + } + fs << "\n"; + fs << "\n"; + for (CoarseReal x : ticks(x_min_, x_max_, x_ticks, log_x_)) + { + double px = left + x_pos(x); + fs << "\n" + << "" + << (log_x_ ? detail::tick_label(x, true) : detail::axis_label(static_cast(x), static_cast(x_min_), static_cast(x_max_), x_ticks, false)) << "\n"; + } + if (!show_function_) + { + fs << "" + << x_label_ << "\n"; + } + else + { + fs << "\n"; + fs << "\n"; + for (CoarseReal x : ticks(x_min_, x_max_, x_ticks, log_x_)) + { + double px = left + x_pos(x); + fs << "\n" + << "" + << (log_x_ ? detail::tick_label(x, true) : detail::axis_label(static_cast(x), static_cast(x_min_), static_cast(x_max_), x_ticks, false)) << "\n"; + } + fs << "" + << x_label_ << "\n"; + fs << "" << (!function_label_.empty() ? function_label_ : (!title_.empty() ? title_ : std::string("f(x, y)"))) << "\n"; + } + } + // The panels share the y axis, which is labelled on the first: + for (CoarseReal y : ticks(y_min_, y_max_, y_ticks, log_y_)) + { + double py = y_pos(y); + fs << "\n" + << "" + << (log_y_ ? detail::tick_label(y, true) : detail::axis_label(static_cast(y), static_cast(y_min_), static_cast(y_max_), y_ticks, false)) << "\n"; + } + fs << "" << y_label_ << "\n"; + if (show_function_) + { + for (CoarseReal y : ticks(y_min_, y_max_, y_ticks, log_y_)) + { + double py = function_top + (y_pos(y) - margin_top); + fs << "\n" + << "" + << (log_y_ ? detail::tick_label(y, true) : detail::axis_label(static_cast(y), static_cast(y_min_), static_cast(y_max_), y_ticks, false)) << "\n"; + } + fs << "" << y_label_ << "\n"; + } + + // Colorbar, with the floor at the bottom and the clip at the top: + int const bar_x = margin_left + plots_width + bar_gap; + int const steps = 256; + for (int s = 0; s < steps; ++s) + { + double t = 1 - (s + 0.5)/steps; + fs << "\n"; + } + fs << "\n"; + int bar_label_width = 0; + auto bar_tick = [&](double t, std::string const & label) { + bar_label_width = (std::max)(bar_label_width, detail::label_width(label)); + double py = margin_top + (1 - t)*H; + fs << "\n" + << "" << label << "\n"; + }; + auto number = [](double v) { + std::ostringstream os; + os << std::setprecision(3) << v; + return os.str(); + }; + if (log_scale_) + { + double decades = std::log10(clip/floor); + // Label every power of ten, or every step-th one when the scale spans many decades, so that the labels don't overlap: + int step = (std::max)(1, static_cast(std::ceil(decades/(std::max)(1, (std::min)(8, H/24))))); + for (double e = step*std::ceil(std::log10(floor)/step); e < std::log10(clip); e += step) + { + double t = (e - std::log10(floor))/decades; + // Keep clear of the end labels: + if (t*H > 16 && (1 - t)*H > 16) + { + bar_tick(t, detail::power_label(std::pow(10.0, e))); + } + } + } + else + { + for (int i = 1; i < 4; ++i) + { + bar_tick(i/4.0, number(floor + (clip - floor)*i/4)); + } + } + bar_tick(0, log_scale_ ? detail::power_label(floor) : number(floor)); + // Say "at least" only when some value exceeds the clip, i.e. is hidden by the saturated scale: + bool clipped = false; + for (panel const & p : panels_) + { + for (std::size_t k = 0; k < p.state.size(); ++k) + { + if (p.state[k] == detail::ulps_class::ok && std::isfinite((p.*values)[k]) && magnitude((p.*values)[k]) > clip*(1 + 1e-9)) + { + clipped = true; + } + } + } + { + std::ostringstream top; + top << std::setprecision(4) << clip; + bar_tick(1, (clipped ? "≥ " : "") + (log_scale_ ? detail::power_label(clip) : top.str())); + } + // Legend for the pixels without a color on the scale: + int legend_y = margin_top + H + 18; + auto swatch = [&](std::array const & c, std::string const & text) { + fs << "\n" + << "" << text << "\n"; + legend_y += 14; + }; + if (any_failed) { swatch(failed_rgb, "NaN or domain error"); } + if (any_spurious) { swatch(spurious_overflow_rgb, "spurious overflow"); } + if (any_no_reference) { swatch(no_reference_rgb, "out of range, handled correctly"); } + // The colorbar's label runs down its right side, clear of the title: + int const label_x = (std::min)(bar_x + bar_width + 8 + bar_label_width + 16, total_width - 10); + fs << "" << quantity << "\n"; + if (show_function_) + { + for (int st = 0; st < steps; ++st) + { + double t = 1 - (st + 0.5)/steps; + auto c = detail::to_8bit_rgb(mode == fn_mode::linear_div || mode == fn_mode::symlog_div ? detail::dark_diverging(t) : viridis(t)); + fs << "\n"; + } + fs << "\n"; + int fn_label_width = 0; + auto fn_tick = [&](double t, std::string const & label) { + fn_label_width = (std::max)(fn_label_width, detail::label_width(label)); + double py = function_top + (1 - t)*H; + fs << "\n" + << "" << label << "\n"; + }; + std::string fn_quantity = "f(x, y)"; + if (!function_label_.empty()) { fn_quantity = function_label_; } + else if (!title_.empty()) { fn_quantity = title_; } + // Enough digits that the ticks, a quarter of the colorbar apart, don't all read alike: + int const fn_precision = detail::tick_precision(mode == fn_mode::linear_div ? -fsym : fmin, mode == fn_mode::linear_div ? fsym : fmax, 4); + auto fn_number = [&](double v) { std::ostringstream os; os << std::setprecision(fn_precision) << v; return os.str(); }; + switch (mode) + { + case fn_mode::log_seq: + { + double lo = std::log10(fmin); + double hi = std::log10(fmax); + int step = (std::max)(1, static_cast(std::ceil((hi - lo)/(std::max)(1, (std::min)(6, H/24))))); + for (int e = static_cast(std::ceil(lo)); e <= hi; e += step) + { + double t = fn_t(std::pow(10.0, e)); + if (t*H > 16 && (1 - t)*H > 16) + { + fn_tick(t, detail::power_label(std::pow(10.0, e))); + } + } + break; + } + case fn_mode::linear_seq: + for (int i = 1; i < 4; ++i) + { + fn_tick(i/4.0, fn_number(fmin + (fmax - fmin)*i/4)); + } + break; + case fn_mode::linear_div: + fn_tick(0.25, fn_number(-fsym/2)); + fn_tick(0.5, "0"); + fn_tick(0.75, fn_number(fsym/2)); + break; + case fn_mode::symlog_div: + { + fn_tick(0.5, "0"); + double lo = std::log10(fscale); + double hi = std::log10(fsym); + int step = (std::max)(1, static_cast(std::ceil((hi - lo)/(std::max)(1, (std::min)(3, H/48))))); + for (int e = static_cast(std::ceil(lo)); e <= hi; e += step) + { + double t = fn_t(std::pow(10.0, e)); + if ((t - 0.5)*H > 16 && (1 - t)*H > 16) + { + fn_tick(t, detail::power_label(std::pow(10.0, e))); + fn_tick(1 - t, "-" + detail::power_label(std::pow(10.0, e))); + } + } + break; + } + } + // The ends of the colorbar are the extreme values, not clipped: + if (mode == fn_mode::symlog_div) + { + fn_tick(0, "-" + detail::power_label(fsym)); + fn_tick(1, detail::power_label(fsym)); + } + else + { + fn_tick(0, mode == fn_mode::log_seq ? detail::power_label(fmin) : fn_number(mode == fn_mode::linear_div ? -fsym : fmin)); + fn_tick(1, mode == fn_mode::log_seq ? detail::power_label(fmax) : fn_number(mode == fn_mode::linear_div ? fsym : fmax)); + } + int const fn_label_x = (std::min)(bar_x + bar_width + 8 + fn_label_width + 16, total_width - 10); + fs << "" << fn_quantity << "\n"; + } + fs << "\n"; +} + +} BOOST_MATH_NAMESPACE_END +#endif // BOOST_MATH_TOOLS_ULPS_HEATMAP_HPP diff --git a/include/boost/math/tools/ulps_plot.hpp b/include/boost/math/tools/ulps_plot.hpp index 8e3995673b..55798e0ec3 100644 --- a/include/boost/math/tools/ulps_plot.hpp +++ b/include/boost/math/tools/ulps_plot.hpp @@ -4,6 +4,7 @@ // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_TOOLS_ULP_PLOT_HPP #define BOOST_MATH_TOOLS_ULP_PLOT_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include @@ -16,25 +17,999 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif #include -#include +#include #ifndef BOOST_MATH_STANDALONE #include #endif +// The data layer (points, markers, envelope, curves) is drawn into PNGs embedded in the SVG, while the axes and text +// stay vector; see png_encoder. lodepng (https://github.com/lvandeve/lodepng) is the default encoder only on request, +// so that a program which merely has lodepng.h on its include path still links: define BOOST_MATH_USE_LODEPNG, +// or include lodepng.h before this header, and link lodepng.cpp. Otherwise there is no default encoder. +#if defined(BOOST_MATH_USE_LODEPNG) && !defined(LODEPNG_H) +#include "lodepng.h" +#endif +#ifdef LODEPNG_H +#define BOOST_MATH_ULPS_HAS_LODEPNG +#define BOOST_MATH_ULPS_HEATMAP_HAS_LODEPNG +#endif + // Design of this function comes from: // https://blogs.mathworks.com/cleve/2017/01/23/ulps-plots-reveal-math-function-accurary/ // The envelope is the maximum of 1/2 and half the condition number of function evaluation. +// +// Sampling: the abscissas are a uniform grid in the plotted coordinate (x, or log(x) on a logarithmic axis), plus random +// probes between the grid points. The condition number |x f'(x)/f(x)| at the grid points comes from finite differences of +// the reference values on the grid (see detail::grid_condition_numbers), so it costs no extra evaluations of f. -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { namespace detail { + +// Encodes 8-bit RGB pixels, row-major from the top row, as a PNG. +using png_encoder_type = std::function(std::vector const &, std::size_t, std::size_t)>; + +inline png_encoder_type default_png_encoder() +{ +#ifdef BOOST_MATH_ULPS_HAS_LODEPNG + return [](std::vector const & rgb, std::size_t width, std::size_t height) { + std::vector png; + unsigned error = lodepng::encode(png, rgb, static_cast(width), static_cast(height), LCT_RGB); + if (error) + { + throw std::runtime_error(std::string("lodepng: ") + lodepng_error_text(error)); + } + return png; + }; +#else + return nullptr; +#endif +} + +inline std::string base64(std::vector const & bytes) +{ + static constexpr char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + std::string out; + out.reserve(4*((bytes.size() + 2)/3)); + for (std::size_t i = 0; i < bytes.size(); i += 3) + { + std::uint32_t n = std::uint32_t(bytes[i]) << 16; + if (i + 1 < bytes.size()) { n |= std::uint32_t(bytes[i + 1]) << 8; } + if (i + 2 < bytes.size()) { n |= bytes[i + 2]; } + out += table[(n >> 18) & 63]; + out += table[(n >> 12) & 63]; + out += i + 1 < bytes.size() ? table[(n >> 6) & 63] : '='; + out += i + 2 < bytes.size() ? table[n & 63] : '='; + } + return out; +} + +// Runs body(j) for j in [0, n) on several threads; all of the hardware's if threads is 0. If body throws, no further +// work is handed out, and the first exception is rethrown once the threads have finished. +template +void parallel_for(std::size_t n, unsigned threads, Body body) +{ + if (n == 0) + { + return; + } + if (threads == 0) + { + threads = (std::max)(1u, std::thread::hardware_concurrency()); + } + if (threads == 1 || n == 1) + { + for (std::size_t j = 0; j < n; ++j) + { + body(j); + } + return; + } + threads = static_cast((std::min)(static_cast(threads), n)); + std::atomic next{0}; + std::atomic failed{false}; + std::exception_ptr error; + std::mutex error_mutex; + auto work = [&]() { + try + { + for (std::size_t j = next++; j < n && !failed; j = next++) + { + body(j); + } + } + catch (...) + { + std::lock_guard lock(error_mutex); + if (!error) + { + error = std::current_exception(); + } + failed = true; + } + }; + std::vector pool; + try + { + for (unsigned t = 0; t < threads; ++t) + { + pool.emplace_back(work); + } + } + catch (...) + { + // Couldn't start a thread: stop the ones already running and report it. + failed = true; + for (auto & th : pool) + { + th.join(); + } + throw; + } + for (auto & th : pool) + { + th.join(); + } + if (error) + { + std::rethrow_exception(error); + } +} + +#ifdef BOOST_MATH_STANDALONE +// Uniform random numbers in [lo, hi) of a type that std::uniform_real_distribution may not support. +template::value> +class standalone_uniform +{ +public: + standalone_uniform(Real const & lo, Real const & hi) : lo_(lo), hi_(hi) {} + + template + Real operator()(Gen & gen) { return lo_ + (hi_ - lo_)*static_cast(unit_(gen)); } + +private: + Real lo_; + Real hi_; + std::uniform_real_distribution unit_{0.0L, 1.0L}; +}; + +template +class standalone_uniform : public std::uniform_real_distribution +{ +public: + using std::uniform_real_distribution::uniform_real_distribution; +}; +#endif + +// ---- Condition numbers by finite differences on a grid ---- + +// How well a finite-difference derivative must agree with a lower-order one to be trusted, as a fraction of +// max(|f|/|x|, |f'|): that is, of the scale on which an error in f' changes the condition number |x f'/f|. +constexpr double fd_tolerance = 0.05; + +// The largest span of a stencil, relative to |x|, that is trusted. The condition number is relative, and many +// functions vary on the scale of |x| itself (log(x), x^a, near 0 or on a coarse logarithmic grid), where a stencil +// as wide as |x| can pass the agreement test and still be badly wrong. On a logarithmic axis this asks for about +// 20 grid points per decade; on a linear one, it sends the few points within 8 grid steps of 0 to a local difference. +constexpr double fd_max_span = 0.5; + +// f'(t[j]) from the polynomial interpolating (t[k], f[k]), k < n: sum over k != j of L_k'(t[j]) (f[k] - f[j]). +template +Real derivative_at_node(Real const * t, Real const * f, int n, int j) +{ + Real d = 0; + for (int k = 0; k < n; ++k) + { + if (k == j) + { + continue; + } + Real num = 1; + Real den = t[k] - t[j]; + for (int m = 0; m < n; ++m) + { + if (m != k && m != j) + { + num *= t[j] - t[m]; + den *= t[k] - t[m]; + } + } + d += (num/den)*(f[k] - f[j]); + } + return d; +} + +// The Lagrange basis polynomials of the nodes t[0..n) at s. +template +void lagrange_weights(Real const * t, int n, Real const & s, Real * w) +{ + for (int k = 0; k < n; ++k) + { + Real num = 1; + Real den = 1; + for (int m = 0; m < n; ++m) + { + if (m != k) + { + num *= s - t[m]; + den *= t[k] - t[m]; + } + } + w[k] = num/den; + } +} + +// The start of the window of four consecutive nodes of t[0..n) (sorted, ascending or descending) around s. +template +std::size_t interpolation_window(Real const * t, std::size_t n, Real const & s) +{ + bool const ascending = t[0] < t[n - 1]; + std::size_t lo = 0; + std::size_t hi = n; + // The number of nodes on the near side of s: + while (lo < hi) + { + std::size_t mid = (lo + hi)/2; + if (ascending ? (t[mid] <= s) : (t[mid] >= s)) { lo = mid + 1; } else { hi = mid; } + } + std::size_t start = lo >= 2 ? lo - 2 : 0; + return (std::min)(start, n - 4); +} + +// The derivative of f at each node x[j] of a grid of n nodes (sorted, ascending or descending), from the values f[j*stride]. +// Each comes from a five-point stencil: centered (fourth order) where it can be, shifted one-sided near the edges and next to +// values that are not finite. trusted[j*stride] says whether it agrees with the three-point (second order) estimate from the +// same values to within fd_tolerance*max(|f|/|x|, |f'|): if not, f is not smooth on the scale of the grid there (a pole, +// a kink, a narrow feature, or too coarse a grid), and the condition number should be computed some other way. +// d is NaN where f is not finite or no stencil fits. +template +void grid_derivatives(Real const * x, Real const * f, std::size_t stride, std::size_t n, Real * d, unsigned char * trusted) +{ + using std::abs; + using std::isfinite; + static constexpr int offsets[5] = {-2, -1, -3, 0, -4}; + for (std::size_t j = 0; j < n; ++j) + { + d[j*stride] = std::numeric_limits::quiet_NaN(); + trusted[j*stride] = 0; + if (!isfinite(f[j*stride]) || n < 5) + { + continue; + } + long start = -1; + for (int o : offsets) + { + long s = static_cast(j) + o; + if (s < 0 || s + 4 >= static_cast(n)) + { + continue; + } + bool finite = true; + for (long k = s; k < s + 5; ++k) + { + finite = finite && isfinite(f[static_cast(k)*stride]); + } + if (finite) + { + start = s; + break; + } + } + if (start < 0) + { + continue; + } + Real ts[5]; + Real fs[5]; + for (int k = 0; k < 5; ++k) + { + ts[k] = x[start + k]; + fs[k] = f[static_cast(start + k)*stride]; + } + int const jj = static_cast(static_cast(j) - start); + Real const d5 = derivative_at_node(ts, fs, 5, jj); + int const s3 = (std::min)(2, (std::max)(0, jj - 1)); + Real const d3 = derivative_at_node(ts + s3, fs + s3, 3, jj - s3); + d[j*stride] = d5; + // |x| |d5 - d3| <= tol max(|f|, |x d5|), with a stencil narrow compared to |x|. Both hold trivially at x = 0, + // where the condition number is 0: + Real const ax = abs(x[j]); + trusted[j*stride] = isfinite(d5) && (ax == 0 || abs(ts[4] - ts[0]) <= Real(fd_max_span)*ax) + && ax*abs(d5 - d3) <= Real(fd_tolerance)*(std::max)(Real(abs(fs[jj])), Real(ax*abs(d5))); + } +} + +// |x f'(x)/fx| at a single point, with fx = f(x), from a central difference with relative step cbrt(eps), or a one-sided one +// with relative step sqrt(eps) if a side is undefined. Two or three extra evaluations of f; used where the grid can't be trusted. +template +Real local_condition_number(F const & f, Real const & x, Real const & fx) +{ + using std::abs; + using std::isfinite; + using std::pow; + using std::sqrt; + if (x == 0) + { + return 0; + } + static Real const cbrt_eps = pow(std::numeric_limits::epsilon(), Real(1)/3); + Real const sqrt_eps = sqrt(std::numeric_limits::epsilon()); +#ifndef BOOST_MATH_NO_EXCEPTIONS + try + { +#endif + Real xp = x + x*cbrt_eps; + Real xm = x - x*cbrt_eps; + Real slope = (f(xp) - f(xm))/(xp - xm); + if (isfinite(slope)) + { + return abs(x*slope/fx); + } +#ifndef BOOST_MATH_NO_EXCEPTIONS + } + catch (...) + { + } +#endif + for (int sign : {1, -1}) + { +#ifndef BOOST_MATH_NO_EXCEPTIONS + try + { +#endif + Real xh = x + sign*x*sqrt_eps; + Real slope = (f(xh) - fx)/(xh - x); + if (isfinite(slope)) + { + return abs(x*slope/fx); + } +#ifndef BOOST_MATH_NO_EXCEPTIONS + } + catch (...) + { + } +#endif + } + return std::numeric_limits::quiet_NaN(); +} + +// Given the grid derivatives d (from grid_derivatives) of f on the grid x[0..n), estimates f'(s) at a point s between the +// nodes from the cubic through the four nearest grid derivatives. f' is smooth where f has a simple zero, so dividing by the +// exact f(s) = fs gives the narrow spike of |s f'/f| there exactly, which interpolating the condition number would smear out. +// The estimate is used only if the four nodes are trusted and the cubic through the grid values of f predicts fs well enough +// that the condition number is good to about fd_tolerance; otherwise f has a feature between the nodes, and this returns false. +template +bool interpolate_derivative(Real const * x, Real const * f, Real const * d, unsigned char const * trusted, std::size_t n, + Real const & s, Real const & fs, Real & ds) +{ + using std::abs; + using std::isfinite; + if (n < 5) + { + return false; + } + std::size_t const start = interpolation_window(x, n, s); + for (std::size_t k = start; k < start + 4; ++k) + { + if (!trusted[k]) + { + return false; + } + } + Real w[4]; + lagrange_weights(x + start, 4, s, w); + Real fi = 0; + ds = 0; + for (std::size_t k = 0; k < 4; ++k) + { + fi += w[k]*f[start + k]; + ds += w[k]*d[start + k]; + } + // An error e in the interpolated f means an error of about e/h in f', so |s| e/(h |f|) in the condition number. + // As in grid_derivatives, the window must also be narrow compared to |s|: + Real const h = abs(x[start + 2] - x[start + 1]); + Real const as = abs(s); + return isfinite(ds) && (as == 0 || abs(x[start + 3] - x[start]) <= Real(fd_max_span)*as) + && as*abs(fi - fs) <= Real(fd_tolerance)*h*(std::max)(Real(abs(fs)), Real(as*abs(ds))); +} + +// The condition numbers |x f'(x)/f(x)| at the nodes of the grid x (sorted) with reference values fx = f(x), and at the probes +// px (anywhere in the grid's range) with values fpx, returned in pcond. Inf where f = 0, NaN where f is not finite. +// The grid's come from finite differences of fx (grid_derivatives), and the probes' from interpolate_derivative; where these +// can't be trusted, local_condition_number evaluates f at nearby points. If fallbacks isn't null, it receives the number of those. +// With threads other than 1, f must be thread safe. +template +std::vector grid_condition_numbers(F const & f, std::vector const & x, std::vector const & fx, + std::vector const & px, std::vector const & fpx, std::vector & pcond, + std::size_t * fallbacks = nullptr, unsigned threads = 1) +{ + using std::abs; + using std::isfinite; + std::size_t const n = x.size(); + std::atomic local{0}; + std::vector d(n); + std::vector trusted(n); + grid_derivatives(x.data(), fx.data(), 1, n, d.data(), trusted.data()); + std::vector cond(n, std::numeric_limits::quiet_NaN()); + std::size_t const chunk = 64; + parallel_for((n + chunk - 1)/chunk, threads, [&](std::size_t c) { + for (std::size_t j = c*chunk; j < (std::min)(n, (c + 1)*chunk); ++j) + { + if (!isfinite(fx[j])) + { + continue; + } + if (trusted[j]) + { + cond[j] = abs(x[j]*d[j]/fx[j]); + } + else + { + cond[j] = local_condition_number(f, x[j], fx[j]); + ++local; + } + } + }); + pcond.assign(px.size(), std::numeric_limits::quiet_NaN()); + parallel_for((px.size() + chunk - 1)/chunk, threads, [&](std::size_t c) { + for (std::size_t j = c*chunk; j < (std::min)(px.size(), (c + 1)*chunk); ++j) + { + if (!isfinite(fpx[j])) + { + continue; + } + Real dj; + if (interpolate_derivative(x.data(), fx.data(), d.data(), trusted.data(), n, px[j], fpx[j], dj)) + { + pcond[j] = abs(px[j]*dj/fpx[j]); + } + else + { + pcond[j] = local_condition_number(f, px[j], fpx[j]); + ++local; + } + } + }); + if (fallbacks) + { + *fallbacks = local; + } + return cond; +} + +// ---- Drawing the data layer ---- + +// Clips the segment (x0, y0)-(x1, y1) to the rectangle [xmin, xmax] x [ymin, ymax] (Liang-Barsky); false if nothing is left. +inline bool clip_segment(double & x0, double & y0, double & x1, double & y1, double xmin, double ymin, double xmax, double ymax) +{ + if (!(std::isfinite(x0) && std::isfinite(y0) && std::isfinite(x1) && std::isfinite(y1))) + { + return false; + } + double t0 = 0; + double t1 = 1; + double const dx = x1 - x0; + double const dy = y1 - y0; + double const p[4] = {-dx, dx, -dy, dy}; + double const q[4] = {x0 - xmin, xmax - x0, y0 - ymin, ymax - y0}; + for (int i = 0; i < 4; ++i) + { + if (p[i] == 0) + { + if (q[i] < 0) { return false; } + continue; + } + double r = q[i]/p[i]; + if (p[i] < 0) { t0 = (std::max)(t0, r); } else { t1 = (std::min)(t1, r); } + if (t0 > t1) { return false; } + } + double const ox = x0; + double const oy = y0; + x0 = ox + t0*dx; + y0 = oy + t0*dy; + x1 = ox + t1*dx; + y1 = oy + t1*dy; + return true; +} + +struct plot_point { double x; double y; }; + +// Draws the primitives of the data layer as SVG elements, clipped to a rectangle. Used when there is no PNG encoder. +class vector_canvas +{ +public: + vector_canvas(std::ostream & os, double x0, double y0, double width, double height, std::string const & id) + : os_(os), x0_(x0), y0_(y0), x1_(x0 + width), y1_(y0 + height) + { + os_ << "\n\n"; + } + void disk(std::string const & color, double cx, double cy, double r) + { + os_ << "\n"; + } + void segment(std::string const & color, double ax, double ay, double bx, double by, double width) + { + if (clip_segment(ax, ay, bx, by, x0_ - 1, y0_ - 1, x1_ + 1, y1_ + 1)) + { + os_ << "\n"; + } + } + void polygon(std::string const & color, std::vector const & p) + { + os_ << "\n"; + } + void polyline(std::string const & color, std::vector const & p, double width) + { + // One path per run of segments that stay (after clipping) inside the rectangle: + bool pen_down = false; + for (std::size_t i = 0; i + 1 < p.size(); ++i) + { + double ax = p[i].x, ay = p[i].y, bx = p[i + 1].x, by = p[i + 1].y; + if (!clip_segment(ax, ay, bx, by, x0_ - 1, y0_ - 1, x1_ + 1, y1_ + 1)) + { + end_path(pen_down, color, width); + continue; + } + if (!pen_down || ax != p[i].x || ay != p[i].y) + { + end_path(pen_down, color, width); + os_ << "\n"; + pen_down = false; + } + } + std::ostream & os_; + double x0_, y0_, x1_, y1_; +}; + +// A short name for SVG ids, from content, so that different plots inlined in one page don't collide. +inline std::string svg_id(std::string const & prefix, std::string const & content) +{ + std::uint64_t h = 1469598103934665603ULL; + for (char c : content) + { + h = (h ^ static_cast(c))*1099511628211ULL; + } + std::ostringstream os; + os << prefix << std::hex << (h & 0xffffffffffffULL); + return os.str(); +} + +// Rasterizes the primitives of the data layer, with 4x4 supersampling for antialiasing, into coverage masks. +// finish() writes each mask as a PNG in the SVG and paints its color through it, so colors stay CSS strings and the +// background, gridlines and text show through. A pixel of the mask covers one unit of the SVG's user space. +// +// Each pixel of a mask holds a bit for each of its 16 subsamples, and shapes are ORed in, so overlapping shapes of one +// color (adjacent points, the joints of a polyline) cover their union, neither more nor less. +// The masks are painted in order. A shape goes into the topmost mask of its color unless a mask of another color above +// that one covers any part of a pixel the shape covers (masks blend per pixel, so disjoint subsamples of one pixel still +// interact), in which case it starts a new mask on top; so the result is the same as painting the shapes one by one, +// with one mask per color in the usual case. max_masks limits the number of masks of each color, which bounds the size +// of the file when shapes of a few colors are interleaved: past it, a shape goes into the topmost mask of its color. +// Each color has a mask of its own, however many colors there are. +class raster_canvas +{ +public: + // The most masks of one color: + static constexpr std::size_t max_masks = 32; + + raster_canvas(double x0, double y0, int width, int height) + : x0_(x0), y0_(y0), width_(width), height_(height) + { + } + void disk(std::string const & color, double cx, double cy, double r) + { + fill(color, cx - r, cy - r, cx + r, cy + r, [&](double x, double y) { + return (x - cx)*(x - cx) + (y - cy)*(y - cy) <= r*r; + }); + } + void segment(std::string const & color, double ax, double ay, double bx, double by, double width) + { + double const h = width/2; + if (!clip_segment(ax, ay, bx, by, x0_ - h, y0_ - h, x0_ + width_ + h, y0_ + height_ + h)) + { + return; + } + double const dx = bx - ax; + double const dy = by - ay; + double const len2 = dx*dx + dy*dy; + fill(color, (std::min)(ax, bx) - h, (std::min)(ay, by) - h, (std::max)(ax, bx) + h, (std::max)(ay, by) + h, + [&](double x, double y) { + double t = len2 > 0 ? ((x - ax)*dx + (y - ay)*dy)/len2 : 0; + t = (std::min)(1.0, (std::max)(0.0, t)); + double ex = ax + t*dx - x; + double ey = ay + t*dy - y; + return ex*ex + ey*ey <= h*h; + }); + } + // A convex polygon: + void polygon(std::string const & color, std::vector const & p) + { + double xmin = p[0].x, xmax = p[0].x, ymin = p[0].y, ymax = p[0].y; + double area = 0; + for (std::size_t i = 0; i < p.size(); ++i) + { + plot_point const & a = p[i]; + plot_point const & b = p[(i + 1) % p.size()]; + xmin = (std::min)(xmin, a.x); xmax = (std::max)(xmax, a.x); + ymin = (std::min)(ymin, a.y); ymax = (std::max)(ymax, a.y); + area += a.x*b.y - b.x*a.y; + } + fill(color, xmin, ymin, xmax, ymax, [&](double x, double y) { + for (std::size_t i = 0; i < p.size(); ++i) + { + plot_point const & a = p[i]; + plot_point const & b = p[(i + 1) % p.size()]; + if (((b.x - a.x)*(y - a.y) - (b.y - a.y)*(x - a.x))*area < 0) + { + return false; + } + } + return true; + }); + } + // The union of the segments, so the joints are not painted twice: + void polyline(std::string const & color, std::vector const & p, double width) + { + for (std::size_t i = 0; i + 1 < p.size(); ++i) + { + segment(color, p[i].x, p[i].y, p[i + 1].x, p[i + 1].y, width); + } + } + // Writes the masks, bottom first. Their ids start with prefix and go on with a hash of their geometry, colors and content. + void finish(std::ostream & os, png_encoder_type const & encoder, std::string const & prefix) const + { + std::vector pngs; + std::ostringstream key; + key << x0_ << ' ' << y0_ << ' ' << width_ << ' ' << height_ << '\n'; + for (mask const & m : masks_) + { + std::vector rgb(3*m.bits.size()); + for (std::size_t k = 0; k < m.bits.size(); ++k) + { + unsigned n = 0; + for (unsigned b = m.bits[k]; b != 0; b &= b - 1) + { + ++n; + } + unsigned char v = static_cast((255*n + 8)/16); + rgb[3*k] = rgb[3*k + 1] = rgb[3*k + 2] = v; + } + pngs.push_back(base64(encoder(rgb, static_cast(width_), static_cast(height_)))); + key << m.color << '\n' << pngs.back() << '\n'; + } + std::string const id = svg_id(prefix, key.str()); + for (std::size_t l = 0; l < masks_.size(); ++l) + { + std::string mask_id = id + "-" + std::to_string(l); + os << "\n" + << "\n"; + } + } + std::size_t masks() const + { + return masks_.size(); + } +private: + struct mask + { + std::string color; + std::vector bits; + }; + std::size_t pixel(int i, int j) const + { + return static_cast(j)*static_cast(width_) + static_cast(i); + } + // Rasterizes the shape inside(x, y) within the box [xmin, xmax] x [ymin, ymax] (in user space), and ORs it into a mask. + template + void fill(std::string const & color, double xmin, double ymin, double xmax, double ymax, Inside inside) + { + if (!(xmin <= xmax && ymin <= ymax)) + { + return; + } + int const i0 = (std::max)(0, static_cast(std::floor((std::max)(xmin - x0_, -1.0)))); + int const i1 = (std::min)(width_ - 1, static_cast(std::floor((std::min)(xmax - x0_, double(width_))))); + int const j0 = (std::max)(0, static_cast(std::floor((std::max)(ymin - y0_, -1.0)))); + int const j1 = (std::min)(height_ - 1, static_cast(std::floor((std::min)(ymax - y0_, double(height_))))); + if (i0 > i1 || j0 > j1) + { + return; + } + std::size_t const bw = static_cast(i1 - i0 + 1); + auto box = [&](int i, int j) { return static_cast(j - j0)*bw + static_cast(i - i0); }; + shape_.assign(bw*static_cast(j1 - j0 + 1), 0); + bool any = false; + for (int j = j0; j <= j1; ++j) + { + for (int i = i0; i <= i1; ++i) + { + unsigned b = 0; + for (int sj = 0; sj < 4; ++sj) + { + for (int si = 0; si < 4; ++si) + { + if (inside(x0_ + i + (si + 0.5)/4, y0_ + j + (sj + 0.5)/4)) + { + b |= 1u << (4*sj + si); + } + } + } + shape_[box(i, j)] = static_cast(b); + any = any || b != 0; + } + } + if (!any) + { + return; + } + auto overlaps = [&](mask const & m) { + for (int j = j0; j <= j1; ++j) + { + for (int i = i0; i <= i1; ++i) + { + if (m.bits[pixel(i, j)] != 0 && shape_[box(i, j)] != 0) + { + return true; + } + } + } + return false; + }; + // The topmost mask of this color that no mask of another color above it overlaps: + std::size_t target = masks_.size(); + for (std::size_t l = masks_.size(); l-- > 0;) + { + if (masks_[l].color == color) + { + target = l; + break; + } + if (overlaps(masks_[l])) + { + break; + } + } + if (target == masks_.size()) + { + std::size_t same_color = 0; + std::size_t topmost = masks_.size(); + for (std::size_t l = 0; l < masks_.size(); ++l) + { + if (masks_[l].color == color) + { + ++same_color; + topmost = l; + } + } + if (same_color >= max_masks) + { + target = topmost; + } + } + if (target == masks_.size()) + { + masks_.push_back(mask{color, std::vector(static_cast(width_)*static_cast(height_), 0)}); + } + mask & m = masks_[target]; + for (int j = j0; j <= j1; ++j) + { + for (int i = i0; i <= i1; ++i) + { + m.bits[pixel(i, j)] = static_cast(m.bits[pixel(i, j)] | shape_[box(i, j)]); + } + } + } + double x0_; + double y0_; + int width_; + int height_; + std::vector masks_; + std::vector shape_; +}; + +// Significant digits that tell apart tick labels spaced (hi - lo)/intervals apart, and at least 4: +// a function that varies only in its sixth digit over the plot must not get identical labels. +inline int tick_precision(double lo, double hi, int intervals) +{ + double spacing = std::abs(hi - lo)/(std::max)(1, intervals); + double magnitude = (std::max)(std::abs(lo), std::abs(hi)); + if (!(spacing > 0) || !(magnitude > 0)) + { + return 4; + } + int digits = static_cast(std::ceil(std::log10(magnitude/spacing))) + 1; + return (std::min)(17, (std::max)(4, digits)); +} + +// Labels a tick on an axis spanning [lo, hi] with the given number of intervals between ticks. On a linear axis +// whose values are tiny or huge, use compact scientific notation (2e-4, 1.5e6) rather than a string of zeros. +inline std::string axis_label(double v, double lo, double hi, int intervals, bool log_axis) +{ + std::ostringstream os; + double magnitude = (std::max)(std::abs(lo), std::abs(hi)); + int precision = tick_precision(lo, hi, intervals); + if (log_axis || v == 0 || !(magnitude < 1e-2 || magnitude >= 1e5)) + { + os << std::setprecision(log_axis ? 4 : precision) << v; + return os.str(); + } + os << std::scientific << std::setprecision(precision - 1) << v; + std::string s = os.str(); + std::string::size_type e = s.find('e'); + std::string mantissa = s.substr(0, e); + if (mantissa.find('.') != std::string::npos) + { + mantissa.erase(mantissa.find_last_not_of('0') + 1); + if (mantissa.back() == '.') + { + mantissa.pop_back(); + } + } + return mantissa + "e" + std::to_string(std::stoi(s.substr(e + 1))); +} + + +// How an implementation's result relates to the true value, which is used to decide whether the ulps are meaningful. +enum class ulps_class : std::uint8_t +{ + // Both are in range: the ulps are meaningful. + ok, + // The true value is NaN or infinite (or its evaluation threw): f is undefined there. Not a defect. + undefined, + // |true value| > max: the implementation threw std::overflow_error or returned an infinity of the right sign. Correct. + overflow_handled, + // The true value is nonzero but below the smallest normal: the implementation returned zero or a subnormal of the right sign. Correct. + underflow_handled, + // The true value is a finite double, but the implementation returned NaN or threw something other than an overflow_error. A bug. + failed, + // The true value is a finite double, but the implementation threw std::overflow_error or returned an infinity. A bug. + spurious_overflow, + // The true value is out of range, but the implementation returned an ordinary number, NaN, the wrong sign, or threw something else. + // Counted as the maximal error. + mishandled +}; + +// Evaluates call() (which returns the implementation's value) and classifies the outcome against the true value z. +// When the result is ulps_class::ok, w holds the implementation's value. +template +ulps_class classify_result(PreciseReal const & z, Call call, CoarseReal & w, std::string * message = nullptr) +{ + using std::abs; + using std::isfinite; + using std::isinf; + using std::isnan; + if (!isfinite(z)) + { + return ulps_class::undefined; + } + bool const over = abs(z) > static_cast((std::numeric_limits::max)()); + bool const under = z != 0 && abs(z) < static_cast((std::numeric_limits::min)()); + try + { + w = static_cast(call()); + } + catch (std::overflow_error const & e) + { + if (message) { *message = std::string("std::overflow_error: ") + e.what(); } + return over ? ulps_class::overflow_handled : ulps_class::spurious_overflow; + } + catch (std::underflow_error const & e) + { + if (message) { *message = std::string("std::underflow_error: ") + e.what(); } + return under ? ulps_class::underflow_handled : ulps_class::failed; + } + catch (std::exception const & e) + { + if (message) { *message = e.what(); } + return (over || under) ? ulps_class::mishandled : ulps_class::failed; + } + catch (...) + { + if (message) { *message = "unknown exception"; } + return (over || under) ? ulps_class::mishandled : ulps_class::failed; + } + if (isnan(w)) + { + if (message) { *message = "returned NaN"; } + return (over || under) ? ulps_class::mishandled : ulps_class::failed; + } + if (isinf(w)) + { + if (message) { *message = "returned an infinity"; } + if (over) + { + return ((w > 0) == (z > 0)) ? ulps_class::overflow_handled : ulps_class::mishandled; + } + return ulps_class::spurious_overflow; + } + if (over) + { + return ulps_class::mishandled; + } + if (under) + { + bool const right_sign = (w == 0) || ((w > 0) == (z > 0)); + bool const tiny = abs(w) < (std::numeric_limits::min)(); + return (right_sign && tiny) ? ulps_class::underflow_handled : ulps_class::mishandled; + } + return ulps_class::ok; +} + +// Abscissas of the vertical gridlines: evenly spaced, or at whole powers of ten on a logarithmic axis. +template +std::vector vertical_gridlines(CoarseReal min_x, CoarseReal max_x, int vertical_lines, bool log_x) +{ + using std::ceil; + using std::floor; + using std::log10; + using std::pow; + std::vector xs; + if (!log_x) + { + for (int i = 1; i <= vertical_lines; ++i) + { + xs.push_back(min_x + ((max_x - min_x)*i)/vertical_lines); + } + return xs; + } + const int lo = static_cast(ceil(log10(min_x))); + const int hi = static_cast(floor(log10(max_x))); + const int step = (std::max)(1, static_cast(ceil(double(hi - lo)/(std::max)(1, vertical_lines)))); + for (int e = hi; e >= lo; e -= step) + { + xs.push_back(static_cast(pow(10.0L, e))); + } + std::reverse(xs.begin(), xs.end()); + return xs; +} + template void write_gridlines(std::ostream& fs, int horizontal_lines, int vertical_lines, F1 x_scale, F2 y_scale, CoarseReal min_x, CoarseReal max_x, PreciseReal min_y, PreciseReal max_y, - int graph_width, int graph_height, int margin_left, std::string const & font_color) + int graph_width, int graph_height, int margin_left, std::string const & font_color, bool log_x = false) { // Make a grid: for (int i = 1; i <= horizontal_lines; ++i) { @@ -50,8 +1025,7 @@ void write_gridlines(std::ostream& fs, int horizontal_lines, int vertical_lines, << std::setprecision(4) << y_cord_dataspace << "\n"; } - for (int i = 1; i <= vertical_lines; ++i) { - CoarseReal x_cord_dataspace = min_x + ((max_x - min_x)*i)/vertical_lines; + for (CoarseReal x_cord_dataspace : vertical_gridlines(min_x, max_x, vertical_lines, log_x)) { CoarseReal x = x_scale(x_cord_dataspace); fs << "" - << std::setprecision(4) << x_cord_dataspace << "\n"; + << axis_label(static_cast(x_cord_dataspace), static_cast(min_x), static_cast(max_x), vertical_lines, log_x) << "\n"; } } } @@ -67,8 +1041,15 @@ void write_gridlines(std::ostream& fs, int horizontal_lines, int vertical_lines, template class ulps_plot { public: + // Of the samples, 4/5 are a uniform grid in the plotted coordinate and 1/5 random probes, uniform in the same coordinate + // (seeded with random_seed, or randomly if it is -1). With perturb_abscissas, f is evaluated at the sample and the + // implementation at the nearest CoarseReal; otherwise both at the CoarseReal. + // With log_abscissas, the abscissas are sampled uniformly in log(x), and the x-axis is logarithmic; requires 0 < a. + // f, and the implementations passed to add_fn, are evaluated on this many threads (all of the hardware's if 0); with + // more than one, they must be thread safe. ulps_plot(F hi_acc_impl, CoarseReal a, CoarseReal b, - size_t samples = 1000, bool perturb_abscissas = false, int random_seed = -1); + size_t samples = 1000, bool perturb_abscissas = false, int random_seed = -1, bool log_abscissas = false, + unsigned threads = 1); ulps_plot& clip(PreciseReal clip); @@ -95,13 +1076,34 @@ class ulps_plot { ulps_plot& vertical_lines(int vertical_lines); + // Draws the function itself (the high-accuracy ordinates) in a second plot below the ulps plot, + // with the same width and x axis. Off by default. + ulps_plot& show_function(bool show_function); + + // With show_function, asks for a logarithmic y axis, which is useful when f spans many decades. It is used + // only if every finite value of f is positive; otherwise (f changes sign or is zero somewhere) the axis is linear. + ulps_plot& log_function(bool log_function); + + ulps_plot& function_color(std::string const & color); + + // Encodes 8-bit RGB pixels, row-major from the top row, as a PNG; lodepng by default, if lodepng.h is found. + // The points, markers and curves are drawn into PNGs embedded in the SVG, and the axes and text are vector. + // With no encoder (nullptr, or no lodepng.h), everything is drawn as SVG elements, as before. + using png_encoder_type = detail::png_encoder_type; + ulps_plot& png_encoder(png_encoder_type encoder); + void write(std::string const & filename) const; + // For each function added: counts of samples by outcome (see detail::ulps_class), the worst ulps and the worst + // ulps/envelope with the abscissas where they occur, and the first message of a failure. + std::string summary() const; + friend std::ostream& operator<<(std::ostream& fs, ulps_plot const & plot) { using std::abs; using std::floor; using std::isnan; + using std::isfinite; if (plot.ulp_list_.size() == 0) { throw std::domain_error("No functions added for comparison."); @@ -111,6 +1113,8 @@ class ulps_plot { throw std::domain_error("Width = " + std::to_string(plot.width_) + ", which is too small."); } + // The y range comes from the ulps alone (and clip). The condition number envelope never sets it: where the envelope + // leaves the plot (e.g. near poles) it is clipped to the plot area. PreciseReal worst_ulp_distance = 0; PreciseReal min_y = (std::numeric_limits::max)(); PreciseReal max_y = std::numeric_limits::lowest(); @@ -144,14 +1148,14 @@ class ulps_plot { if (plot.clip_ > 0) { - if (max_y > plot.clip_) + // With a clip, the range is symmetric, so that the ±envelope and the ticks are too: ±min(clip, worst |ulps|). + PreciseReal extent = (std::max)(max_y, PreciseReal(-min_y)); + if (extent > plot.clip_) { - max_y = plot.clip_; - } - if (min_y < -plot.clip_) - { - min_y = -plot.clip_; + extent = plot.clip_; } + max_y = extent; + min_y = -extent; } int height = static_cast(floor(static_cast(plot.width_)/1.61803)); @@ -170,6 +1174,11 @@ class ulps_plot { // Maps [a,b] to [0, graph_width] auto x_scale = [&](CoarseReal x)->CoarseReal { + using std::log; + if (plot.log_abscissas_) + { + return (log(x/plot.a_)/log(plot.b_/plot.a_))*static_cast(graph_width); + } return ((x-plot.a_)/(plot.b_ - plot.a_))*static_cast(graph_width); }; @@ -178,10 +1187,14 @@ class ulps_plot { return ((max_y - y)/(max_y - min_y) )*static_cast(graph_height); }; + // The function plot goes below the ulps plot, separated by room for the ulps plot's x tick labels: + int const function_gap = 40; + int const function_height = plot.show_function_ ? graph_height/2 : 0; + int const total_height = plot.show_function_ ? height + function_gap + function_height + margin_bottom : height; fs << "\n" << "\n" + << total_height << "'>\n" << "\n"; if (plot.title_.size() > 0) @@ -207,7 +1220,7 @@ class ulps_plot { if (worst_ulp_distance > 3) { detail::write_gridlines(fs, plot.horizontal_lines_, plot.vertical_lines_, x_scale, y_scale, plot.a_, plot.b_, - min_y, max_y, graph_width, graph_height, margin_left, plot.font_color_); + min_y, max_y, graph_width, graph_height, margin_left, plot.font_color_, plot.log_abscissas_); } else { @@ -228,9 +1241,8 @@ class ulps_plot { << std::setprecision(4) << y_cord_dataspace << "\n"; } } - for (int i = 1; i <= plot.vertical_lines_; ++i) + for (CoarseReal x_cord_dataspace : detail::vertical_gridlines(plot.a_, plot.b_, plot.vertical_lines_, plot.log_abscissas_)) { - CoarseReal x_cord_dataspace = plot.a_ + ((plot.b_ - plot.a_)*i)/plot.vertical_lines_; CoarseReal x = x_scale(x_cord_dataspace); fs << "" - << std::setprecision(4) << x_cord_dataspace << "\n"; + << detail::axis_label(static_cast(x_cord_dataspace), static_cast(plot.a_), static_cast(plot.b_), plot.vertical_lines_, plot.log_abscissas_) << "\n"; } } - int color_idx = 0; - for (auto const & ulp : plot.ulp_list_) - { - std::string color = plot.colors_[color_idx++]; - for (size_t j = 0; j < ulp.size(); ++j) + // Everything data-dependent (points, markers, the envelope) is clipped to the plot area, with room for the markers on its edges, + // so that nothing runs into the neighboring panel. With a PNG encoder it is rasterized, and drawn as SVG elements otherwise. + // + // Results that are not comparisons are marked on the edges, and counted in a legend: + // green triangle (top): NaN or a domain error, though the true value is a finite double (a bug); + // cyan diamond (top): spurious overflow: std::overflow_error or an infinity, though the true value is a finite double (a bug); + // yellow circle (top): out of range, but mishandled (counted as the maximal error); + // gray tick (bottom): correctly handled: the true value is undefined, overflows (and std::overflow_error or an infinity + // was returned), or underflows (and zero or a subnormal was returned). + std::string const nan_color = plot.nan_color_.empty() ? "#7fff00" : plot.nan_color_; + auto draw_data = [&](auto & canvas) { + size_t color_idx = 0; + for (auto const & ulp : plot.ulp_list_) { - if (isnan(ulp[j])) + std::string const & color = plot.colors_[color_idx++]; + // Cropped points are crosses, in the color of their function unless one was set, + // so that they stay distinguishable when several functions are plotted: + std::string const & crop_color = plot.crop_color_set_ ? plot.crop_color_ : color; + for (size_t j = 0; j < ulp.size(); ++j) { - if(plot.nan_color_ == "") + if (isnan(ulp[j])) + { + // Not a comparison: see the markers below. continue; - CoarseReal x = x_scale(plot.coarse_abscissas_[j]); - PreciseReal y = y_scale(static_cast(plot.clip_)); - fs << "\n"; - y = y_scale(static_cast(-plot.clip_)); - fs << "\n"; + } + double x = static_cast(x_scale(plot.coarse_abscissas_[j])); + if (plot.clip_ > 0 && static_cast(abs(ulp[j])) > plot.clip_) + { + if (crop_color.empty()) + { + continue; + } + double y = static_cast(y_scale(static_cast(ulp[j] < 0 ? -plot.clip_ : plot.clip_))); + canvas.segment(crop_color, x - 2.5, y - 2.5, x + 2.5, y + 2.5, 1); + canvas.segment(crop_color, x + 2.5, y - 2.5, x - 2.5, y + 2.5, 1); + } + else + { + canvas.disk(color, x, static_cast(y_scale(static_cast(ulp[j]))), 1); + } + } + } + for (auto const & classes : plot.class_list_) + { + for (size_t j = 0; j < classes.size(); ++j) + { + double x = static_cast(x_scale(plot.coarse_abscissas_[j])); + switch (classes[j]) + { + case detail::ulps_class::ok: + break; + case detail::ulps_class::failed: + canvas.polygon(nan_color, {{x - 3, 1}, {x + 3, 1}, {x, 8}}); + break; + case detail::ulps_class::spurious_overflow: + canvas.polygon("#00e5ff", {{x, 1}, {x + 4, 5}, {x, 9}, {x - 4, 5}}); + break; + case detail::ulps_class::mishandled: + canvas.disk("black", x, 5, 4); + canvas.disk("#ffe600", x, 5, 3.5); + break; + default: + canvas.segment("#888888", x, graph_height - 7, x, graph_height - 1, 1); + break; + } + } + } + if (plot.ulp_envelope_) + { + // ±cond, broken where it is undefined. Where it leaves the plot (near zeros and poles), it is clipped. + for (int sign : {1, -1}) + { + std::vector run; + for (size_t j = 0; j <= plot.cond_.size(); ++j) + { + if (j == plot.cond_.size() || isnan(plot.cond_[j])) + { + canvas.polyline(plot.envelope_color_, run, 1); + run.clear(); + continue; + } + run.push_back({static_cast(x_scale(plot.coarse_abscissas_[j])), static_cast(y_scale(sign*plot.cond_[j]))}); + } } - if (plot.clip_ > 0 && static_cast(abs(ulp[j])) > plot.clip_) + } + }; + if (plot.png_encoder_) + { + detail::raster_canvas canvas(-4, -4, graph_width + 8, graph_height + 8); + draw_data(canvas); + canvas.finish(fs, plot.png_encoder_, "ulps-"); + } + else + { + // The clip path's id depends only on what it defines, so a collision between plots is harmless: + detail::vector_canvas canvas(fs, -4, -4, graph_width + 8, graph_height + 8, + detail::svg_id("ulps-clip-", std::to_string(graph_width) + " " + std::to_string(graph_height))); + draw_data(canvas); + canvas.finish(); + } + { + size_t counts[7] = {0, 0, 0, 0, 0, 0, 0}; + for (auto const & classes : plot.class_list_) + { + for (detail::ulps_class c : classes) { - if (plot.crop_color_ == "") - continue; - CoarseReal x = x_scale(plot.coarse_abscissas_[j]); - PreciseReal y = y_scale(static_cast(ulp[j] < 0 ? -plot.clip_ : plot.clip_)); - fs << "\n"; + ++counts[static_cast(c)]; } - else + } + size_t gray = counts[1] + counts[2] + counts[3]; + struct entry { std::string text; size_t n; int kind; }; + std::vector legend = { + {"NaN or domain error", counts[4], 4}, + {"spurious overflow", counts[5], 5}, + {"out of range, mishandled", counts[6], 6}, + {"out of range or undefined, handled correctly", gray, 1}}; + int row = 0; + for (auto const & e : legend) + { + if (e.n == 0) { - CoarseReal x = x_scale(plot.coarse_abscissas_[j]); - PreciseReal y = y_scale(static_cast(ulp[j])); - fs << "\n"; + continue; } + int ly = 16 + 15*row++; + int lx = graph_width - 12; + std::string fill = e.kind == 4 ? nan_color : e.kind == 5 ? "#00e5ff" : e.kind == 6 ? "#ffe600" : "#888888"; + fs << "\n"; + fs << "" << e.text << " (" << e.n << ")\n"; } } - - if (plot.ulp_envelope_) + fs << "\n"; + if (plot.show_function_) { - std::string close_path = "' stroke='" + plot.envelope_color_ + "' stroke-width='1' fill='none'>\n"; - size_t jstart = 0; - while (plot.cond_[jstart] > max_y) + // The function, from the high-accuracy ordinates, on the same x axis as the ulps plot. + // f itself is plotted, never |f|. A logarithmic axis needs every finite f to be positive. + using std::log10; + using std::pow; + bool all_positive = true; + for (auto const & y : plot.precise_ordinates_) { - ++jstart; - if (jstart >= plot.cond_.size()) + if (isfinite(y) && !(y > 0)) { - goto done; + all_positive = false; } } - - size_t jmin = jstart; - new_top_path: - if (jmin >= plot.cond_.size()) + bool const log_f = plot.log_function_ && all_positive; + auto transform = [&](PreciseReal y)->PreciseReal { + return log_f ? log10(y) : y; + }; + auto usable = [&](PreciseReal y)->bool { + return isfinite(y); + }; + PreciseReal lo = (std::numeric_limits::max)(); + PreciseReal hi = std::numeric_limits::lowest(); + for (auto const & y : plot.precise_ordinates_) { - goto start_bottom_paths; + if (usable(y)) + { + PreciseReal t = transform(y); + lo = (std::min)(lo, t); + hi = (std::max)(hi, t); + } } - fs << "\n"; + fs << "\n"; + fs << "\n"; + // y gridlines and labels: + if (log_f) + { + int decades = static_cast(hi - lo); + int step = (std::max)(1, static_cast(std::ceil(double(decades)/plot.horizontal_lines_))); + for (int e = static_cast(hi); e >= static_cast(lo); e -= step) { - ++j; - while ( (j < plot.coarse_abscissas_.size() - 2) && bad) - { - bad = isnan(plot.cond_[j]) || (plot.cond_[j] > max_y); - ++j; - } - jmin = j; - fs << close_path; - goto new_top_path; + PreciseReal y = f_scale(static_cast(e)); + fs << "\n"; + fs << "1e" << e << "\n"; } - - CoarseReal t = x_scale(plot.coarse_abscissas_[j]); - PreciseReal y = y_scale(plot.cond_[j]); - fs << " L" << t << " " << y; } - fs << close_path; - start_bottom_paths: - jmin = jstart; - new_bottom_path: - if (jmin >= plot.cond_.size()) + else { - goto done; + int lines = (std::max)(2, plot.horizontal_lines_/2); + int precision = detail::tick_precision(static_cast(lo), static_cast(hi), lines); + for (int i = 0; i <= lines; ++i) + { + PreciseReal v = lo + ((hi - lo)*i)/lines; + PreciseReal y = f_scale(v); + fs << "\n"; + fs << "" << std::setprecision(precision) << v << "\n"; + } } - fs << "\n"; + fs << "" + << detail::axis_label(static_cast(x_cord_dataspace), static_cast(plot.a_), static_cast(plot.b_), plot.vertical_lines_, plot.log_abscissas_) << "\n"; + } + fs << "" << "f(x)" << "\n"; + // The curve, broken wherever the function is not finite: + auto draw_curve = [&](auto & canvas) { + std::vector run; + for (size_t j = 0; j <= plot.precise_ordinates_.size(); ++j) { - ++j; - while ( (j < plot.coarse_abscissas_.size() - 2) && bad) + if (j == plot.precise_ordinates_.size() || !usable(plot.precise_ordinates_[j])) { - bad = isnan(plot.cond_[j]) || (-plot.cond_[j] < min_y); - ++j; + canvas.polyline(plot.function_color_, run, 1); + run.clear(); + continue; } - jmin = j; - fs << close_path; - goto new_bottom_path; + run.push_back({static_cast(x_scale(plot.coarse_abscissas_[j])), + static_cast(f_scale(transform(plot.precise_ordinates_[j])))}); } - CoarseReal t = x_scale(plot.coarse_abscissas_[j]); - PreciseReal y = y_scale(-plot.cond_[j]); - fs << " L" << t << " " << y; + }; + if (plot.png_encoder_) + { + detail::raster_canvas canvas(-4, -4, graph_width + 8, function_height + 8); + draw_curve(canvas); + canvas.finish(fs, plot.png_encoder_, "ulps-f-"); + } + else + { + detail::vector_canvas canvas(fs, -4, -4, graph_width + 8, function_height + 8, + detail::svg_id("ulps-clip-", std::to_string(graph_width) + " " + std::to_string(function_height))); + draw_curve(canvas); + canvas.finish(); } - fs << close_path; + fs << "\n"; } - done: - fs << "\n" - << "\n"; + fs << "\n"; return fs; } @@ -359,9 +1523,13 @@ class ulps_plot { std::vector precise_ordinates_; std::vector cond_; std::list> ulp_list_; + std::list> class_list_; + std::list first_message_; std::vector colors_; CoarseReal a_; CoarseReal b_; + bool log_abscissas_; + unsigned threads_; PreciseReal clip_; int width_; std::string envelope_color_; @@ -372,9 +1540,22 @@ class ulps_plot { std::string background_color_; std::string font_color_; std::string crop_color_; + bool crop_color_set_ = false; std::string nan_color_; + bool show_function_ = false; + bool log_function_ = false; + std::string function_color_ = "orange"; + png_encoder_type png_encoder_ = detail::default_png_encoder(); + }; +template +ulps_plot& ulps_plot::png_encoder(png_encoder_type encoder) +{ + png_encoder_ = encoder; + return *this; +} + template ulps_plot& ulps_plot::envelope_color(std::string const & color) { @@ -410,6 +1591,27 @@ ulps_plot& ulps_plot::ve return *this; } +template +ulps_plot& ulps_plot::show_function(bool show_function) +{ + show_function_ = show_function; + return *this; +} + +template +ulps_plot& ulps_plot::log_function(bool log_function) +{ + log_function_ = log_function; + return *this; +} + +template +ulps_plot& ulps_plot::function_color(std::string const & color) +{ + function_color_ = color; + return *this; +} + template ulps_plot& ulps_plot::title(std::string const & title) { @@ -435,6 +1637,7 @@ template ulps_plot& ulps_plot::crop_color(std::string const & color) { crop_color_ = color; + crop_color_set_ = true; return *this; } @@ -453,7 +1656,7 @@ ulps_plot& ulps_plot::ul } namespace detail{ -bool ends_with(std::string const& filename, std::string const& suffix) +inline bool ends_with(std::string const& filename, std::string const& suffix) { if(filename.size() < suffix.size()) { @@ -464,10 +1667,62 @@ bool ends_with(std::string const& filename, std::string const& suffix) } } +template +std::string ulps_plot::summary() const +{ + using std::abs; + using std::isnan; + std::ostringstream os; + os << std::setprecision(std::numeric_limits::max_digits10); + auto uit = ulp_list_.begin(); + auto cit = class_list_.begin(); + auto mit = first_message_.begin(); + for (size_t f = 0; f < ulp_list_.size(); ++f, ++uit, ++cit, ++mit) + { + size_t counts[7] = {0, 0, 0, 0, 0, 0, 0}; + size_t first[7]; + for (size_t& v : first) { v = static_cast(-1); } + size_t worst_ulps = static_cast(-1); + size_t worst_ratio = static_cast(-1); + for (size_t j = 0; j < cit->size(); ++j) + { + size_t c = static_cast((*cit)[j]); + if (counts[c]++ == 0) { first[c] = j; } + if ((*cit)[j] != detail::ulps_class::ok) { continue; } + if (worst_ulps == static_cast(-1) || abs((*uit)[j]) > abs((*uit)[worst_ulps])) { worst_ulps = j; } + if (!isnan(cond_[j])) + { + PreciseReal r = abs(static_cast((*uit)[j]))/cond_[j]; + if (worst_ratio == static_cast(-1) || r > abs(static_cast((*uit)[worst_ratio]))/cond_[worst_ratio]) { worst_ratio = j; } + } + } + os << "samples=" << cit->size() << " ok=" << counts[0] << " undefined=" << counts[1] << " overflow_handled=" << counts[2] + << " underflow_handled=" << counts[3] << " green_nan_or_domain_error=" << counts[4] << " cyan_spurious_overflow=" << counts[5] + << " mishandled=" << counts[6] << "\n"; + if (worst_ulps != static_cast(-1)) + { + os << " worst_ulps=" << (*uit)[worst_ulps] << " at x=" << coarse_abscissas_[worst_ulps] << "\n"; + } + if (worst_ratio != static_cast(-1)) + { + os << " worst_ulps_over_envelope=" << (static_cast((*uit)[worst_ratio])/cond_[worst_ratio]) << " at x=" << coarse_abscissas_[worst_ratio] << "\n"; + } + char const * names[7] = {"", "", "", "", "green", "cyan", "mishandled"}; + for (size_t c = 4; c < 7; ++c) + { + if (counts[c] > 0) + { + os << " " << names[c] << ": first at x=" << coarse_abscissas_[first[c]] << (mit->empty() ? "" : ("; message: " + *mit)) << "\n"; + } + } + } + return os.str(); +} + template void ulps_plot::write(std::string const & filename) const { - if(!boost::math::tools::detail::ends_with(filename, ".svg")) + if(!BOOST_MATH_NAMESPACE::tools::detail::ends_with(filename, ".svg")) { throw std::logic_error("Only svg files are supported at this time."); } @@ -479,7 +1734,8 @@ void ulps_plot::write(std::string const & filename) template ulps_plot::ulps_plot(F hi_acc_impl, CoarseReal a, CoarseReal b, - size_t samples, bool perturb_abscissas, int random_seed) : crop_color_("red") + size_t samples, bool perturb_abscissas, int random_seed, bool log_abscissas, unsigned threads) + : threads_(threads), crop_color_("red") { // Use digits10 for this comparison in case the two types have differeing radixes: static_assert(std::numeric_limits::digits10 >= std::numeric_limits::digits10, "PreciseReal must have higher precision that CoarseReal"); @@ -491,8 +1747,38 @@ ulps_plot::ulps_plot(F hi_acc_impl, CoarseReal a, Co { throw std::domain_error("On interval [a,b], b > a is required."); } + if (log_abscissas && !(a > 0)) + { + throw std::domain_error("Logarithmic abscissas require a > 0."); + } a_ = a; b_ = b; + log_abscissas_ = log_abscissas; + + using std::exp; + using std::isfinite; + using std::log; + // A uniform grid in the plotted coordinate t (x, or log(x)), at the centres of grid_size cells spanning [a, b], gives the + // envelope by finite differences and most of the points. A quarter as many random probes (uniform in t) find the errors + // between the grid points: at integers and half-integers, which often take their own code paths and which a grid can + // hit or miss, and in narrow features such as the spikes of the condition number at zeros. + size_t const probes = samples/5; + size_t const grid_size = samples - probes; + PreciseReal const t_lo = log_abscissas ? static_cast(log(static_cast(a))) : static_cast(a); + PreciseReal const t_hi = log_abscissas ? static_cast(log(static_cast(b))) : static_cast(b); + // With perturb_abscissas, f is evaluated at x and the implementation at the nearest CoarseReal; otherwise both at the CoarseReal. + auto make_abscissa = [&](PreciseReal const & t, PreciseReal & precise, CoarseReal & coarse) { + PreciseReal x = log_abscissas ? static_cast(exp(t)) : t; + x = (std::min)((std::max)(x, static_cast(a)), static_cast(b)); + coarse = static_cast(x); + precise = perturb_abscissas ? x : static_cast(coarse); + }; + std::vector grid_x(grid_size); + std::vector grid_coarse(grid_size); + for (size_t i = 0; i < grid_size; ++i) + { + make_abscissa(t_lo + (t_hi - t_lo)*(static_cast(i) + PreciseReal(0.5))/static_cast(grid_size), grid_x[i], grid_coarse[i]); + } std::mt19937_64 gen; if (random_seed == -1) @@ -500,65 +1786,75 @@ ulps_plot::ulps_plot(F hi_acc_impl, CoarseReal a, Co std::random_device rd; gen.seed(rd()); } - + else + { + gen.seed(static_cast(random_seed)); + } // Boost's uniform_real_distribution can generate quad and multiprecision random numbers; std's cannot: #ifndef BOOST_MATH_STANDALONE - boost::random::uniform_real_distribution dis(static_cast(a), static_cast(b)); + boost::random::uniform_real_distribution dis(t_lo, t_hi); #else - // Use std::random in standalone mode if it is a type that the standard library can support (float, double, or long double) - static_assert(std::numeric_limits::digits10 <= std::numeric_limits::digits10, "Standalone mode does not support types with precision that exceeds long double"); - std::uniform_real_distribution dis(static_cast(a), static_cast(b)); + // std's can only generate float, double and long double; other types get a long double in [0, 1), which leaves the + // last bits of a multiprecision probe zero (or those of t_lo), but the probes needn't be uniform to the last bit: + detail::standalone_uniform dis(t_lo, t_hi); #endif - - precise_abscissas_.resize(samples); - coarse_abscissas_.resize(samples); - - if (perturb_abscissas) + std::vector probe_x(probes); + std::vector probe_coarse(probes); + for (size_t i = 0; i < probes; ++i) { - for(size_t i = 0; i < samples; ++i) - { - precise_abscissas_[i] = dis(gen); - } - std::sort(precise_abscissas_.begin(), precise_abscissas_.end()); - for (size_t i = 0; i < samples; ++i) + make_abscissa(dis(gen), probe_x[i], probe_coarse[i]); + } + + auto reference = [&](PreciseReal const & x) { +#ifndef BOOST_MATH_NO_EXCEPTIONS + try { - coarse_abscissas_[i] = static_cast(precise_abscissas_[i]); +#endif + return static_cast(hi_acc_impl(x)); +#ifndef BOOST_MATH_NO_EXCEPTIONS } - } - else - { - for(size_t i = 0; i < samples; ++i) + catch (...) { - coarse_abscissas_[i] = static_cast(dis(gen)); + return std::numeric_limits::quiet_NaN(); } - std::sort(coarse_abscissas_.begin(), coarse_abscissas_.end()); - for (size_t i = 0; i < samples; ++i) +#endif + }; + std::vector grid_y(grid_size); + std::vector probe_y(probes); + size_t const chunk = 64; + detail::parallel_for((samples + chunk - 1)/chunk, threads_, [&](size_t c) { + for (size_t i = c*chunk; i < (std::min)(samples, (c + 1)*chunk); ++i) { - precise_abscissas_[i] = static_cast(coarse_abscissas_[i]); + if (i < grid_size) { grid_y[i] = reference(grid_x[i]); } else { probe_y[i - grid_size] = reference(probe_x[i - grid_size]); } } - } + }); + std::vector probe_cond; + std::vector grid_cond = detail::grid_condition_numbers(reference, grid_x, grid_y, probe_x, probe_y, probe_cond, nullptr, threads_); - precise_ordinates_.resize(samples); + // Merge the grid and the probes, in order: + std::vector order(samples); for (size_t i = 0; i < samples; ++i) { - precise_ordinates_[i] = hi_acc_impl(precise_abscissas_[i]); + order[i] = i; } - - cond_.resize(samples, std::numeric_limits::quiet_NaN()); - for (size_t i = 0 ; i < samples; ++i) + auto precise_x = [&](size_t i) -> PreciseReal const & { return i < grid_size ? grid_x[i] : probe_x[i - grid_size]; }; + std::stable_sort(order.begin(), order.end(), [&](size_t i, size_t j) { return precise_x(i) < precise_x(j); }); + precise_abscissas_.resize(samples); + coarse_abscissas_.resize(samples); + precise_ordinates_.resize(samples); + cond_.resize(samples); + for (size_t k = 0; k < samples; ++k) { - PreciseReal y = precise_ordinates_[i]; - if (y != 0) - { - // Maybe cond_ is badly names; should it be half_cond_? - cond_[i] = boost::math::tools::evaluation_condition_number(hi_acc_impl, precise_abscissas_[i])/2; - // Half-ULP accuracy is the correctly rounded result, so make sure the envelop doesn't go below this: - if (cond_[i] < 0.5) - { - cond_[i] = 0.5; - } - } - // else leave it as nan. + size_t i = order[k]; + bool const grid = i < grid_size; + size_t const m = grid ? i : i - grid_size; + precise_abscissas_[k] = grid ? grid_x[m] : probe_x[m]; + coarse_abscissas_[k] = grid ? grid_coarse[m] : probe_coarse[m]; + precise_ordinates_[k] = grid ? grid_y[m] : probe_y[m]; + PreciseReal const c = grid ? grid_cond[m] : probe_cond[m]; + // cond_ is half the condition number, and never below the half-ulp of the correctly rounded result. + // It is NaN where f is zero or undefined: + cond_[k] = (isfinite(c) && precise_ordinates_[k] != 0) ? (std::max)(PreciseReal(c/2), PreciseReal(0.5)) : std::numeric_limits::quiet_NaN(); } clip_ = -1; width_ = 1100; @@ -576,16 +1872,44 @@ template ulps_plot& ulps_plot::add_fn(G g, std::string const & color) { using std::abs; + using std::isfinite; + using std::nextafter; size_t samples = precise_abscissas_.size(); - std::vector ulps(samples); + std::vector ulps(samples, std::numeric_limits::quiet_NaN()); + std::vector classes(samples, detail::ulps_class::ok); + std::vector messages(samples); + size_t const chunk = 64; + detail::parallel_for((samples + chunk - 1)/chunk, threads_, [&](size_t ch) { + for (size_t i = ch*chunk; i < (std::min)(samples, (ch + 1)*chunk); ++i) + { + PreciseReal y_hi_acc = precise_ordinates_[i]; + CoarseReal w = 0; + // The implementation is evaluated everywhere, even where the true value is out of range, to check that + // overflow and underflow are handled correctly: + detail::ulps_class c = detail::classify_result(y_hi_acc, [&]() { return g(coarse_abscissas_[i]); }, w, &messages[i]); + classes[i] = c; + if (c != detail::ulps_class::ok) + { + continue; + } + PreciseReal y_lo_acc = static_cast(w); + PreciseReal absy = abs(y_hi_acc); + PreciseReal dist = static_cast(nextafter(static_cast(absy), (std::numeric_limits::max)()) - static_cast(absy)); + ulps[i] = static_cast((y_lo_acc - y_hi_acc)/dist); + } + }); + std::string first_message; for (size_t i = 0; i < samples; ++i) { - PreciseReal y_hi_acc = precise_ordinates_[i]; - PreciseReal y_lo_acc = static_cast(g(coarse_abscissas_[i])); - PreciseReal absy = abs(y_hi_acc); - PreciseReal dist = static_cast(nextafter(static_cast(absy), (std::numeric_limits::max)()) - static_cast(absy)); - ulps[i] = static_cast((y_lo_acc - y_hi_acc)/dist); + detail::ulps_class const c = classes[i]; + if (!messages[i].empty() && (c == detail::ulps_class::failed || c == detail::ulps_class::spurious_overflow || c == detail::ulps_class::mishandled)) + { + first_message = messages[i]; + break; + } } + class_list_.emplace_back(classes); + first_message_.emplace_back(first_message); ulp_list_.emplace_back(ulps); colors_.emplace_back(color); return *this; @@ -594,5 +1918,5 @@ ulps_plot& ulps_plot::ad -} // namespace boost::math::tools +} BOOST_MATH_NAMESPACE_END // namespace boost::math::tools #endif diff --git a/include/boost/math/tools/univariate_statistics.hpp b/include/boost/math/tools/univariate_statistics.hpp index 98a97abac2..57e68c5357 100644 --- a/include/boost/math/tools/univariate_statistics.hpp +++ b/include/boost/math/tools/univariate_statistics.hpp @@ -6,9 +6,11 @@ #ifndef BOOST_MATH_TOOLS_UNIVARIATE_STATISTICS_HPP #define BOOST_MATH_TOOLS_UNIVARIATE_STATISTICS_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include +#endif #include #include @@ -22,7 +24,7 @@ BOOST_MATH_HEADER_DEPRECATED(""); -namespace boost::math::tools { +BOOST_MATH_NAMESPACE_BEGIN namespace tools { template auto mean(ForwardIterator first, ForwardIterator last) @@ -407,7 +409,7 @@ auto median_absolute_deviation(RandomAccessIterator first, RandomAccessIterator using std::isnan; if (isnan(center)) { - center = boost::math::tools::median(first, last); + center = BOOST_MATH_NAMESPACE::tools::median(first, last); } size_t num_elems = std::distance(first, last); BOOST_MATH_ASSERT_MSG(num_elems > 0, "The median of a zero-length vector is undefined."); @@ -433,5 +435,5 @@ inline auto median_absolute_deviation(RandomAccessContainer & v, typename Random return median_absolute_deviation(v.begin(), v.end(), center); } -} +} BOOST_MATH_NAMESPACE_END #endif diff --git a/include/boost/math/tools/user.hpp b/include/boost/math/tools/user.hpp index 6d3df000c0..2a09680cdf 100644 --- a/include/boost/math/tools/user.hpp +++ b/include/boost/math/tools/user.hpp @@ -70,11 +70,11 @@ // // #define BOOST_MATH_PROMOTE_FLOAT_POLICY true // -// Promote doubles to long double internally: +// Promote doubles to long double internally (the default is false): // // #define BOOST_MATH_PROMOTE_DOUBLE_POLICY true // -// What do discrete quantiles return? +// What do discrete quantiles return (the default is integer_round_up)? // // #define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_round_outwards // diff --git a/include/boost/math/tools/utility.hpp b/include/boost/math/tools/utility.hpp index 3e22865780..6d7aaecdc8 100644 --- a/include/boost/math/tools/utility.hpp +++ b/include/boost/math/tools/utility.hpp @@ -10,10 +10,11 @@ #ifndef BOOST_MATH_HAS_GPU_SUPPORT +#ifndef BOOST_MATH_BUILD_MODULE #include +#endif -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN template constexpr T min BOOST_MATH_PREVENT_MACRO_SUBSTITUTION (const T& a, const T& b) @@ -33,13 +34,11 @@ void swap BOOST_MATH_PREVENT_MACRO_SUBSTITUTION (T& a, T& b) return (std::swap)(a, b); } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #else -namespace boost { -namespace math { +BOOST_MATH_NAMESPACE_BEGIN template BOOST_MATH_GPU_ENABLED constexpr T min BOOST_MATH_PREVENT_MACRO_SUBSTITUTION (const T& a, const T& b) @@ -61,8 +60,7 @@ BOOST_MATH_GPU_ENABLED constexpr void swap BOOST_MATH_PREVENT_MACRO_SUBSTITUTION b = t; } -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_HAS_GPU_SUPPORT diff --git a/include/boost/math/tools/workaround.hpp b/include/boost/math/tools/workaround.hpp index 7edd1c12aa..830ab302ab 100644 --- a/include/boost/math/tools/workaround.hpp +++ b/include/boost/math/tools/workaround.hpp @@ -16,7 +16,7 @@ #include -namespace boost{ namespace math{ namespace tools{ +BOOST_MATH_NAMESPACE_BEGIN namespace tools{ // // We call this short forwarding function so that we can work around a bug // on Darwin that causes std::fmod to return a NaN. The test case is: @@ -36,7 +36,7 @@ inline long double fmod_workaround(long double a, long double b) noexcept } #endif -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_TOOLS_WORHAROUND_HPP diff --git a/include/boost/math/tr1.hpp b/include/boost/math/tr1.hpp index 0ec947b611..bd06532b9a 100644 --- a/include/boost/math/tr1.hpp +++ b/include/boost/math/tr1.hpp @@ -18,7 +18,7 @@ #include #include -namespace boost{ namespace math{ namespace tr1{ extern "C"{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C"{ #endif // __cplusplus @@ -384,113 +384,113 @@ long double BOOST_MATH_TR1_DECL boost_sph_neumannl BOOST_MATH_PREVENT_MACRO_SUBS #ifdef __cplusplus -}}}} // namespaces +}} BOOST_MATH_NAMESPACE_END #include -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ // // Declare overload of the functions which forward to the // C interfaces: // // C99 Functions: inline double acosh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_acosh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_acosh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float acoshf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_acoshf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_acoshf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double acoshl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_acoshl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_acoshl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float acosh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::acoshf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::acoshf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double acosh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::acoshl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::acoshl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type acosh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::acosh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::acosh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } inline double asinh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_asinh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_asinh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float asinhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_asinhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_asinhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double asinhl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_asinhl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_asinhl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float asinh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::asinhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::asinhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double asinh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::asinhl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::asinhl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type asinh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::asinh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::asinh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } inline double atanh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_atanh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_atanh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float atanhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_atanhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_atanhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double atanhl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_atanhl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_atanhl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float atanh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::atanhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::atanhf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double atanh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::atanhl(x); } +{ return BOOST_MATH_NAMESPACE::tr1::atanhl(x); } template inline typename tools::promote_args::type atanh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::atanh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::atanh BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } inline double cbrt BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_cbrt BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cbrt BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float cbrtf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_cbrtf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cbrtf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double cbrtl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_cbrtl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cbrtl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float cbrt BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::cbrtf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::cbrtf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double cbrt BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::cbrtl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::cbrtl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type cbrt BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::cbrt BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::cbrt BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } inline double copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) -{ return boost::math::tr1::boost_copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float copysignf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::boost_copysignf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_copysignf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double copysignl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::boost_copysignl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_copysignl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::copysignf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::copysignf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::copysignl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::copysignl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } template inline typename tools::promote_args::type copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 x, T2 y) -{ return boost::math::tr1::copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } +{ return BOOST_MATH_NAMESPACE::tr1::copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } inline double erf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_erf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_erf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float erff BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_erff BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_erff BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double erfl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_erfl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_erfl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float erf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::erff BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::erff BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double erf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::erfl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::erfl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type erf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::erf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::erf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } inline double erfc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_erfc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_erfc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float erfcf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_erfcf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_erfcf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double erfcl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_erfcl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_erfcl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float erfc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::erfcf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::erfcf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double erfc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::erfcl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::erfcl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type erfc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::erfc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::erfc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } #if 0 double exp2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x); @@ -499,18 +499,18 @@ long double exp2l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x); #endif inline float expm1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_expm1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_expm1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline double expm1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_expm1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_expm1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double expm1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_expm1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_expm1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float expm1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::expm1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::expm1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double expm1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::expm1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::expm1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type expm1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::expm1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::expm1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } #if 0 double fdim BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y); @@ -521,46 +521,46 @@ float fmaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y, float z); long double fmal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y, long double z); #endif inline double fmax BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) -{ return boost::math::tr1::boost_fmax BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_fmax BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float fmaxf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::boost_fmaxf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_fmaxf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double fmaxl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::boost_fmaxl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_fmaxl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float fmax BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::fmaxf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::fmaxf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double fmax BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::fmaxl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::fmaxl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } template inline typename tools::promote_args::type fmax BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 x, T2 y) -{ return boost::math::tr1::fmax BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } +{ return BOOST_MATH_NAMESPACE::tr1::fmax BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } inline double fmin BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) -{ return boost::math::tr1::boost_fmin BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_fmin BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float fminf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::boost_fminf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_fminf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double fminl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::boost_fminl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_fminl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float fmin BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::fminf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::fminf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double fmin BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::fminl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::fminl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } template inline typename tools::promote_args::type fmin BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 x, T2 y) -{ return boost::math::tr1::fmin BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } +{ return BOOST_MATH_NAMESPACE::tr1::fmin BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } inline float hypotf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::boost_hypotf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_hypotf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline double hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) -{ return boost::math::tr1::boost_hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double hypotl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::boost_hypotl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_hypotl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::hypotf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::hypotf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::hypotl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::hypotl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } template inline typename tools::promote_args::type hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 x, T2 y) -{ return boost::math::tr1::hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } +{ return BOOST_MATH_NAMESPACE::tr1::hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } #if 0 int ilogb BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x); @@ -569,18 +569,18 @@ int ilogbl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x); #endif inline float lgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_lgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_lgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline double lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double lgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_lgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_lgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::lgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::lgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::lgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::lgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } #ifdef BOOST_HAS_LONG_LONG #if 0 @@ -590,33 +590,33 @@ long long llrintl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x); #endif inline long long llroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_llroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_llroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long long llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long long llroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_llroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_llroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long long llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::llroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::llroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long long llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::llroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::llroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline long long llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) { return llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast(x)); } #endif inline float log1pf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_log1pf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_log1pf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline double log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double log1pl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_log1pl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_log1pl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::log1pf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::log1pf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::log1pl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::log1pl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } #if 0 double log2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x); float log2f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x); @@ -630,18 +630,18 @@ long lrintf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x); long lrintl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x); #endif inline long lroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_lroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_lroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long lroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_lroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_lroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::lroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::lroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::lroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::lroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template long lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast(x)); } #if 0 double nan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(const char *str); float nanf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(const char *str); @@ -651,32 +651,32 @@ float nearbyintf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x); long double nearbyintl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x); #endif inline float nextafterf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::boost_nextafterf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_nextafterf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline double nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) -{ return boost::math::tr1::boost_nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double nextafterl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::boost_nextafterl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_nextafterl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::nextafterf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::nextafterf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::nextafterl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::nextafterl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } template inline typename tools::promote_args::type nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 x, T2 y) -{ return boost::math::tr1::nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } +{ return BOOST_MATH_NAMESPACE::tr1::nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } inline float nexttowardf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::boost_nexttowardf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_nexttowardf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline double nexttoward BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) -{ return boost::math::tr1::boost_nexttoward BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_nexttoward BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double nexttowardl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::boost_nexttowardl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_nexttowardl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float nexttoward BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::nexttowardf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::nexttowardf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double nexttoward BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::nexttowardl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::nexttowardl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } template inline typename tools::promote_args::type nexttoward BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 x, T2 y) -{ return static_cast::type>(boost::math::tr1::nexttoward BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast(y))); } +{ return static_cast::type>(BOOST_MATH_NAMESPACE::tr1::nexttoward BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast(y))); } #if 0 double remainder BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y); float remainderf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y); @@ -689,18 +689,18 @@ float rintf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x); long double rintl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x); #endif inline float roundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_roundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_roundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline double round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double roundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_roundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_roundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::roundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::roundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::roundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::roundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } #if 0 double scalbln BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, long ex); float scalblnf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, long ex); @@ -710,32 +710,32 @@ float scalbnf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, int ex); long double scalbnl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, int ex); #endif inline float tgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_tgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_tgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline double tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double tgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_tgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_tgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::tgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::tgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::tgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::tgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } inline float truncf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_truncf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_truncf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline double trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double truncl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_truncl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_truncl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::truncf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::truncf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::truncl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::truncl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } # define NO_MACRO_EXPAND /**/ // C99 macros defined as C++ templates @@ -779,93 +779,93 @@ template<> bool BOOST_MATH_TR1_DECL isnormal NO_MACRO_EXPAND(long d // [5.2.1.1] associated Laguerre polynomials: inline float assoc_laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, unsigned m, float x) -{ return boost::math::tr1::boost_assoc_laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_assoc_laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } inline double assoc_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, unsigned m, double x) -{ return boost::math::tr1::boost_assoc_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_assoc_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } inline long double assoc_laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, unsigned m, long double x) -{ return boost::math::tr1::boost_assoc_laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_assoc_laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } inline float assoc_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, unsigned m, float x) -{ return boost::math::tr1::assoc_laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::assoc_laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } inline long double assoc_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, unsigned m, long double x) -{ return boost::math::tr1::assoc_laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::assoc_laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, x); } template inline typename tools::promote_args::type assoc_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, unsigned m, T x) -{ return boost::math::tr1::assoc_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::assoc_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, m, static_cast::type>(x)); } // [5.2.1.2] associated Legendre functions: inline float assoc_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, float x) -{ return boost::math::tr1::boost_assoc_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_assoc_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } inline double assoc_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, double x) -{ return boost::math::tr1::boost_assoc_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_assoc_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } inline long double assoc_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, long double x) -{ return boost::math::tr1::boost_assoc_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_assoc_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } inline float assoc_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, float x) -{ return boost::math::tr1::assoc_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::assoc_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } inline long double assoc_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, long double x) -{ return boost::math::tr1::assoc_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } +{ return BOOST_MATH_NAMESPACE::tr1::assoc_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, x); } template inline typename tools::promote_args::type assoc_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, T x) -{ return boost::math::tr1::assoc_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::assoc_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, static_cast::type>(x)); } // [5.2.1.3] beta function: inline float betaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::boost_betaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_betaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline double beta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) -{ return boost::math::tr1::boost_beta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_beta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double betal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::boost_betal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_betal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline float beta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) -{ return boost::math::tr1::betaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::betaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } inline long double beta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) -{ return boost::math::tr1::betal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } +{ return BOOST_MATH_NAMESPACE::tr1::betal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } template inline typename tools::promote_args::type beta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T2 x, T1 y) -{ return boost::math::tr1::beta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } +{ return BOOST_MATH_NAMESPACE::tr1::beta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x), static_cast::type>(y)); } // [5.2.1.4] (complete) elliptic integral of the first kind: inline float comp_ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float k) -{ return boost::math::tr1::boost_comp_ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_comp_ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } inline double comp_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double k) -{ return boost::math::tr1::boost_comp_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_comp_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } inline long double comp_ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double k) -{ return boost::math::tr1::boost_comp_ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_comp_ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } inline float comp_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float k) -{ return boost::math::tr1::comp_ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } +{ return BOOST_MATH_NAMESPACE::tr1::comp_ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } inline long double comp_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double k) -{ return boost::math::tr1::comp_ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } +{ return BOOST_MATH_NAMESPACE::tr1::comp_ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k); } template inline typename tools::promote_args::type comp_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T k) -{ return boost::math::tr1::comp_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(k)); } +{ return BOOST_MATH_NAMESPACE::tr1::comp_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(k)); } // [5.2.1.5] (complete) elliptic integral of the second kind: inline float comp_ellint_2f(float k) -{ return boost::math::tr1::boost_comp_ellint_2f(k); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_comp_ellint_2f(k); } inline double comp_ellint_2(double k) -{ return boost::math::tr1::boost_comp_ellint_2(k); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_comp_ellint_2(k); } inline long double comp_ellint_2l(long double k) -{ return boost::math::tr1::boost_comp_ellint_2l(k); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_comp_ellint_2l(k); } inline float comp_ellint_2(float k) -{ return boost::math::tr1::comp_ellint_2f(k); } +{ return BOOST_MATH_NAMESPACE::tr1::comp_ellint_2f(k); } inline long double comp_ellint_2(long double k) -{ return boost::math::tr1::comp_ellint_2l(k); } +{ return BOOST_MATH_NAMESPACE::tr1::comp_ellint_2l(k); } template inline typename tools::promote_args::type comp_ellint_2(T k) -{ return boost::math::tr1::comp_ellint_2(static_cast::type> BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k)); } +{ return BOOST_MATH_NAMESPACE::tr1::comp_ellint_2(static_cast::type> BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k)); } // [5.2.1.6] (complete) elliptic integral of the third kind: inline float comp_ellint_3f(float k, float nu) -{ return boost::math::tr1::boost_comp_ellint_3f(k, nu); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_comp_ellint_3f(k, nu); } inline double comp_ellint_3(double k, double nu) -{ return boost::math::tr1::boost_comp_ellint_3(k, nu); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_comp_ellint_3(k, nu); } inline long double comp_ellint_3l(long double k, long double nu) -{ return boost::math::tr1::boost_comp_ellint_3l(k, nu); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_comp_ellint_3l(k, nu); } inline float comp_ellint_3(float k, float nu) -{ return boost::math::tr1::comp_ellint_3f(k, nu); } +{ return BOOST_MATH_NAMESPACE::tr1::comp_ellint_3f(k, nu); } inline long double comp_ellint_3(long double k, long double nu) -{ return boost::math::tr1::comp_ellint_3l(k, nu); } +{ return BOOST_MATH_NAMESPACE::tr1::comp_ellint_3l(k, nu); } template inline typename tools::promote_args::type comp_ellint_3(T1 k, T2 nu) -{ return boost::math::tr1::comp_ellint_3(static_cast::type> BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k), static_cast::type> BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu)); } +{ return BOOST_MATH_NAMESPACE::tr1::comp_ellint_3(static_cast::type> BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k), static_cast::type> BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu)); } #if 0 // [5.2.1.7] confluent hypergeometric functions: @@ -876,139 +876,139 @@ long double conf_hypergl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double a, lo // [5.2.1.8] regular modified cylindrical Bessel functions: inline float cyl_bessel_if BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float nu, float x) -{ return boost::math::tr1::boost_cyl_bessel_if BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_bessel_if BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline double cyl_bessel_i BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double nu, double x) -{ return boost::math::tr1::boost_cyl_bessel_i BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_bessel_i BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline long double cyl_bessel_il BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double nu, long double x) -{ return boost::math::tr1::boost_cyl_bessel_il BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_bessel_il BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline float cyl_bessel_i BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float nu, float x) -{ return boost::math::tr1::cyl_bessel_if BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_bessel_if BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline long double cyl_bessel_i BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double nu, long double x) -{ return boost::math::tr1::cyl_bessel_il BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_bessel_il BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } template inline typename tools::promote_args::type cyl_bessel_i BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 nu, T2 x) -{ return boost::math::tr1::cyl_bessel_i BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(nu), static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_bessel_i BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(nu), static_cast::type>(x)); } // [5.2.1.9] cylindrical Bessel functions (of the first kind): inline float cyl_bessel_jf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float nu, float x) -{ return boost::math::tr1::boost_cyl_bessel_jf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_bessel_jf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline double cyl_bessel_j BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double nu, double x) -{ return boost::math::tr1::boost_cyl_bessel_j BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_bessel_j BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline long double cyl_bessel_jl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double nu, long double x) -{ return boost::math::tr1::boost_cyl_bessel_jl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_bessel_jl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline float cyl_bessel_j BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float nu, float x) -{ return boost::math::tr1::cyl_bessel_jf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_bessel_jf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline long double cyl_bessel_j BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double nu, long double x) -{ return boost::math::tr1::cyl_bessel_jl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_bessel_jl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } template inline typename tools::promote_args::type cyl_bessel_j BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 nu, T2 x) -{ return boost::math::tr1::cyl_bessel_j BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(nu), static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_bessel_j BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(nu), static_cast::type>(x)); } // [5.2.1.10] irregular modified cylindrical Bessel functions: inline float cyl_bessel_kf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float nu, float x) -{ return boost::math::tr1::boost_cyl_bessel_kf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_bessel_kf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline double cyl_bessel_k BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double nu, double x) -{ return boost::math::tr1::boost_cyl_bessel_k BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_bessel_k BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline long double cyl_bessel_kl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double nu, long double x) -{ return boost::math::tr1::boost_cyl_bessel_kl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_bessel_kl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline float cyl_bessel_k BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float nu, float x) -{ return boost::math::tr1::cyl_bessel_kf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_bessel_kf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline long double cyl_bessel_k BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double nu, long double x) -{ return boost::math::tr1::cyl_bessel_kl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_bessel_kl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } template inline typename tools::promote_args::type cyl_bessel_k BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 nu, T2 x) -{ return boost::math::tr1::cyl_bessel_k BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type> BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu), static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_bessel_k BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type> BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu), static_cast::type>(x)); } // [5.2.1.11] cylindrical Neumann functions; // cylindrical Bessel functions (of the second kind): inline float cyl_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float nu, float x) -{ return boost::math::tr1::boost_cyl_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline double cyl_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double nu, double x) -{ return boost::math::tr1::boost_cyl_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline long double cyl_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double nu, long double x) -{ return boost::math::tr1::boost_cyl_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_cyl_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline float cyl_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float nu, float x) -{ return boost::math::tr1::cyl_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } inline long double cyl_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double nu, long double x) -{ return boost::math::tr1::cyl_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(nu, x); } template inline typename tools::promote_args::type cyl_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 nu, T2 x) -{ return boost::math::tr1::cyl_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(nu), static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::cyl_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(nu), static_cast::type>(x)); } // [5.2.1.12] (incomplete) elliptic integral of the first kind: inline float ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float k, float phi) -{ return boost::math::tr1::boost_ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } inline double ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double k, double phi) -{ return boost::math::tr1::boost_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } inline long double ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double k, long double phi) -{ return boost::math::tr1::boost_ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } inline float ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float k, float phi) -{ return boost::math::tr1::ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::ellint_1f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } inline long double ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double k, long double phi) -{ return boost::math::tr1::ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::ellint_1l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } template inline typename tools::promote_args::type ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 k, T2 phi) -{ return boost::math::tr1::ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(k), static_cast::type>(phi)); } +{ return BOOST_MATH_NAMESPACE::tr1::ellint_1 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(k), static_cast::type>(phi)); } // [5.2.1.13] (incomplete) elliptic integral of the second kind: inline float ellint_2f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float k, float phi) -{ return boost::math::tr1::boost_ellint_2f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_ellint_2f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } inline double ellint_2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double k, double phi) -{ return boost::math::tr1::boost_ellint_2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_ellint_2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } inline long double ellint_2l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double k, long double phi) -{ return boost::math::tr1::boost_ellint_2l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_ellint_2l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } inline float ellint_2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float k, float phi) -{ return boost::math::tr1::ellint_2f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::ellint_2f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } inline long double ellint_2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double k, long double phi) -{ return boost::math::tr1::ellint_2l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::ellint_2l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, phi); } template inline typename tools::promote_args::type ellint_2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 k, T2 phi) -{ return boost::math::tr1::ellint_2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(k), static_cast::type>(phi)); } +{ return BOOST_MATH_NAMESPACE::tr1::ellint_2 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(k), static_cast::type>(phi)); } // [5.2.1.14] (incomplete) elliptic integral of the third kind: inline float ellint_3f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float k, float nu, float phi) -{ return boost::math::tr1::boost_ellint_3f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_ellint_3f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } inline double ellint_3 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double k, double nu, double phi) -{ return boost::math::tr1::boost_ellint_3 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_ellint_3 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } inline long double ellint_3l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double k, long double nu, long double phi) -{ return boost::math::tr1::boost_ellint_3l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_ellint_3l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } inline float ellint_3 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float k, float nu, float phi) -{ return boost::math::tr1::ellint_3f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::ellint_3f BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } inline long double ellint_3 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double k, long double nu, long double phi) -{ return boost::math::tr1::ellint_3l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } +{ return BOOST_MATH_NAMESPACE::tr1::ellint_3l BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(k, nu, phi); } template inline typename tools::promote_args::type ellint_3 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T1 k, T2 nu, T3 phi) -{ return boost::math::tr1::ellint_3 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(k), static_cast::type>(nu), static_cast::type>(phi)); } +{ return BOOST_MATH_NAMESPACE::tr1::ellint_3 BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(k), static_cast::type>(nu), static_cast::type>(phi)); } // [5.2.1.15] exponential integral: inline float expintf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::boost_expintf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_expintf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline double expint BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) -{ return boost::math::tr1::boost_expint BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_expint BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double expintl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::boost_expintl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_expintl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline float expint BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) -{ return boost::math::tr1::expintf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::expintf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } inline long double expint BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) -{ return boost::math::tr1::expintl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } +{ return BOOST_MATH_NAMESPACE::tr1::expintl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } template inline typename tools::promote_args::type expint BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T x) -{ return boost::math::tr1::expint BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::expint BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(x)); } // [5.2.1.16] Hermite polynomials: inline float hermitef BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, float x) -{ return boost::math::tr1::boost_hermitef BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_hermitef BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline double hermite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, double x) -{ return boost::math::tr1::boost_hermite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_hermite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline long double hermitel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, long double x) -{ return boost::math::tr1::boost_hermitel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_hermitel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline float hermite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, float x) -{ return boost::math::tr1::hermitef BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::hermitef BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline long double hermite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, long double x) -{ return boost::math::tr1::hermitel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::hermitel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } template inline typename tools::promote_args::type hermite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, T x) -{ return boost::math::tr1::hermite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::hermite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, static_cast::type>(x)); } #if 0 // [5.2.1.17] hypergeometric functions: @@ -1020,96 +1020,96 @@ long double x); // [5.2.1.18] Laguerre polynomials: inline float laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, float x) -{ return boost::math::tr1::boost_laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline double laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, double x) -{ return boost::math::tr1::boost_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline long double laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, long double x) -{ return boost::math::tr1::boost_laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline float laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, float x) -{ return boost::math::tr1::laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::laguerref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline long double laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, long double x) -{ return boost::math::tr1::laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::laguerrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } template inline typename tools::promote_args::type laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, T x) -{ return boost::math::tr1::laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::laguerre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, static_cast::type>(x)); } // [5.2.1.19] Legendre polynomials: inline float legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, float x) -{ return boost::math::tr1::boost_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } inline double legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, double x) -{ return boost::math::tr1::boost_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } inline long double legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, long double x) -{ return boost::math::tr1::boost_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } inline float legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, float x) -{ return boost::math::tr1::legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } +{ return BOOST_MATH_NAMESPACE::tr1::legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } inline long double legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, long double x) -{ return boost::math::tr1::legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } +{ return BOOST_MATH_NAMESPACE::tr1::legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, x); } template inline typename tools::promote_args::type legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, T x) -{ return boost::math::tr1::legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, static_cast::type>(x)); } // [5.2.1.20] Riemann zeta function: inline float riemann_zetaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float z) -{ return boost::math::tr1::boost_riemann_zetaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_riemann_zetaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } inline double riemann_zeta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double z) -{ return boost::math::tr1::boost_riemann_zeta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_riemann_zeta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } inline long double riemann_zetal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double z) -{ return boost::math::tr1::boost_riemann_zetal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_riemann_zetal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } inline float riemann_zeta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float z) -{ return boost::math::tr1::riemann_zetaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } +{ return BOOST_MATH_NAMESPACE::tr1::riemann_zetaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } inline long double riemann_zeta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double z) -{ return boost::math::tr1::riemann_zetal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } +{ return BOOST_MATH_NAMESPACE::tr1::riemann_zetal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(z); } template inline typename tools::promote_args::type riemann_zeta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(T z) -{ return boost::math::tr1::riemann_zeta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(z)); } +{ return BOOST_MATH_NAMESPACE::tr1::riemann_zeta BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(static_cast::type>(z)); } // [5.2.1.21] spherical Bessel functions (of the first kind): inline float sph_besself BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, float x) -{ return boost::math::tr1::boost_sph_besself BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_sph_besself BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline double sph_bessel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, double x) -{ return boost::math::tr1::boost_sph_bessel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_sph_bessel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline long double sph_bessell BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, long double x) -{ return boost::math::tr1::boost_sph_bessell BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_sph_bessell BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline float sph_bessel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, float x) -{ return boost::math::tr1::sph_besself BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::sph_besself BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline long double sph_bessel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, long double x) -{ return boost::math::tr1::sph_bessell BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::sph_bessell BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } template inline typename tools::promote_args::type sph_bessel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, T x) -{ return boost::math::tr1::sph_bessel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::sph_bessel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, static_cast::type>(x)); } // [5.2.1.22] spherical associated Legendre functions: inline float sph_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, float theta) -{ return boost::math::tr1::boost_sph_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_sph_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } inline double sph_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, double theta) -{ return boost::math::tr1::boost_sph_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_sph_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } inline long double sph_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, long double theta) -{ return boost::math::tr1::boost_sph_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_sph_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } inline float sph_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, float theta) -{ return boost::math::tr1::sph_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } +{ return BOOST_MATH_NAMESPACE::tr1::sph_legendref BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } inline long double sph_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, long double theta) -{ return boost::math::tr1::sph_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } +{ return BOOST_MATH_NAMESPACE::tr1::sph_legendrel BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, theta); } template inline typename tools::promote_args::type sph_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned l, unsigned m, T theta) -{ return boost::math::tr1::sph_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, static_cast::type>(theta)); } +{ return BOOST_MATH_NAMESPACE::tr1::sph_legendre BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(l, m, static_cast::type>(theta)); } // [5.2.1.23] spherical Neumann functions; // spherical Bessel functions (of the second kind): inline float sph_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, float x) -{ return boost::math::tr1::boost_sph_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_sph_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline double sph_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, double x) -{ return boost::math::tr1::boost_sph_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_sph_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline long double sph_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, long double x) -{ return boost::math::tr1::boost_sph_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::boost_sph_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline float sph_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, float x) -{ return boost::math::tr1::sph_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::sph_neumannf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } inline long double sph_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, long double x) -{ return boost::math::tr1::sph_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } +{ return BOOST_MATH_NAMESPACE::tr1::sph_neumannl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, x); } template inline typename tools::promote_args::type sph_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(unsigned n, T x) -{ return boost::math::tr1::sph_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, static_cast::type>(x)); } +{ return BOOST_MATH_NAMESPACE::tr1::sph_neumann BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(n, static_cast::type>(x)); } -}}} // namespaces +} BOOST_MATH_NAMESPACE_END #else // __cplusplus diff --git a/include/boost/math_fwd.hpp b/include/boost/math_fwd.hpp index cb044718d9..c76adbbccc 100644 --- a/include/boost/math_fwd.hpp +++ b/include/boost/math_fwd.hpp @@ -9,15 +9,14 @@ #ifndef BOOST_MATH_FWD_HPP #define BOOST_MATH_FWD_HPP -namespace boost -{ -namespace math -{ +#include + +BOOST_MATH_NAMESPACE_BEGIN // From ----------------------------------------// -template < typename T > +BOOST_MATH_EXPORT template < typename T > class quaternion; // Also has many function templates (including operators) @@ -25,7 +24,7 @@ template < typename T > // From ------------------------------------------// -template < typename T > +BOOST_MATH_EXPORT template < typename T > class octonion; template < > @@ -35,8 +34,7 @@ template < > template < > class octonion< long double >; -} // namespace math -} // namespace boost +BOOST_MATH_NAMESPACE_END #endif // BOOST_MATH_FWD_HPP diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt new file mode 100644 index 0000000000..e0167a5f88 --- /dev/null +++ b/module/CMakeLists.txt @@ -0,0 +1,195 @@ +# Copyright 2026 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +# +# Builds Boost.Math as a C++ module (boost.math) and runs the module-aware +# tests in ../test against it, consuming the standard library module +# (import std). This file is included from ../test/CMakeLists.txt when the +# CMake option BOOST_MATH_BUILD_MODULE is set and expects the Boost +# superproject (for the Boost:: dependency targets). import std is required +# (see the check below). + +if(NOT TARGET tests) + add_custom_target(tests) +endif() + +# The module interface unit. +add_library(boost_math_module) +target_sources(boost_math_module + PUBLIC + FILE_SET math_module TYPE CXX_MODULES FILES math.cppm +) +target_link_libraries(boost_math_module PUBLIC Boost::math) +target_compile_features(boost_math_module PUBLIC cxx_std_23) + +# The purview includes the library's angled headers by design. +# clang-scan-deps warns on that and ignores -Wno-include-angled-in-module-purview, +# so -w keeps the dependency-scan output clean (this glue unit's code is fully +# warned on in the header builds). +target_compile_options(boost_math_module PRIVATE $<$:-w>) + +# math.cppm defines BOOST_MATH_BUILD_MODULE and BOOST_MATH_STANDALONE itself, +# but the tests link this target and need both macros too: BOOST_MATH_BUILD_MODULE +# so they import the module instead of including the headers directly, and +# BOOST_MATH_STANDALONE so any textually included support header (for example +# test/math_unit_test.hpp -> tools/config.hpp) follows the same configuration +# branch the module was built with. +target_compile_definitions(boost_math_module PUBLIC BOOST_MATH_BUILD_MODULE BOOST_MATH_STANDALONE=1) + +# Export the detail-namespace entities that the tests exercise directly. +# Only the interface unit needs this, so keep it private to the module target. +target_compile_definitions(boost_math_module PRIVATE BOOST_MATH_EXPORT_TESTING) + +# Mixing textual standard library includes in consumers with a module built from +# header units trips include-translation bugs, so the standard library module is +# required for the test build. CMAKE_CXX_COMPILER_IMPORT_STD lists the standards +# it is available for; it is only populated when CMAKE_EXPERIMENTAL_CXX_IMPORT_STD +# is set before the project() call. +if(NOT "23" IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD) + message(FATAL_ERROR + "Building the Boost.Math module tests requires 'import std' (the C++23 " + "standard library module). Use a toolchain that supports it and pass " + "-DCMAKE_EXPERIMENTAL_CXX_IMPORT_STD= before the project() call. " + "CMAKE_CXX_COMPILER_IMPORT_STD='${CMAKE_CXX_COMPILER_IMPORT_STD}'") +endif() + +set_target_properties(boost_math_module PROPERTIES CXX_MODULE_STD ON) +target_compile_definitions(boost_math_module PRIVATE BOOST_MATH_USE_STD_MODULE) +message(STATUS "Boost.Math module: using 'import std;'") + +# Tests that switch to `import boost.math;` when BOOST_MATH_BUILD_MODULE is set. +# The list grows as components are added to the module interface unit. +set(BOOST_MATH_MODULE_TESTS + test_digamma_simple + test_expm1_simple + test_log1p_simple + git_issue_1194 + git_issue_1255 + git_issue_1294 + git_issue_800 + git_issue_1120 + scipy_issue_17146 + test_ccmath_isinf + test_ccmath_isnan + git_issue_1139 + test_cubic_roots + test_quartic_roots + git_issue_898 + test_cardinal_quadratic_b_spline + test_whittaker_shannon + test_runs_test + test_linear_regression + test_ljung_box + test_differential_evolution + test_random_search + test_quaternion_constexpr + octonion_test_simple + test_lambert_w_module + test_students_t_df_module + test_ccmath_next_module + test_lambert_w_std_free_module + test_exp_sinh_module + test_lanczos_smoothing_module + test_finite_difference_module + test_signal_statistics_module + # Differentiation + test_autodiff_module + # Quadrature + test_gauss_module + test_gauss_kronrod_module + test_trapezoidal_module + test_sinh_sinh_module + test_naive_monte_carlo_module + test_ooura_fourier_integrals_module + test_wavelet_transforms_module + # Interpolators + test_cardinal_cubic_b_spline_module + test_cardinal_quintic_b_spline_module + test_barycentric_rational_module + test_vector_barycentric_rational_module + test_catmull_rom_module + test_pchip_module + test_makima_module + test_cubic_hermite_module + test_quintic_hermite_module + test_septic_hermite_module + test_bezier_polynomial_module + #test_bilinear_uniform_module # ICE on GCC-15 + # Statistics + test_univariate_statistics_module + test_bivariate_statistics_module + test_anderson_darling_module + test_t_test_module + test_z_test_module + # Optimization + test_gradient_descent_module + test_lbfgs_module + test_nesterov_module + # Tools + test_polynomial_module + test_roots_module + test_fft_module + test_norms_module + test_agm_module + test_estrin_module + test_series_module + test_minima_module + # Algebra + test_complex_module + # Distributions (adapted regression tests) + git_issue_1006 + git_issue_1175 + git_issue_826 + scipy_issue_14901_ncf + scipy_issue_15101 + scipy_issue_17388 + scipy_issue_17916 + scipy_issue_17916_nct + scipy_issue_18302 + scipy_issue_18511 + # Special functions (adapted regression tests) + git_issue_705 + git_issue_810 + test_tgamma_eh + # Optimization / statistics (adapted) + test_jso + test_chatterjee_correlation +) + +# In module mode (BOOST_MATH_BUILD_MODULE, which also implies BOOST_MATH_STANDALONE) +# every consumer above is written to include no standard library header and no other +# Boost library textually: the standard library arrives through import std and +# boost.math through the module. A textual std header pulled in after the import trips +# a concept-merge failure on clang with libc++ and is rejected outright by GCC with +# libstdc++ and by MSVC, so keeping the consumers std-include-free is what lets the +# whole set build on all three toolchains rather than clang alone. +# +# test_lambert_w_std_free_module additionally names no standard library entity at all; +# it is the canary for GCC's C++20 module exposure rule (a namespace-scope entity with +# internal linkage cannot be reached from an exported template), which guards the +# BOOST_MATH_INLINE_CONSTEXPR fixes on the compiler that actually diagnoses them. + +# octonion_test_simple additionally uses Boost.MPL textually +set(BOOST_MATH_MODULE_EXTRA_LIBS_octonion_test_simple Boost::mpl) + +add_executable(module_quick_test "${CMAKE_CURRENT_SOURCE_DIR}/quick_test.cpp") +target_link_libraries(module_quick_test PRIVATE boost_math_module Boost::core) +# The superproject pins an older policy version (CMP0155), so C++ sources are not +# scanned for module imports by default. Force scanning so `import boost.math;` +# is resolved to the module built above. +set_target_properties(module_quick_test PROPERTIES CXX_SCAN_FOR_MODULES ON CXX_MODULE_STD ON) +add_test(NAME module_quick_test COMMAND module_quick_test) +add_dependencies(tests module_quick_test) + +foreach(test ${BOOST_MATH_MODULE_TESTS}) + add_executable(module_${test} "${CMAKE_CURRENT_SOURCE_DIR}/../test/${test}.cpp") + target_link_libraries(module_${test} + PRIVATE + boost_math_module + Boost::core + ${BOOST_MATH_MODULE_EXTRA_LIBS_${test}} + ) + set_target_properties(module_${test} PROPERTIES CXX_SCAN_FOR_MODULES ON CXX_MODULE_STD ON) + add_test(NAME module_${test} COMMAND module_${test}) + add_dependencies(tests module_${test}) +endforeach() diff --git a/module/Jamfile b/module/Jamfile new file mode 100644 index 0000000000..39996bf018 --- /dev/null +++ b/module/Jamfile @@ -0,0 +1,33 @@ +# Copyright 2026 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +# bring in the rules for testing +require-b2 5.0.1 ; +import-search /boost/config/checks ; +import config : requires ; +import modules ; +import testing ; +import path ; +import pch ; +import type ; + +# b2 registers the standard C++ suffixes (cpp cxx cc) but not cppm, so teach it +# that the .cppm module interface unit is a C++ source. +type.register-suffixes cppm : CPP ; + +project + : requirements + msvc:all + msvc:on + msvc:latest + + gcc:-fmodules-ts + gcc:23 + + clang:23 + ; + +obj math : math.cppm : BOOST_MATH_EXPORT_TESTING msvc:-interface ; + +run quick_test.cpp math : : : math ; diff --git a/module/math.cppm b/module/math.cppm new file mode 100644 index 0000000000..47fa0d423f --- /dev/null +++ b/module/math.cppm @@ -0,0 +1,234 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +module; + +// The module is always built in standalone mode so that no entity from another +// Boost library can attach itself to the boost.math module. +#ifndef BOOST_MATH_STANDALONE +# define BOOST_MATH_STANDALONE +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +# define BOOST_MATH_BUILD_MODULE +#endif + +// Marks this translation unit as the module interface unit (as opposed to a +// consumer that imports the module). Some headers key off this to declare +// entities here that consumers instead receive through the import. +#define BOOST_MATH_INTERFACE_UNIT + +// Platform intrinsic headers are not part of the standard library module, so +// they are always brought in here. The conditions mirror the include sites in +// special_functions/next.hpp and special_functions/detail/lanczos_sse2.hpp. +#if !defined(_CRAYC) && (!defined(__GNUC__) || (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 3))) +# if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(__SSE2__) +# include +# include +# endif +#endif + +// import std exports declarations but not macros. The headers below provide the +// feature-test macros and the object-like macros the library uses (assert, +// errno, FP_ classification, HUGE_VAL, FLT_/DBL_ limits, INT64_C, ...) so they +// are included regardless of whether import std is used. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// The macro hub and its helper entities are deliberately kept in the global +// module so that consumer translation units may also include them textually +// (for example through test/math_unit_test.hpp). +#include +#include + +// When the standard library module is available these are provided by import +// std, otherwise they are supplied here in the global module fragment. +#ifndef BOOST_MATH_USE_STD_MODULE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_MATH_NO_CXX17_HDR_EXECUTION +# include +#endif + +#endif // BOOST_MATH_USE_STD_MODULE + +export module boost.math; + +#ifdef BOOST_MATH_USE_STD_MODULE +import std; +#endif + +#ifdef _MSC_VER +# pragma warning( push ) +# pragma warning( disable : 5244 ) +#elif defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Winclude-angled-in-module-purview" +#endif + +extern "C++" { + +// Foundation components +#include +#include +#include + +// Special functions (umbrella) +#include +#include +#include + +// Statistical distributions (umbrella) +#include + +// Constexpr cmath (umbrella) +#include + +// Tools (curated public set) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Quadrature +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Interpolators (the deprecated boost::math namespace shims are intentionally excluded) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Statistics +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Optimization (cma_es is excluded: it requires Eigen) +#include +#include +#include +#include +#include +#include +#include +#include + +// Differentiation. finite_difference and lanczos_smoothing must precede +// autodiff: their unqualified detail:: references become ambiguous once +// autodiff's inline namespace introduces a second differentiation::detail. +#include +#include +#include + +// Algebra types and complex inverse trigonometric functions +#include +#include +#include + +} // extern "C++" + +#ifdef _MSC_VER +# pragma warning( pop ) +#elif defined(__clang__) +# pragma clang diagnostic pop +#endif diff --git a/module/quick_test.cpp b/module/quick_test.cpp new file mode 100644 index 0000000000..41199a00f8 --- /dev/null +++ b/module/quick_test.cpp @@ -0,0 +1,143 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Smoke test for the boost.math module: exercises at least one entity from +// every component exported by module/math.cppm. + +#include + +// The FP_ classification macros do not cross module boundaries, so +// is always included textually (before any import, which is the include +// ordering both libstdc++ and libc++ support). +#include + +// Import the STL if we can +#if defined(__cpp_lib_modules) && __cpp_lib_modules >= 202207L +import std; +#else +#include +#include +#include +#include +#endif + +import boost.math; + +int main() +{ + // constants + BOOST_TEST_GT(boost::math::constants::pi(), 3.14); + BOOST_TEST_LT(boost::math::constants::pi(), 3.15); + BOOST_TEST_EQ(boost::math::double_constants::half, 0.5); + static_assert(boost::math::float_constants::half == 0.5F, "float_constants"); + + // policies + const auto pol {boost::math::policies::make_policy( + boost::math::policies::domain_error())}; + static_cast(pol); + static_assert(boost::math::policies::is_policy::value, "is_policy"); + BOOST_TEST_GT((boost::math::policies::digits>()), 50); + + // error handling types are visible through the import + static_assert(boost::math::policies::is_noexcept_error_policy< + boost::math::policies::policy<>>::value == false, "default policy throws"); + + // special functions + BOOST_TEST_EQ(boost::math::tgamma(4.0), 6.0); + BOOST_TEST_EQ(boost::math::sign(-3.5), -1); + BOOST_TEST(boost::math::isnan(std::sqrt(-1.0))); + BOOST_TEST_EQ(boost::math::round(2.5), 3.0); + BOOST_TEST_EQ(boost::math::factorial(5), 120.0); + BOOST_TEST_EQ(boost::math::fpclassify(1.0), FP_NORMAL); + { + const auto erf_value {boost::math::erf(1.0)}; + BOOST_TEST_GT(erf_value, 0.84); + BOOST_TEST_LT(erf_value, 0.85); + const auto bessel_value {boost::math::cyl_bessel_j(0, 1.0)}; + BOOST_TEST_GT(bessel_value, 0.76); + BOOST_TEST_LT(bessel_value, 0.77); + } + + // ccmath + static_assert(boost::math::ccmath::abs(-1) == 1, "ccmath abs"); + static_assert(boost::math::ccmath::isnan(0.0) == false, "ccmath isnan"); + static_assert(boost::math::ccmath::sqrt(4.0) == 2.0, "ccmath sqrt"); + + // tools + { + const double coeffs[] {1.0, 2.0, 3.0}; + BOOST_TEST_EQ(boost::math::tools::evaluate_polynomial(coeffs, 2.0), 17.0); + const auto roots {boost::math::tools::cubic_roots(1.0, -6.0, 11.0, -6.0)}; + BOOST_TEST_EQ(roots[0], 1.0); + BOOST_TEST_EQ(roots[2], 3.0); + const boost::math::tools::polynomial p {{1.0, 1.0}}; + const auto p2 {p * p}; + BOOST_TEST_EQ(p2[1], 2.0); + } + + // quadrature and interpolators + { + const auto integral {boost::math::quadrature::trapezoidal( + [](double x) { return x * x; }, 0.0, 1.0)}; + BOOST_TEST_GT(integral, 0.333); + BOOST_TEST_LT(integral, 0.334); + std::vector v {0.0, 1.0, 4.0, 9.0, 16.0}; + boost::math::interpolators::cardinal_cubic_b_spline spline {v.data(), v.size(), 0.0, 1.0}; + const auto interp {spline(2.0)}; + BOOST_TEST_GT(interp, 3.9); + BOOST_TEST_LT(interp, 4.1); + } + + // statistics and optimization + { + std::vector data {1.0, 2.0, 3.0, 4.0, 5.0}; + BOOST_TEST_EQ(boost::math::statistics::mean(data), 3.0); + BOOST_TEST_EQ(boost::math::statistics::median(data), 3.0); + boost::math::optimization::random_search_parameters> params {}; + params.lower_bounds = {-1.0}; + params.upper_bounds = {1.0}; + static_cast(params); + } + + // distributions + { + const boost::math::normal_distribution<> dist {}; + BOOST_TEST_EQ(boost::math::cdf(dist, 0.0), 0.5); + BOOST_TEST_EQ(boost::math::median(dist), 0.0); + BOOST_TEST_EQ(boost::math::cdf(boost::math::complement(dist, 0.0)), 0.5); + const boost::math::students_t st {5.0}; + BOOST_TEST_GT(boost::math::pdf(st, 0.0), 0.37); + const auto q {boost::math::quantile(boost::math::binomial(50, 0.5), 0.5)}; + BOOST_TEST_GT(q, 24.0); + BOOST_TEST_LT(q, 26.0); + } + + // differentiation + { + const auto derivative {boost::math::differentiation::finite_difference_derivative( + [](double x) { return x * x; }, 1.0)}; + BOOST_TEST_GT(derivative, 1.99); + BOOST_TEST_LT(derivative, 2.01); + const auto x {boost::math::differentiation::make_fvar(3.0)}; + const auto y {x * x}; + BOOST_TEST_EQ(y.derivative(1), 6.0); + // std::numeric_limits partial specialization is reachable through the import + using fvar_type = decltype(x); + static_assert(std::numeric_limits::is_specialized, "autodiff limits"); + } + + // quaternion, octonion and complex inverse trig + { + const boost::math::quaternion q {1.0, 2.0, 3.0, 4.0}; + BOOST_TEST_EQ(boost::math::norm(q), 30.0); + const boost::math::octonion o {1.0, 1.0}; + BOOST_TEST_GT(boost::math::abs(o), 1.41); + const std::complex z {0.5, 0.0}; + const auto az {boost::math::asin(z)}; + BOOST_TEST_GT(az.real(), 0.52); + BOOST_TEST_LT(az.real(), 0.53); + } + + return boost::report_errors(); +} diff --git a/nanobind/CMakeLists.txt b/nanobind/CMakeLists.txt new file mode 100644 index 0000000000..69c096565f --- /dev/null +++ b/nanobind/CMakeLists.txt @@ -0,0 +1,92 @@ +# Copyright 2026 Nick Thompson +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +# +# Dev-only nanobind layer, not built by CI. Usage (venv with nanobind numpy mpmath pytest): +# cmake -S nanobind -B build-nb -G Ninja -DPython_EXECUTABLE=venv/bin/python && cmake --build build-nb +# PYTHONPATH=build-nb venv/bin/python -m pytest nanobind/tests + +cmake_minimum_required(VERSION 3.18) +project(boost_math_nanobind LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() +# Same optimisation level as CI. +set(CMAKE_CXX_FLAGS_RELEASE "-O2") + +find_package(Python 3.9 REQUIRED COMPONENTS Interpreter Development.Module) +if(NOT nanobind_DIR) + # -I: don't let this directory (also called nanobind) shadow the package. + execute_process( + COMMAND "${Python_EXECUTABLE}" -I -m nanobind --cmake_dir + OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nanobind_DIR + COMMAND_ERROR_IS_FATAL ANY) +endif() +find_package(nanobind CONFIG REQUIRED) + +set(BOOST_MATH_NB_SOURCES + src/module.cpp + src/gamma.cpp + src/beta.cpp + src/erf_expint_zeta.cpp + src/elementary.cpp + src/bessel.cpp + src/elliptic.cpp + src/jacobi_theta.cpp + src/polynomials.cpp + src/hypergeometric.cpp + src/distributions_continuous.cpp + src/distributions_heavy.cpp + src/distributions_discrete.cpp + src/distributions_noncentral.cpp + src/fft.cpp + src/quadrature.cpp + src/optimization.cpp + src/polynomial_roots.cpp +) + +nanobind_add_module(_ext NOMINSIZE ${BOOST_MATH_NB_SOURCES}) +target_include_directories(_ext PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../include" "${CMAKE_CURRENT_SOURCE_DIR}/src") +target_compile_definitions(_ext PRIVATE BOOST_MATH_STANDALONE) +# Optional: cma_es needs Eigen. +find_package(Eigen3 CONFIG QUIET) +if(Eigen3_FOUND) + target_link_libraries(_ext PRIVATE Eigen3::Eigen) +endif() +# Optional: boost.math.ulps needs Boost.Multiprecision (standalone, which needs Boost.Config) and zlib. Only the +# sibling checkouts (or the cache variables) are searched, never a system Boost of another release. +find_path(BOOST_MATH_NB_MULTIPRECISION_INCLUDE boost/multiprecision/cpp_bin_float.hpp + HINTS "${CMAKE_CURRENT_SOURCE_DIR}/../../multiprecision/include" "$ENV{HOME}/boost/libs/multiprecision/include" + DOC "Boost.Multiprecision's include directory, for boost.math.ulps" NO_DEFAULT_PATH) +find_path(BOOST_MATH_NB_CONFIG_INCLUDE boost/config.hpp + HINTS "${CMAKE_CURRENT_SOURCE_DIR}/../../config/include" "$ENV{HOME}/boost/libs/config/include" + DOC "Boost.Config's include directory, for boost.math.ulps" NO_DEFAULT_PATH) +find_package(ZLIB) +if(BOOST_MATH_NB_MULTIPRECISION_INCLUDE AND BOOST_MATH_NB_CONFIG_INCLUDE AND ZLIB_FOUND) + set(ulps_sources src/ulps.cpp src/ulps_gamma.cpp src/ulps_special.cpp src/ulps_elliptic.cpp) + target_sources(_ext PRIVATE ${ulps_sources}) + # Only these see Multiprecision, so that its presence changes nothing else: + set_source_files_properties(${ulps_sources} PROPERTIES + INCLUDE_DIRECTORIES "${BOOST_MATH_NB_MULTIPRECISION_INCLUDE};${BOOST_MATH_NB_CONFIG_INCLUDE}" + COMPILE_DEFINITIONS BOOST_MP_STANDALONE) + set_source_files_properties(src/module.cpp PROPERTIES COMPILE_DEFINITIONS BMPY_HAVE_ULPS) + target_link_libraries(_ext PRIVATE ZLIB::ZLIB) +else() + message(STATUS "boost.math.ulps disabled: needs Boost.Multiprecision, Boost.Config and zlib " + "(set BOOST_MATH_NB_MULTIPRECISION_INCLUDE and BOOST_MATH_NB_CONFIG_INCLUDE)") +endif() +if(NOT MSVC) + # Match CI and test/Makefile: contraction allowed everywhere. + target_compile_options(_ext PRIVATE -ffp-contract=fast) +endif() + +set(pkg_dir "${CMAKE_CURRENT_BINARY_DIR}/boost/math") +set_target_properties(_ext PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${pkg_dir}") +# The pure-Python files, copied on every build so that edits to them need no relink: +add_custom_target(boost_math_py ALL + COMMAND "${CMAKE_COMMAND}" -E make_directory "${pkg_dir}" + COMMAND "${CMAKE_COMMAND}" -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/boost/math/__init__.py" "${CMAKE_CURRENT_SOURCE_DIR}/boost/math/ulps.py" "${pkg_dir}") diff --git a/nanobind/boost/math/__init__.py b/nanobind/boost/math/__init__.py new file mode 100644 index 0000000000..0361fdce0b --- /dev/null +++ b/nanobind/boost/math/__init__.py @@ -0,0 +1,9 @@ +# Copyright 2026 Nick Thompson +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +"""Dev-only Boost.Math bindings; build instructions are in nanobind/CMakeLists.txt.""" + +from ._ext import * # noqa: F401,F403 +from . import _ext + +__all__ = [n for n in dir(_ext) if not n.startswith("_")] diff --git a/nanobind/boost/math/ulps.py b/nanobind/boost/math/ulps.py new file mode 100644 index 0000000000..efd5ca0edc --- /dev/null +++ b/nanobind/boost/math/ulps.py @@ -0,0 +1,130 @@ +# Copyright 2026 Nick Thompson +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +"""ulps plots and heatmaps from boost::math::tools::ulps_plot and ulps_heatmap; the reference is the same +function at cpp_bin_float_50, or reference= any Python callable (an mpmath function, say). For example: + + import boost.math as bm; from boost.math import ulps + ulps.plot(bm.digamma, -5, 5).save("digamma.svg") + ulps.render_to_png(ulps.heatmap(bm.lgamma_p, (1, 1e7), (0.01, 1e7), log_x=True, log_y=True)[0], "lgamma_p.png") +""" + +import math +import os +import re +import shutil +import subprocess +import tempfile + +from . import _ext + + +class Svg: + """An SVG: str() is its text, summary the C++ summary(); shown inline in Jupyter.""" + + def __init__(self, text, summary): + self.text = text + self.summary = summary + + def __str__(self): + return self.text + + def _repr_svg_(self): + return self.text + + def save(self, path): + with open(path, "w", encoding="utf-8") as f: + f.write(self.text) + return path + + +def _name(f): + if not hasattr(_ext, "_ulps_plot"): + raise RuntimeError("boost.math.ulps was built without Boost.Multiprecision or zlib; see nanobind/CMakeLists.txt") + if isinstance(f, str): + return f + if getattr(_ext, getattr(f, "__name__", ""), None) is not f: + raise TypeError("ulps plots need a boost.math function or its name; arbitrary Python callables are not supported") + return f.__name__ + + +def _python_reference(reference): + """Wraps reference for the C++ side: arguments come as floats, or as 55-digit strings (made mpmath numbers here) + where they aren't doubles, and the result goes back as a float or a decimal string; NaN if it raises or isn't real.""" + try: + import mpmath as mp + except ImportError: + raise ImportError("reference= needs mpmath: pip install mpmath") from None + + def call(*args): + try: + r = reference(*[mp.mpf(a) if isinstance(a, str) else a for a in args]) + if isinstance(r, mp.mpf): + return mp.nstr(r, 55) if mp.isfinite(r) else float(r) + return float(r) + except Exception: + return math.nan + + return call + + +def _run(fn, reference, threads): + if reference is None: + return fn(None, threads) + import mpmath as mp + call = _python_reference(reference) + # The Python calls are serialized anyway; more threads only add GIL churn: + with mp.workdps(60): + return fn(call, 1) + + +def plot(f, a, b, *, samples=10000, log_x=False, title=None, reference=None, clip=None, show_function=False, + threads=0): + """The ulps plot of f on [a, b]; threads=0 uses them all. reference= an mpmath-based callable replaces + the cpp_bin_float_50 reference, and runs on one thread.""" + name = _name(f) + svg, summary = _run(lambda ref, th: _ext._ulps_plot(name, a, b, samples, log_x, name if title is None else title, ref, + clip or -1, show_function, th), reference, threads) + return Svg(svg, summary) + + +def heatmap(f, x_range, y_range, *, width=800, height=500, log_x=False, log_y=False, title=None, x_label="x", + y_label="y", log_scale=False, clip=None, reference=None, show_function=False, threads=0): + """The ulps heatmap of f(x, y) over x_range by y_range: (ulps, ulps/envelope), two Svgs. reference= as for plot.""" + name = _name(f) + ulps, envelope, summary = _run( + lambda ref, th: _ext._ulps_heatmap(name, *x_range, *y_range, width, height, log_x, log_y, + name if title is None else title, x_label, y_label, log_scale, clip or -1, + ref, show_function, th), reference, threads) + return Svg(ulps, summary), Svg(envelope, summary) + + +def _chrome(): + candidates = [os.environ.get("CHROME"), "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"] + candidates += [shutil.which(c) for c in ("google-chrome", "google-chrome-stable", "chromium", "chromium-browser")] + return next((c for c in candidates if c and os.path.isfile(c)), None) + + +def render_to_png(svg, path, *, width=None, height=None): + """Renders an Svg (or SVG text) to a PNG with headless Chrome, or cairosvg. Returns path.""" + text = str(svg) + size = lambda attr: int(float(re.search(r"]*?\b" + attr + r"=['\"]([0-9.]+)", text).group(1))) + width = width or size("width") + height = height or size("height") + path = os.path.abspath(path) + chrome = _chrome() + if chrome: + with tempfile.TemporaryDirectory() as tmp: + src = os.path.join(tmp, "plot.svg") + with open(src, "w", encoding="utf-8") as f: + f.write(text) + subprocess.run([chrome, "--headless", "--disable-gpu", "--hide-scrollbars", f"--screenshot={path}", + f"--window-size={width},{height}", "file://" + src], + check=True, capture_output=True, timeout=120) + return path + try: + import cairosvg + except ImportError: + raise RuntimeError("render_to_png needs Google Chrome (or set $CHROME) or `pip install cairosvg`") from None + cairosvg.svg2png(bytestring=text.encode(), write_to=path, output_width=width, output_height=height) + return path diff --git a/nanobind/src/bessel.cpp b/nanobind/src/bessel.cpp new file mode 100644 index 0000000000..51728ab59c --- /dev/null +++ b/nanobind/src/bessel.cpp @@ -0,0 +1,41 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +#include "bindings.hpp" +#include "macros.hpp" + +void bmpy::bind_bessel(nb::module_& m) { + BMPY_R2(cyl_bessel_j, "v", "x"); + BMPY_R2(cyl_neumann, "v", "x"); + BMPY_R2(cyl_bessel_i, "v", "x"); + BMPY_R2(cyl_bessel_k, "v", "x"); + BMPY_R2(cyl_bessel_j_prime, "v", "x"); + BMPY_R2(cyl_neumann_prime, "v", "x"); + BMPY_R2(cyl_bessel_i_prime, "v", "x"); + BMPY_R2(cyl_bessel_k_prime, "v", "x"); + BMPY_I1R1(sph_bessel, unsigned, "n", "x"); + BMPY_I1R1(sph_neumann, unsigned, "n", "x"); + BMPY_I1R1(sph_bessel_prime, unsigned, "n", "x"); + BMPY_I1R1(sph_neumann_prime, unsigned, "n", "x"); + BMPY_R1I1(cyl_bessel_j_zero, int, "v", "m"); + BMPY_R1I1(cyl_neumann_zero, int, "v", "m"); + + // Complex results. + BMPY_R2(cyl_hankel_1, "v", "x"); + BMPY_R2(cyl_hankel_2, "v", "x"); + BMPY_R2(sph_hankel_1, "v", "x"); + BMPY_R2(sph_hankel_2, "v", "x"); + + BMPY_R1(airy_ai, "x"); + BMPY_R1(airy_bi, "x"); + BMPY_R1(airy_ai_prime, "x"); + BMPY_R1(airy_bi_prime, "x"); + BMPY_T_I1(airy_ai_zero, int, "m"); + BMPY_T_I1(airy_bi_zero, int, "m"); +} diff --git a/nanobind/src/beta.cpp b/nanobind/src/beta.cpp new file mode 100644 index 0000000000..55386e92e6 --- /dev/null +++ b/nanobind/src/beta.cpp @@ -0,0 +1,26 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#include "bindings.hpp" +#include "macros.hpp" + +void bmpy::bind_beta(nb::module_& m) { + BMPY_R2(beta, "a", "b"); + BMPY_R3(beta, "a", "b", "x"); // non-normalised incomplete + BMPY_R3(betac, "a", "b", "x"); + BMPY_R2(lbeta, "a", "b"); + BMPY_R3(ibeta, "a", "b", "x"); + BMPY_R3(ibetac, "a", "b", "x"); + BMPY_R3(libeta, "a", "b", "x"); + BMPY_R3(libetac, "a", "b", "x"); + BMPY_R3(ibeta_inv, "a", "b", "p"); + BMPY_R3(ibetac_inv, "a", "b", "q"); + BMPY_R3(ibeta_inva, "b", "x", "p"); + BMPY_R3(ibeta_invb, "a", "x", "p"); + BMPY_R3(ibetac_inva, "b", "x", "q"); + BMPY_R3(ibetac_invb, "a", "x", "q"); + BMPY_R3(ibeta_derivative, "a", "b", "x"); +} diff --git a/nanobind/src/bindings.hpp b/nanobind/src/bindings.hpp new file mode 100644 index 0000000000..b57873f331 --- /dev/null +++ b/nanobind/src/bindings.hpp @@ -0,0 +1,34 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_MATH_NANOBIND_BINDINGS_HPP +#define BOOST_MATH_NANOBIND_BINDINGS_HPP + +#include "vectorize.hpp" + +namespace bmpy { + +void bind_gamma(nb::module_& m); +void bind_beta(nb::module_& m); +void bind_erf_expint_zeta(nb::module_& m); +void bind_elementary(nb::module_& m); +void bind_bessel(nb::module_& m); +void bind_elliptic(nb::module_& m); +void bind_jacobi_theta(nb::module_& m); +void bind_polynomials(nb::module_& m); +void bind_hypergeometric(nb::module_& m); +void bind_distributions_continuous(nb::module_& m); +void bind_distributions_heavy(nb::module_& m); +void bind_distributions_discrete(nb::module_& m); +void bind_distributions_noncentral(nb::module_& m); +void bind_fft(nb::module_& m); +void bind_quadrature(nb::module_& m); +void bind_optimization(nb::module_& m); +void bind_polynomial_roots(nb::module_& m); +// Only with Boost.Multiprecision and zlib; see CMakeLists.txt. +void bind_ulps(nb::module_& m); + +} // namespace bmpy + +#endif diff --git a/nanobind/src/distributions.hpp b/nanobind/src/distributions.hpp new file mode 100644 index 0000000000..44852970c1 --- /dev/null +++ b/nanobind/src/distributions.hpp @@ -0,0 +1,107 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Binds a Boost.Math distribution (double, default policy) as a Python class +// with vectorised pdf/cdf/quantile-style methods and scalar moment methods. + +#ifndef BOOST_MATH_NANOBIND_DISTRIBUTIONS_HPP +#define BOOST_MATH_NANOBIND_DISTRIBUTIONS_HPP + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "vectorize.hpp" + +namespace bmpy { + +// The default policy, except that moments the distribution lacks (the mean of a +// Cauchy, ...) raise ValueError at run time instead of failing to compile. +using dist_policy = boost::math::policies::policy>; + +template +void def_dist_vec(nb::class_& cls, const char* name, const char* argname, G g) { + cls.def(name, [g](const D& d, double x) { return g(d, x); }, nb::arg(argname)); + cls.def( + name, + [g, name, argname](const D& d, nb::object x) { + auto f = [&d, &g](double v) { return g(d, v); }; + return call_array(name, f, {x}, {argname}); + }, + nb::arg(argname)); +} + +template +nb::class_& add_dist_methods(nb::class_& cls) { + namespace bm = boost::math; + def_dist_vec(cls, "pdf", "x", [](const D& d, double x) { return bm::pdf(d, x); }); + def_dist_vec(cls, "logpdf", "x", [](const D& d, double x) { return bm::logpdf(d, x); }); + def_dist_vec(cls, "cdf", "x", [](const D& d, double x) { return bm::cdf(d, x); }); + def_dist_vec(cls, "logcdf", "x", [](const D& d, double x) { return bm::logcdf(d, x); }); + def_dist_vec(cls, "cdf_complement", "x", [](const D& d, double x) { return bm::cdf(bm::complement(d, x)); }); + def_dist_vec(cls, "logcdf_complement", "x", [](const D& d, double x) { return bm::logcdf(bm::complement(d, x)); }); + def_dist_vec(cls, "quantile", "p", [](const D& d, double p) { return bm::quantile(d, p); }); + def_dist_vec(cls, "quantile_complement", "q", [](const D& d, double q) { return bm::quantile(bm::complement(d, q)); }); + def_dist_vec(cls, "hazard", "x", [](const D& d, double x) { return bm::hazard(d, x); }); + def_dist_vec(cls, "chf", "x", [](const D& d, double x) { return bm::chf(d, x); }); + + // Unqualified calls (found by ADL) so that accessors only some distributions + // declare, such as entropy, need no declaration here. +#define BMPY_DIST_ACCESSOR(fn) \ + if constexpr (requires(const D& d) { fn(d); }) \ + cls.def(#fn, [](const D& d) { return fn(d); }); + BMPY_DIST_ACCESSOR(mean) + BMPY_DIST_ACCESSOR(variance) + BMPY_DIST_ACCESSOR(standard_deviation) + BMPY_DIST_ACCESSOR(skewness) + BMPY_DIST_ACCESSOR(kurtosis) + BMPY_DIST_ACCESSOR(kurtosis_excess) + BMPY_DIST_ACCESSOR(mode) + BMPY_DIST_ACCESSOR(median) + BMPY_DIST_ACCESSOR(entropy) + BMPY_DIST_ACCESSOR(support) + BMPY_DIST_ACCESSOR(range) +#undef BMPY_DIST_ACCESSOR + return cls; +} + +// A parameter: the constructor's argument name, and its value read back from the distribution. +template +using dist_param = std::pair; + +#define BMPY_PARAM(name, accessor) \ + bmpy::dist_param{name, +[](const D& d) { return nb::cast(d.accessor()); }} + +// Exposes the parameters as read-only properties, under the constructor's argument names, and a repr that +// constructs the same distribution: normal_distribution(mean=0.0, sd=1.0). A parameter named like a method +// (the mean of a normal, the mode of a triangular) stays the method, which returns the same value. +template +nb::class_& add_dist_params(nb::class_& cls, std::initializer_list> params) { + std::vector> ps(params); + for (auto const& [name, get] : ps) { + if (!nb::hasattr(cls, name)) { + cls.def_prop_ro(name, get); + } + } + std::string type = nb::cast(cls.attr("__name__")); + cls.def("__repr__", [type, ps](const D& d) { + std::string s = type + "("; + for (std::size_t i = 0; i < ps.size(); ++i) { + s += (i ? ", " : "") + std::string(ps[i].first) + "=" + nb::cast(nb::repr(ps[i].second(d))); + } + return s + ")"; + }); + return cls; +} + +} // namespace bmpy + +#endif diff --git a/nanobind/src/distributions_continuous.cpp b/nanobind/src/distributions_continuous.cpp new file mode 100644 index 0000000000..4c9a6c51fb --- /dev/null +++ b/nanobind/src/distributions_continuous.cpp @@ -0,0 +1,201 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bindings.hpp" +#include "distributions.hpp" + +namespace bm = boost::math; +namespace nb = nanobind; +using nb::arg; +using bmpy::add_dist_methods; +using pol = bmpy::dist_policy; + +void bmpy::bind_distributions_continuous(nb::module_& m) { + { + using D = bm::arcsine_distribution; + nb::class_ c(m, "arcsine_distribution"); + c.def(nb::init(), arg("x_min") = 0.0, arg("x_max") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("x_min", x_min), BMPY_PARAM("x_max", x_max)}); + } + { + using D = bm::beta_distribution; + nb::class_ c(m, "beta_distribution"); + c.def(nb::init(), arg("alpha") = 1.0, arg("beta") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("alpha", alpha), BMPY_PARAM("beta", beta)}); + } + { + using D = bm::cauchy_distribution; + nb::class_ c(m, "cauchy_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::chi_squared_distribution; + nb::class_ c(m, "chi_squared_distribution"); + c.def(nb::init(), arg("df") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("df", degrees_of_freedom)}); + } + { + using D = bm::exponential_distribution; + nb::class_ c(m, "exponential_distribution"); + c.def(nb::init(), arg("lambda_") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("lambda_", lambda)}); + } + { + using D = bm::extreme_value_distribution; + nb::class_ c(m, "extreme_value_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::generalized_extreme_value_distribution; + nb::class_ c(m, "generalized_extreme_value_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0, arg("shape") = 0.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale), BMPY_PARAM("shape", shape)}); + } + { + using D = bm::fisher_f_distribution; + nb::class_ c(m, "fisher_f_distribution"); + c.def(nb::init(), arg("df1"), arg("df2")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("df1", degrees_of_freedom1), BMPY_PARAM("df2", degrees_of_freedom2)}); + } + { + using D = bm::gamma_distribution; + nb::class_ c(m, "gamma_distribution"); + c.def(nb::init(), arg("shape"), arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("shape", shape), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::inverse_chi_squared_distribution; + nb::class_ c(m, "inverse_chi_squared_distribution"); + c.def(nb::init(), arg("df") = 1.0); + c.def(nb::init(), arg("df"), arg("scale")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("df", degrees_of_freedom), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::inverse_gamma_distribution; + nb::class_ c(m, "inverse_gamma_distribution"); + c.def(nb::init(), arg("shape") = 1.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("shape", shape), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::inverse_gaussian_distribution; + nb::class_ c(m, "inverse_gaussian_distribution"); + c.def(nb::init(), arg("mean") = 1.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("mean", mean), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::laplace_distribution; + nb::class_ c(m, "laplace_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::logistic_distribution; + nb::class_ c(m, "logistic_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::lognormal_distribution; + nb::class_ c(m, "lognormal_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::normal_distribution; + nb::class_ c(m, "normal_distribution"); + c.def(nb::init(), arg("mean") = 0.0, arg("sd") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("mean", mean), BMPY_PARAM("sd", standard_deviation)}); + } + { + using D = bm::pareto_distribution; + nb::class_ c(m, "pareto_distribution"); + c.def(nb::init(), arg("scale") = 1.0, arg("shape") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("scale", scale), BMPY_PARAM("shape", shape)}); + } + { + using D = bm::rayleigh_distribution; + nb::class_ c(m, "rayleigh_distribution"); + c.def(nb::init(), arg("sigma") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("sigma", sigma)}); + } + { + using D = bm::skew_normal_distribution; + nb::class_ c(m, "skew_normal_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0, arg("shape") = 0.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale), BMPY_PARAM("shape", shape)}); + } + { + using D = bm::students_t_distribution; + nb::class_ c(m, "students_t_distribution"); + c.def(nb::init(), arg("df") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("df", degrees_of_freedom)}); + } + { + using D = bm::triangular_distribution; + nb::class_ c(m, "triangular_distribution"); + c.def(nb::init(), arg("lower") = -1.0, arg("mode") = 0.0, arg("upper") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("lower", lower), BMPY_PARAM("mode", mode), BMPY_PARAM("upper", upper)}); + } + { + using D = bm::uniform_distribution; + nb::class_ c(m, "uniform_distribution"); + c.def(nb::init(), arg("lower") = 0.0, arg("upper") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("lower", lower), BMPY_PARAM("upper", upper)}); + } + { + using D = bm::weibull_distribution; + nb::class_ c(m, "weibull_distribution"); + c.def(nb::init(), arg("shape"), arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("shape", shape), BMPY_PARAM("scale", scale)}); + } +} diff --git a/nanobind/src/distributions_discrete.cpp b/nanobind/src/distributions_discrete.cpp new file mode 100644 index 0000000000..bb8cf5354a --- /dev/null +++ b/nanobind/src/distributions_discrete.cpp @@ -0,0 +1,68 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Discrete distributions use the default discrete_quantile policy. + +#include +#include +#include +#include +#include +#include + +#include + +#include "bindings.hpp" +#include "distributions.hpp" + +namespace bm = boost::math; +namespace nb = nanobind; +using nb::arg; +using bmpy::add_dist_methods; +using pol = bmpy::dist_policy; + +void bmpy::bind_distributions_discrete(nb::module_& m) { + { + using D = bm::bernoulli_distribution; + nb::class_ c(m, "bernoulli_distribution"); + c.def(nb::init(), arg("p") = 0.5); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("p", success_fraction)}); + } + { + using D = bm::binomial_distribution; + nb::class_ c(m, "binomial_distribution"); + c.def(nb::init(), arg("n") = 1.0, arg("p") = 0.5); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("n", trials), BMPY_PARAM("p", success_fraction)}); + } + { + using D = bm::geometric_distribution; + nb::class_ c(m, "geometric_distribution"); + c.def(nb::init(), arg("p")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("p", success_fraction)}); + } + { + using D = bm::hypergeometric_distribution; + nb::class_ c(m, "hypergeometric_distribution"); + c.def(nb::init(), arg("r"), arg("n"), arg("N")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("r", defective), BMPY_PARAM("n", sample_count), BMPY_PARAM("N", total)}); + } + { + using D = bm::negative_binomial_distribution; + nb::class_ c(m, "negative_binomial_distribution"); + c.def(nb::init(), arg("r"), arg("p")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("r", successes), BMPY_PARAM("p", success_fraction)}); + } + { + using D = bm::poisson_distribution; + nb::class_ c(m, "poisson_distribution"); + c.def(nb::init(), arg("mean") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("mean", mean)}); + } +} diff --git a/nanobind/src/distributions_heavy.cpp b/nanobind/src/distributions_heavy.cpp new file mode 100644 index 0000000000..3687b8c569 --- /dev/null +++ b/nanobind/src/distributions_heavy.cpp @@ -0,0 +1,82 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Stable-law and other distributions with large tables or unusual constructors. + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "bindings.hpp" +#include "distributions.hpp" + +namespace bm = boost::math; +namespace nb = nanobind; +using nb::arg; +using bmpy::add_dist_methods; +using pol = bmpy::dist_policy; + +void bmpy::bind_distributions_heavy(nb::module_& m) { + { + using D = bm::holtsmark_distribution; + nb::class_ c(m, "holtsmark_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::landau_distribution; + nb::class_ c(m, "landau_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::mapairy_distribution; + nb::class_ c(m, "mapairy_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::saspoint5_distribution; + nb::class_ c(m, "saspoint5_distribution"); + c.def(nb::init(), arg("location") = 0.0, arg("scale") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("location", location), BMPY_PARAM("scale", scale)}); + } + { + using D = bm::von_mises_distribution; + nb::class_ c(m, "von_mises_distribution"); + c.def(nb::init(), arg("mean") = 0.0, arg("concentration") = 1.0); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("mean", mean), BMPY_PARAM("concentration", concentration)}); + } + { + using D = bm::kolmogorov_smirnov_distribution; + nb::class_ c(m, "kolmogorov_smirnov_distribution"); + c.def(nb::init(), arg("n")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("n", number_of_observations)}); + } + { + using D = bm::hyperexponential_distribution; + nb::class_ c(m, "hyperexponential_distribution"); + c.def(nb::init&>(), arg("rates")); + c.def( + "__init__", + [](D* self, const std::vector& probs, const std::vector& rates) { new (self) D(probs, rates); }, + arg("probabilities"), arg("rates")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("probabilities", probabilities), BMPY_PARAM("rates", rates)}); + } +} diff --git a/nanobind/src/distributions_noncentral.cpp b/nanobind/src/distributions_noncentral.cpp new file mode 100644 index 0000000000..1aa2d335d4 --- /dev/null +++ b/nanobind/src/distributions_noncentral.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +#include "bindings.hpp" +#include "distributions.hpp" + +namespace bm = boost::math; +namespace nb = nanobind; +using nb::arg; +using bmpy::add_dist_methods; +using pol = bmpy::dist_policy; + +void bmpy::bind_distributions_noncentral(nb::module_& m) { + { + using D = bm::non_central_beta_distribution; + nb::class_ c(m, "non_central_beta_distribution"); + c.def(nb::init(), arg("alpha"), arg("beta"), arg("lambda_")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("alpha", alpha), BMPY_PARAM("beta", beta), BMPY_PARAM("lambda_", non_centrality)}); + } + { + using D = bm::non_central_chi_squared_distribution; + nb::class_ c(m, "non_central_chi_squared_distribution"); + c.def(nb::init(), arg("df"), arg("lambda_")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("df", degrees_of_freedom), BMPY_PARAM("lambda_", non_centrality)}); + } + { + using D = bm::non_central_f_distribution; + nb::class_ c(m, "non_central_f_distribution"); + c.def(nb::init(), arg("df1"), arg("df2"), arg("lambda_")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("df1", degrees_of_freedom1), BMPY_PARAM("df2", degrees_of_freedom2), BMPY_PARAM("lambda_", non_centrality)}); + } + { + using D = bm::non_central_t_distribution; + nb::class_ c(m, "non_central_t_distribution"); + c.def(nb::init(), arg("df"), arg("delta")); + add_dist_methods(c); + bmpy::add_dist_params(c, {BMPY_PARAM("df", degrees_of_freedom), BMPY_PARAM("delta", non_centrality)}); + } +} diff --git a/nanobind/src/elementary.cpp b/nanobind/src/elementary.cpp new file mode 100644 index 0000000000..a214dc962d --- /dev/null +++ b/nanobind/src/elementary.cpp @@ -0,0 +1,103 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bindings.hpp" +#include "macros.hpp" + +void bmpy::bind_elementary(nb::module_& m) { + BMPY_R1(log1p, "x"); + BMPY_R1(log1pmx, "x"); + BMPY_R1(expm1, "x"); + BMPY_R1(cbrt, "x"); + BMPY_R1(sqrt1pm1, "x"); + BMPY_R2(powm1, "x", "y"); + BMPY_R2(pow1p, "x", "y"); + BMPY_R1(sin_pi, "x"); + BMPY_R1(cos_pi, "x"); + BMPY_R1(sinc_pi, "x"); + BMPY_R1(sinhc_pi, "x"); + BMPY_R1(asinh, "x"); + BMPY_R1(acosh, "x"); + BMPY_R1(atanh, "x"); + BMPY_R2(hypot, "x", "y"); + BMPY_R1(rsqrt, "x"); + BMPY_R1(logit, "p"); + BMPY_R1(logistic_sigmoid, "x"); + BMPY_R2(logaddexp, "x", "y"); + + // Floating-point navigation; float32 inputs work in float. + BMPY_R1(float_next, "x"); + BMPY_R1(float_prior, "x"); + BMPY_R2(float_distance, "a", "b"); + BMPY_R1I1(float_advance, int, "x", "n"); + BMPY_R2(nextafter, "x", "y"); + BMPY_R1(ulp, "x"); + BMPY_R2(relative_difference, "a", "b"); + BMPY_R2(epsilon_difference, "a", "b"); + + bmpy::def_vec>( + m, "fibonacci", [](unsigned long long n) { return bm::fibonacci(n); }, {"n"}, + "boost::math::fibonacci"); + bmpy::def_vec>( + m, "prime", [](unsigned n) { return static_cast(bm::prime(n)); }, {"n"}, "boost::math::prime"); + + // The segmented sieve; results are uint64 arrays. prime_count needs an execution policy, and + // libc++ may have no ; without nvcc the cuda policy runs on the CPU. + auto to_array = [](std::vector&& primes) { + auto* data = new std::vector(std::move(primes)); + nb::capsule owner(data, [](void* p) noexcept { delete static_cast*>(p); }); + return nb::ndarray>(data->data(), {data->size()}, owner); + }; + m.def("prime_sieve", [to_array](std::uint64_t upper) { + std::vector primes; + { + nb::gil_scoped_release release; + bm::prime_sieve(upper, primes); + } + return to_array(std::move(primes)); + }, nb::arg("upper"), "boost::math::prime_sieve: the primes in [2, upper)"); + m.def("prime_range", [to_array](std::uint64_t lower, std::uint64_t upper) { + std::vector primes; + { + nb::gil_scoped_release release; + bm::prime_range(lower, upper, primes); + } + return to_array(std::move(primes)); + }, nb::arg("lower"), nb::arg("upper"), "boost::math::prime_range: the primes in [lower, upper)"); + m.def("prime_count", [](std::uint64_t upper) { + nb::gil_scoped_release release; + return bm::prime_count(bm::execution::cuda, upper); + }, nb::arg("upper"), "boost::math::prime_count: the number of primes in [2, upper)"); + m.def("prime_count", [](std::uint64_t lower, std::uint64_t upper) { + nb::gil_scoped_release release; + return bm::prime_count(bm::execution::cuda, lower, upper); + }, nb::arg("lower"), nb::arg("upper"), "boost::math::prime_count: the number of primes in [lower, upper)"); +} diff --git a/nanobind/src/elliptic.cpp b/nanobind/src/elliptic.cpp new file mode 100644 index 0000000000..c4c2eb8557 --- /dev/null +++ b/nanobind/src/elliptic.cpp @@ -0,0 +1,50 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bindings.hpp" +#include "macros.hpp" + +void bmpy::bind_elliptic(nb::module_& m) { + BMPY_R1(ellint_1, "k"); + BMPY_R2(ellint_1, "k", "phi"); + BMPY_R1(ellint_2, "k"); + BMPY_R2(ellint_2, "k", "phi"); + BMPY_R2(ellint_3, "k", "n"); + BMPY_R3(ellint_3, "k", "n", "phi"); + BMPY_R1(ellint_d, "k"); + BMPY_R2(ellint_d, "k", "phi"); + BMPY_R2(ellint_rc, "x", "y"); + BMPY_R3(ellint_rd, "x", "y", "z"); + BMPY_R3(ellint_rf, "x", "y", "z"); + BMPY_R3(ellint_rg, "x", "y", "z"); + BMPY_R4(ellint_rj, "x", "y", "z", "p"); + BMPY_R2(jacobi_zeta, "k", "phi"); + BMPY_R2(heuman_lambda, "k", "phi"); + + BMPY_R2(jacobi_sn, "k", "u"); + BMPY_R2(jacobi_cn, "k", "u"); + BMPY_R2(jacobi_dn, "k", "u"); + BMPY_R2(jacobi_cd, "k", "u"); + BMPY_R2(jacobi_dc, "k", "u"); + BMPY_R2(jacobi_ns, "k", "u"); + BMPY_R2(jacobi_sd, "k", "u"); + BMPY_R2(jacobi_ds, "k", "u"); + BMPY_R2(jacobi_nc, "k", "u"); + BMPY_R2(jacobi_nd, "k", "u"); + BMPY_R2(jacobi_sc, "k", "u"); + BMPY_R2(jacobi_cs, "k", "u"); +} diff --git a/nanobind/src/erf_expint_zeta.cpp b/nanobind/src/erf_expint_zeta.cpp new file mode 100644 index 0000000000..878922ce97 --- /dev/null +++ b/nanobind/src/erf_expint_zeta.cpp @@ -0,0 +1,27 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +#include "bindings.hpp" +#include "macros.hpp" + +void bmpy::bind_erf_expint_zeta(nb::module_& m) { + BMPY_R1(erf, "z"); + BMPY_R1(erfc, "z"); + BMPY_R1(erf_inv, "p"); + BMPY_R1(erfc_inv, "q"); + BMPY_R1(expint, "z"); // Ei + BMPY_I1R1(expint, unsigned, "n", "z"); // E_n + BMPY_R1(zeta, "s"); + BMPY_R2(owens_t, "h", "a"); + BMPY_R1(lambert_w0, "z"); + BMPY_R1(lambert_wm1, "z"); + BMPY_R1(lambert_w0_prime, "z"); + BMPY_R1(lambert_wm1_prime, "z"); +} diff --git a/nanobind/src/fft.cpp b/nanobind/src/fft.cpp new file mode 100644 index 0000000000..c1e5768e7c --- /dev/null +++ b/nanobind/src/fft.cpp @@ -0,0 +1,222 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// tools::fft>, tools::real_fft> and the DCT-II behind +// chebyshev_transform (detail::dct_ii), as classes. Arrays must be 1-D, C-contiguous NumPy arrays of +// exactly the right dtype and length (writable for the in-place methods); anything else raises ValueError. +// Transforms release the GIL. Each object owns its workspace, so a mutex keeps two threads from using one +// object at the same time. + +#include "bindings.hpp" + +#include +#include + +#include +#include +#include +#include + +namespace bmpy { + +namespace { + +using C = std::complex; + +template +using array1d = nb::ndarray, nb::c_contig, nb::device::cpu>; + +template +char const* dtype_name() +{ + return std::is_same_v ? "complex128" : "float64"; +} + +// Checks that a is a 1-D, C-contiguous NumPy array of dtype T and length n (and writable if asked), +// raising ValueError otherwise, and returns a pointer to its data. +template +T* checked_data(nb::handle a, std::size_t n, bool writable, char const* what) +{ + nb::module_ np = nb::module_::import_("numpy"); + std::string prefix = std::string(what) + ": "; + if (!nb::isinstance(a, np.attr("ndarray"))) + { + throw nb::value_error((prefix + "expected a NumPy array").c_str()); + } + if (!a.attr("dtype").equal(np.attr("dtype")(dtype_name()))) + { + throw nb::value_error((prefix + "expected dtype " + dtype_name() + ", got " + + nb::cast(a.attr("dtype").attr("name"))).c_str()); + } + if (nb::cast(a.attr("ndim")) != 1) + { + throw nb::value_error((prefix + "expected a 1-D array").c_str()); + } + nb::handle flags = a.attr("flags"); + if (!nb::cast(flags.attr("c_contiguous"))) + { + throw nb::value_error((prefix + "expected a contiguous array").c_str()); + } + if (writable && !nb::cast(flags.attr("writeable"))) + { + throw nb::value_error((prefix + "expected a writable array").c_str()); + } + std::size_t len = nb::cast(a.attr("shape")[0]); + if (len != n) + { + throw nb::value_error((prefix + "expected length " + std::to_string(n) + ", got " + std::to_string(len)).c_str()); + } + if (writable) + { + return nb::cast>(a).data(); + } + return const_cast(nb::cast, nb::c_contig, nb::device::cpu>>(a).data()); +} + +template +array1d new_array(std::size_t n, T** data) +{ + T* buf = new T[n == 0 ? 1 : n]; + nb::capsule owner(buf, [](void* p) noexcept { delete[] static_cast(p); }); + *data = buf; + std::size_t shape[1] = {n}; + return array1d(buf, 1, shape, owner); +} + +struct py_fft +{ + explicit py_fft(std::size_t n) : f(n) {} + boost::math::tools::fft f; + std::mutex mutex; + + array1d out_of_place(nb::handle x, bool inverse) + { + std::size_t n = f.size(); + C const* in = checked_data(x, n, false, inverse ? "inverse_transform" : "transform"); + C* out; + array1d result = new_array(n, &out); + { + nb::gil_scoped_release release; + std::lock_guard lock(mutex); + std::span s_in(in, n); + std::span s_out(out, n); + if (inverse) + f.inverse_transform(s_in, s_out); + else + f.transform(s_in, s_out); + } + return result; + } + + void in_place(nb::handle x, bool inverse) + { + std::size_t n = f.size(); + C* v = checked_data(x, n, true, inverse ? "inverse_transform_in_place" : "transform_in_place"); + nb::gil_scoped_release release; + std::lock_guard lock(mutex); + std::span s(v, n); + if (inverse) + f.inverse_transform(s); + else + f.transform(s); + } +}; + +struct py_real_fft +{ + explicit py_real_fft(std::size_t n) : f(n), n(n) {} + boost::math::tools::real_fft f; + std::size_t n; + std::mutex mutex; + + array1d transform(nb::handle x) + { + double const* in = checked_data(x, n, false, "transform"); + C* out; + array1d result = new_array(n / 2 + 1, &out); + { + nb::gil_scoped_release release; + std::lock_guard lock(mutex); + std::span s_in(in, n); + std::span s_out(out, n / 2 + 1); + f.transform(s_in, s_out); + } + return result; + } +}; + +struct py_dct_ii +{ + explicit py_dct_ii(std::size_t n) : d(n), n(n) {} + boost::math::detail::dct_ii d; + std::size_t n; + std::mutex mutex; + + array1d transform(nb::handle x) + { + double const* in = checked_data(x, n, false, "transform"); + double* out; + array1d result = new_array(n, &out); + { + nb::gil_scoped_release release; + std::lock_guard lock(mutex); + d.execute(in, out); + } + return result; + } + + void transform_in_place(nb::handle x) + { + double* v = checked_data(x, n, true, "transform_in_place"); + nb::gil_scoped_release release; + std::lock_guard lock(mutex); + d.execute(v); + } +}; + +void check_length(std::size_t n) +{ + if (n == 0) + { + throw nb::value_error("The length of the transform must be positive."); + } +} + +} // namespace + +void bind_fft(nb::module_& m) +{ + nb::class_(m, "fft", + "Discrete Fourier transform of length n, X[k] = sum_j x[j] exp(-2 pi i j k/n), on complex128 arrays; " + "the inverse divides by n.") + .def("__init__", [](py_fft* self, std::size_t n) { check_length(n); new (self) py_fft(n); }, nb::arg("n")) + .def_prop_ro("size", [](py_fft& self) { return self.f.size(); }) + .def("__len__", [](py_fft& self) { return self.f.size(); }) + .def("transform", [](py_fft& self, nb::handle x) { return self.out_of_place(x, false); }, nb::arg("x"), + "Returns the transform of x as a new array.") + .def("inverse_transform", [](py_fft& self, nb::handle x) { return self.out_of_place(x, true); }, nb::arg("x"), + "Returns the inverse transform of x as a new array.") + .def("transform_in_place", [](py_fft& self, nb::handle x) { self.in_place(x, false); }, nb::arg("x"), + "Replaces x (writable, contiguous) with its transform.") + .def("inverse_transform_in_place", [](py_fft& self, nb::handle x) { self.in_place(x, true); }, nb::arg("x"), + "Replaces x (writable, contiguous) with its inverse transform."); + + nb::class_(m, "real_fft", + "Transform of n float64 samples: returns X[0], ..., X[n/2] (complex128); the rest are conj(X[n-k]).") + .def("__init__", [](py_real_fft* self, std::size_t n) { check_length(n); new (self) py_real_fft(n); }, nb::arg("n")) + .def_prop_ro("size", [](py_real_fft& self) { return self.n; }) + .def("__len__", [](py_real_fft& self) { return self.n; }) + .def("transform", &py_real_fft::transform, nb::arg("x")); + + nb::class_(m, "dct_ii", + "DCT-II with FFTW's REDFT10 normalisation, y[k] = 2 sum_j x[j] cos(pi k (2j+1)/(2n)), on float64 arrays " + "(the transform behind chebyshev_transform).") + .def("__init__", [](py_dct_ii* self, std::size_t n) { check_length(n); new (self) py_dct_ii(n); }, nb::arg("n")) + .def_prop_ro("size", [](py_dct_ii& self) { return self.n; }) + .def("__len__", [](py_dct_ii& self) { return self.n; }) + .def("transform", &py_dct_ii::transform, nb::arg("x")) + .def("transform_in_place", &py_dct_ii::transform_in_place, nb::arg("x")); +} + +} // namespace bmpy diff --git a/nanobind/src/gamma.cpp b/nanobind/src/gamma.cpp new file mode 100644 index 0000000000..62e3bb407a --- /dev/null +++ b/nanobind/src/gamma.cpp @@ -0,0 +1,49 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include + +#include "bindings.hpp" +#include "macros.hpp" + +void bmpy::bind_gamma(nb::module_& m) { + BMPY_R1(tgamma, "z"); + BMPY_R2(tgamma, "a", "z"); // upper incomplete + BMPY_R1(tgamma1pm1, "z"); + BMPY_R1(lgamma, "z"); + BMPY_R1(digamma, "z"); + BMPY_R1(trigamma, "z"); + BMPY_I1R1(polygamma, int, "n", "z"); + BMPY_R2(tgamma_ratio, "a", "b"); + BMPY_R2(tgamma_delta_ratio, "a", "delta"); + BMPY_R2(tgamma_lower, "a", "z"); + BMPY_R2(gamma_p, "a", "z"); + BMPY_R2(gamma_q, "a", "z"); + BMPY_R2(gamma_p_inv, "a", "p"); + BMPY_R2(gamma_q_inv, "a", "q"); + BMPY_R2(gamma_p_inva, "z", "p"); + BMPY_R2(gamma_q_inva, "z", "q"); + BMPY_R2(gamma_p_derivative, "a", "z"); + BMPY_R2(lgamma_p, "a", "z"); + BMPY_R2(lgamma_q, "a", "z"); + BMPY_R2(ligamma, "a", "z"); + BMPY_R2(ligamma_lower, "a", "z"); + + BMPY_T_I1(factorial, unsigned, "n"); + BMPY_T_I1(unchecked_factorial, unsigned, "n"); + BMPY_T_I1(double_factorial, unsigned, "n"); + BMPY_R1I1(rising_factorial, int, "x", "n"); + BMPY_R1I1(falling_factorial, unsigned, "x", "n"); + bmpy::def_vec, bmpy::Int>( + m, "binomial_coefficient", [](unsigned n, unsigned k) { return bm::binomial_coefficient(n, k); }, + {"n", "k"}, "boost::math::binomial_coefficient"); + BMPY_T_I1(bernoulli_b2n, int, "n"); + BMPY_T_I1(tangent_t2n, int, "n"); +} diff --git a/nanobind/src/hypergeometric.cpp b/nanobind/src/hypergeometric.cpp new file mode 100644 index 0000000000..e3b04d2298 --- /dev/null +++ b/nanobind/src/hypergeometric.cpp @@ -0,0 +1,34 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +#include + +#include "bindings.hpp" +#include "macros.hpp" + +void bmpy::bind_hypergeometric(nb::module_& m) { + BMPY_R2(hypergeometric_1F0, "a", "z"); + BMPY_R2(hypergeometric_0F1, "b", "z"); + BMPY_R3(hypergeometric_2F0, "a1", "a2", "z"); + BMPY_R3(hypergeometric_1F1, "a", "b", "z"); + BMPY_R3(hypergeometric_1F1_regularized, "a", "b", "z"); + BMPY_R3(log_hypergeometric_1F1, "a", "b", "z"); + + // pFq: the parameter lists are fixed per call, z is vectorised; double only. + m.def( + "hypergeometric_pFq", + [](std::vector a, std::vector b, nb::object z) { + auto f = [a = std::move(a), b = std::move(b)](double x) { + return bm::hypergeometric_pFq(a, b, x); + }; + return bmpy::call_array("hypergeometric_pFq", f, {z}, {"z"}); + }, + nb::arg("a"), nb::arg("b"), nb::arg("z"), "boost::math::hypergeometric_pFq(a, b, z); vectorised over z, double only"); +} diff --git a/nanobind/src/jacobi_theta.cpp b/nanobind/src/jacobi_theta.cpp new file mode 100644 index 0000000000..cdd27c0ca7 --- /dev/null +++ b/nanobind/src/jacobi_theta.cpp @@ -0,0 +1,23 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#include "bindings.hpp" +#include "macros.hpp" + +void bmpy::bind_jacobi_theta(nb::module_& m) { + BMPY_R2(jacobi_theta1, "z", "q"); + BMPY_R2(jacobi_theta2, "z", "q"); + BMPY_R2(jacobi_theta3, "z", "q"); + BMPY_R2(jacobi_theta4, "z", "q"); + BMPY_R2(jacobi_theta3m1, "z", "q"); + BMPY_R2(jacobi_theta4m1, "z", "q"); + BMPY_R2(jacobi_theta1tau, "z", "tau"); + BMPY_R2(jacobi_theta2tau, "z", "tau"); + BMPY_R2(jacobi_theta3tau, "z", "tau"); + BMPY_R2(jacobi_theta4tau, "z", "tau"); + BMPY_R2(jacobi_theta3m1tau, "z", "tau"); + BMPY_R2(jacobi_theta4m1tau, "z", "tau"); +} diff --git a/nanobind/src/macros.hpp b/nanobind/src/macros.hpp new file mode 100644 index 0000000000..aac26f07a3 --- /dev/null +++ b/nanobind/src/macros.hpp @@ -0,0 +1,34 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Shorthands for the common all-real signatures. The function name is the +// Python name and the Boost.Math function called through bm::. + +#ifndef BOOST_MATH_NANOBIND_MACROS_HPP +#define BOOST_MATH_NANOBIND_MACROS_HPP + +#define BMPY_R1(fn, a) \ + bmpy::def_vec(m, #fn, [](T x0) { return bm::fn(x0); }, {a}, "boost::math::" #fn) +#define BMPY_R2(fn, a, b) \ + bmpy::def_vec(m, #fn, [](T x0, T x1) { return bm::fn(x0, x1); }, {a, b}, "boost::math::" #fn) +#define BMPY_R3(fn, a, b, c) \ + bmpy::def_vec(m, #fn, [](T x0, T x1, T x2) { return bm::fn(x0, x1, x2); }, \ + {a, b, c}, "boost::math::" #fn) +#define BMPY_R4(fn, a, b, c, d) \ + bmpy::def_vec( \ + m, #fn, [](T x0, T x1, T x2, T x3) { return bm::fn(x0, x1, x2, x3); }, {a, b, c, d}, \ + "boost::math::" #fn) +// One integer argument of type I followed by one real argument. +#define BMPY_I1R1(fn, I, a, b) \ + bmpy::def_vec, bmpy::Real>(m, #fn, [](I n, T x) { return bm::fn(n, x); }, {a, b}, "boost::math::" #fn) +// One real argument followed by one integer argument of type I. +#define BMPY_R1I1(fn, I, a, b) \ + bmpy::def_vec>(m, #fn, [](T x, I n) { return bm::fn(x, n); }, {a, b}, "boost::math::" #fn) +// Functions of one integer whose result type is the template argument (factorial(n), ...); double only. +#define BMPY_T_I1(fn, I, a) \ + bmpy::def_vec>(m, #fn, [](I n) { return bm::fn(n); }, {a}, "boost::math::" #fn "") + +namespace bm = boost::math; + +#endif diff --git a/nanobind/src/module.cpp b/nanobind/src/module.cpp new file mode 100644 index 0000000000..75b8d10ab2 --- /dev/null +++ b/nanobind/src/module.cpp @@ -0,0 +1,29 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include "bindings.hpp" + +NB_MODULE(_ext, m) { + m.doc() = "Development-only nanobind bindings for Boost.Math, using the default policy."; + bmpy::bind_gamma(m); + bmpy::bind_beta(m); + bmpy::bind_erf_expint_zeta(m); + bmpy::bind_elementary(m); + bmpy::bind_bessel(m); + bmpy::bind_elliptic(m); + bmpy::bind_jacobi_theta(m); + bmpy::bind_polynomials(m); + bmpy::bind_hypergeometric(m); + bmpy::bind_distributions_continuous(m); + bmpy::bind_distributions_heavy(m); + bmpy::bind_distributions_discrete(m); + bmpy::bind_distributions_noncentral(m); + bmpy::bind_fft(m); + bmpy::bind_quadrature(m); + bmpy::bind_optimization(m); + bmpy::bind_polynomial_roots(m); +#ifdef BMPY_HAVE_ULPS + bmpy::bind_ulps(m); +#endif +} diff --git a/nanobind/src/optimization.cpp b/nanobind/src/optimization.cpp new file mode 100644 index 0000000000..f6014c1b62 --- /dev/null +++ b/nanobind/src/optimization.cpp @@ -0,0 +1,194 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// The derivative-free optimizers (differential_evolution, jso, random_search, and cma_es where Eigen is found) on +// std::vector, +// minimizing a Python callable f(x) -> float over the box [lower_bounds, upper_bounds]. Each returns the +// best argument found. The C++ calls f from its own worker threads, so the GIL is released for the run and +// taken for each call; an exception raised by f cancels the run and is re-raised when it returns. +// The gradient-based optimizers are left out: their objectives are written over reverse-mode autodiff +// variables, which a Python callable can't provide. + +#include "bindings.hpp" + +#include +#include +#include +#if __has_include() +#include +#define BOOST_MATH_NB_HAS_CMA_ES +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace bmpy { + +namespace { + +namespace bo = boost::math::optimization; +using vector = std::vector; + +// The cost function the optimizers call, from any of their threads. +class python_cost +{ +public: + explicit python_cost(nb::callable f) : f_(std::move(f)) {} + + double operator()(vector const& x) const + { + if (cancel_.load()) + { + return std::numeric_limits::infinity(); + } + nb::gil_scoped_acquire acquire; + try + { + return nb::cast(f_(x)); + } + catch (nb::python_error& e) + { + // The error indicator is per thread, so keep the exception itself to raise on the caller's thread. + std::lock_guard lock(mutex_); + if (!error_) + { + error_.emplace(e); + } + cancel_.store(true); + return std::numeric_limits::infinity(); + } + } + + std::atomic* cancellation() const { return &cancel_; } + + // Raises the first exception f raised, if any. Call with the GIL held. + void rethrow() const + { + if (error_) + { + throw nb::python_error(*error_); + } + } + +private: + nb::callable f_; + mutable std::atomic cancel_{false}; + mutable std::mutex mutex_; + mutable std::optional error_; +}; + +void check_bounds(vector const& lower, vector const& upper, char const* name) +{ + if (lower.size() != upper.size() || lower.empty()) + { + throw nb::value_error((std::string(name) + ": lower_bounds and upper_bounds must be non-empty and the same length").c_str()); + } +} + +// Runs the optimizer with the GIL released, then re-raises the first exception from the cost function. +template +vector run_released(python_cost const& cost, Run run) +{ + vector x; + { + nb::gil_scoped_release release; + x = run(); + } + cost.rethrow(); + return x; +} + +} // namespace + +void bind_optimization(nb::module_& m) +{ + using nb::arg; + const double no_target = std::numeric_limits::quiet_NaN(); + + m.def("differential_evolution", [](nb::callable f, vector lower_bounds, vector upper_bounds, std::optional initial_guess, + std::size_t population, std::size_t max_generations, double mutation_factor, + double crossover_probability, unsigned threads, double target_value, std::uint64_t seed) { + check_bounds(lower_bounds, upper_bounds, "differential_evolution"); + bo::differential_evolution_parameters params; + params.lower_bounds = std::move(lower_bounds); + params.upper_bounds = std::move(upper_bounds); + params.initial_guess = initial_guess ? &*initial_guess : nullptr; + params.NP = population; + params.max_generations = max_generations; + params.mutation_factor = mutation_factor; + params.crossover_probability = crossover_probability; + params.threads = threads; + python_cost cost(f); + std::mt19937_64 gen(seed); + return run_released(cost, [&] { return bo::differential_evolution(std::cref(cost), params, gen, target_value, cost.cancellation()); }); + }, arg("f"), arg("lower_bounds"), arg("upper_bounds"), arg("initial_guess") = nb::none(), arg("population") = 500, + arg("max_generations") = 1000, arg("mutation_factor") = 0.65, arg("crossover_probability") = 0.5, arg("threads") = 1u, + arg("target_value") = no_target, arg("seed") = 0, + "optimization::differential_evolution: the argument in the box that minimizes f"); + + m.def("jso", [](nb::callable f, vector lower_bounds, vector upper_bounds, std::optional initial_guess, + std::size_t initial_population_size, std::size_t max_function_evaluations, std::size_t threads, + double target_value, std::uint64_t seed) { + check_bounds(lower_bounds, upper_bounds, "jso"); + bo::jso_parameters params; + params.lower_bounds = std::move(lower_bounds); + params.upper_bounds = std::move(upper_bounds); + params.initial_guess = initial_guess ? &*initial_guess : nullptr; + params.initial_population_size = initial_population_size; + params.max_function_evaluations = max_function_evaluations; + params.threads = threads; + python_cost cost(f); + std::mt19937_64 gen(seed); + return run_released(cost, [&] { return bo::jso(std::cref(cost), params, gen, target_value, cost.cancellation()); }); + }, arg("f"), arg("lower_bounds"), arg("upper_bounds"), arg("initial_guess") = nb::none(), arg("initial_population_size") = 0, + arg("max_function_evaluations") = 0, arg("threads") = 1, arg("target_value") = no_target, arg("seed") = 0, + "optimization::jso: the argument in the box that minimizes f (0 means the defaults from the paper)"); + + m.def("random_search", [](nb::callable f, vector lower_bounds, vector upper_bounds, std::optional initial_guess, + std::size_t max_function_calls, unsigned threads, double target_value, std::uint64_t seed) { + check_bounds(lower_bounds, upper_bounds, "random_search"); + bo::random_search_parameters params; + params.lower_bounds = std::move(lower_bounds); + params.upper_bounds = std::move(upper_bounds); + params.initial_guess = initial_guess ? &*initial_guess : nullptr; + params.max_function_calls = max_function_calls; + params.threads = threads; + python_cost cost(f); + std::mt19937_64 gen(seed); + return run_released(cost, [&] { return bo::random_search(std::cref(cost), params, gen, target_value, cost.cancellation()); }); + }, arg("f"), arg("lower_bounds"), arg("upper_bounds"), arg("initial_guess") = nb::none(), arg("max_function_calls") = 10000, + arg("threads") = 1u, arg("target_value") = no_target, arg("seed") = 0, + "optimization::random_search: the best argument found in the box"); + +#ifdef BOOST_MATH_NB_HAS_CMA_ES + m.def("cma_es", [](nb::callable f, vector lower_bounds, vector upper_bounds, std::optional initial_guess, + std::size_t max_generations, std::size_t population_size, double learning_rate, double target_value, + std::uint64_t seed) { + check_bounds(lower_bounds, upper_bounds, "cma_es"); + bo::cma_es_parameters params; + params.lower_bounds = std::move(lower_bounds); + params.upper_bounds = std::move(upper_bounds); + params.initial_guess = initial_guess ? &*initial_guess : nullptr; + params.max_generations = max_generations; + params.population_size = population_size; + params.learning_rate = learning_rate; + python_cost cost(f); + std::mt19937_64 gen(seed); + return run_released(cost, [&] { return bo::cma_es(std::cref(cost), params, gen, target_value, cost.cancellation()); }); + }, arg("f"), arg("lower_bounds"), arg("upper_bounds"), arg("initial_guess") = nb::none(), arg("max_generations") = 1000, + arg("population_size") = 0, arg("learning_rate") = 1.0, arg("target_value") = no_target, arg("seed") = 0, + "optimization::cma_es: the argument in the box that minimizes f"); +#endif +} + +} // namespace bmpy diff --git a/nanobind/src/polynomial_roots.cpp b/nanobind/src/polynomial_roots.cpp new file mode 100644 index 0000000000..fde0d214d2 --- /dev/null +++ b/nanobind/src/polynomial_roots.cpp @@ -0,0 +1,60 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// tools::polynomial_roots, coefficients in increasing degree (a_0 first). Also the global Aberth +// iteration it falls back to, for comparison: when the two agree bit for bit, the fallback was taken. + +#include "bindings.hpp" + +#include +#include + +#include +#include + +namespace bmpy { + +namespace { + +using C = std::complex; + +nb::ndarray> to_array(std::vector&& roots) +{ + auto* data = new std::vector(std::move(roots)); + nb::capsule owner(data, [](void* p) noexcept { delete static_cast*>(p); }); + return nb::ndarray>(data->data(), {data->size()}, owner); +} + +} // namespace + +void bind_polynomial_roots(nb::module_& m) +{ + namespace bm = boost::math; + m.def("polynomial_roots", [](std::vector a) { + std::vector roots; + { + nb::gil_scoped_release release; + roots = bm::tools::polynomial_roots(a); + } + return to_array(std::move(roots)); + }, nb::arg("coefficients"), "boost::math::tools::polynomial_roots; coefficients a_0, a_1, ..., a_n"); + m.def("polynomial_roots_aberth", [](std::vector a) { + std::vector roots; + { + nb::gil_scoped_release release; + roots = bm::tools::polynomial_roots_detail::aberth(std::vector(a.begin(), a.end())); + } + return to_array(std::move(roots)); + }, nb::arg("coefficients"), "polynomial_roots_detail::aberth: the global fallback, for comparison"); + m.def("polynomial_roots_companion_matrix", [](std::vector a) { + std::vector roots; + { + nb::gil_scoped_release release; + roots = bm::tools::polynomial_roots_companion_matrix(a); + } + return to_array(std::move(roots)); + }, nb::arg("coefficients"), "tools::polynomial_roots_companion_matrix: companion QR of Aurentz, Mach, Vandebril and Watkins"); +} + +} // namespace bmpy diff --git a/nanobind/src/polynomials.cpp b/nanobind/src/polynomials.cpp new file mode 100644 index 0000000000..9fbd4b2018 --- /dev/null +++ b/nanobind/src/polynomials.cpp @@ -0,0 +1,67 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include + +#include "bindings.hpp" +#include "macros.hpp" + +void bmpy::bind_polynomials(nb::module_& m) { + using bmpy::Int; + using bmpy::Real; + BMPY_I1R1(legendre_p, int, "l", "x"); + bmpy::def_vec, Int, Real>( + m, "legendre_p", [](int l, int mm, T x) { return bm::legendre_p(l, mm, x); }, {"l", "m", "x"}, + "boost::math::legendre_p (associated)"); + BMPY_I1R1(legendre_p_prime, int, "l", "x"); + BMPY_I1R1(legendre_q, unsigned, "l", "x"); + BMPY_I1R1(laguerre, unsigned, "n", "x"); + bmpy::def_vec, Int, Real>( + m, "laguerre", [](unsigned n, unsigned mm, T x) { return bm::laguerre(n, mm, x); }, {"n", "m", "x"}, + "boost::math::laguerre (associated)"); + BMPY_I1R1(hermite, unsigned, "n", "x"); + BMPY_I1R1(chebyshev_t, unsigned, "n", "x"); + BMPY_I1R1(chebyshev_u, unsigned, "n", "x"); + BMPY_I1R1(chebyshev_t_prime, unsigned, "n", "x"); + + bmpy::def_vec, Real, Real>( + m, "gegenbauer", [](unsigned n, T lambda, T x) { return bm::gegenbauer(n, lambda, x); }, + {"n", "lambda_", "x"}, "boost::math::gegenbauer"); + bmpy::def_vec, Real, Real>( + m, "gegenbauer_prime", [](unsigned n, T lambda, T x) { return bm::gegenbauer_prime(n, lambda, x); }, + {"n", "lambda_", "x"}, "boost::math::gegenbauer_prime"); + bmpy::def_vec, Real, Real, Int>( + m, "gegenbauer_derivative", + [](unsigned n, T lambda, T x, unsigned k) { return bm::gegenbauer_derivative(n, lambda, x, k); }, + {"n", "lambda_", "x", "k"}, "boost::math::gegenbauer_derivative"); + bmpy::def_vec, Real, Real, Real>( + m, "jacobi", [](unsigned n, T a, T b, T x) { return bm::jacobi(n, a, b, x); }, + {"n", "alpha", "beta", "x"}, "boost::math::jacobi"); + bmpy::def_vec, Real, Real, Real>( + m, "jacobi_prime", [](unsigned n, T a, T b, T x) { return bm::jacobi_prime(n, a, b, x); }, + {"n", "alpha", "beta", "x"}, "boost::math::jacobi_prime"); + bmpy::def_vec, Real, Real, Real, Int>( + m, "jacobi_derivative", + [](unsigned n, T a, T b, T x, unsigned k) { return bm::jacobi_derivative(n, a, b, x, k); }, + {"n", "alpha", "beta", "x", "k"}, "boost::math::jacobi_derivative"); + + bmpy::def_vec, Int, Real, Real>( + m, "spherical_harmonic", + [](unsigned n, int mm, T theta, T phi) { return bm::spherical_harmonic(n, mm, theta, phi); }, + {"n", "m", "theta", "phi"}, "boost::math::spherical_harmonic (complex)"); + bmpy::def_vec, Int, Real, Real>( + m, "spherical_harmonic_r", + [](unsigned n, int mm, T theta, T phi) { return bm::spherical_harmonic_r(n, mm, theta, phi); }, + {"n", "m", "theta", "phi"}, "boost::math::spherical_harmonic_r"); + bmpy::def_vec, Int, Real, Real>( + m, "spherical_harmonic_i", + [](unsigned n, int mm, T theta, T phi) { return bm::spherical_harmonic_i(n, mm, theta, phi); }, + {"n", "m", "theta", "phi"}, "boost::math::spherical_harmonic_i"); +} diff --git a/nanobind/src/quadrature.cpp b/nanobind/src/quadrature.cpp new file mode 100644 index 0000000000..93f139de0b --- /dev/null +++ b/nanobind/src/quadrature.cpp @@ -0,0 +1,181 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// The one-dimensional quadrature routines (and the unit-square cubature), in double, taking a Python +// callable. Each returns what the C++ routine reports: the integral, then its error estimate and L1 norm +// where the C++ gives them. The integrand is called with the GIL held, and an exception it raises +// propagates. naive_monte_carlo is left out: it calls the integrand from its own threads. + +#include "bindings.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace bmpy { + +namespace { + +namespace bq = boost::math::quadrature; + +// f(x) for a Python callable f that returns something convertible to float. +struct scalar_function +{ + nb::callable f; + double operator()(double x) const { return nb::cast(f(x)); } +}; + +struct planar_function +{ + nb::callable f; + double operator()(double x, double y) const { return nb::cast(f(x, y)); } +}; + +const double root_eps = boost::math::tools::root_epsilon(); + +template +std::pair gauss_n(scalar_function const& f, double a, double b) +{ + double L1 = 0; + double Q = bq::gauss::integrate(f, a, b, &L1); + return {Q, L1}; +} + +template +std::tuple gauss_kronrod_n(scalar_function const& f, double a, double b, unsigned max_depth, double tolerance) +{ + double error = 0, L1 = 0; + double Q = bq::gauss_kronrod::integrate(f, a, b, max_depth, tolerance, &error, &L1); + return {Q, error, L1}; +} + +template +std::pair gauss_hermite_n(scalar_function const& f) +{ + double L1 = 0; + double Q = bq::gauss_hermite::integrate(f, &L1); + return {Q, L1}; +} + +[[noreturn]] void bad_points(char const* name, char const* allowed, unsigned points) +{ + throw nb::value_error((std::string(name) + ": points must be one of " + allowed + ", got " + std::to_string(points)).c_str()); +} + +} // namespace + +void bind_quadrature(nb::module_& m) +{ + using nb::arg; + + m.def("tanh_sinh", [](nb::callable f, double a, double b, double tolerance, std::size_t max_refinements) { + double error = 0, L1 = 0; + bq::tanh_sinh integrator(max_refinements); + double Q = integrator.integrate(scalar_function{f}, a, b, tolerance, &error, &L1); + return std::make_tuple(Q, error, L1); + }, arg("f"), arg("a"), arg("b"), arg("tolerance") = root_eps, arg("max_refinements") = 15, + "quadrature::tanh_sinh: (integral, error estimate, L1 norm) of f over [a, b], endpoint singularities allowed"); + + m.def("exp_sinh", [](nb::callable f, double a, double b, double tolerance, std::size_t max_refinements) { + double error = 0, L1 = 0; + bq::exp_sinh integrator(max_refinements); + double Q = integrator.integrate(scalar_function{f}, a, b, tolerance, &error, &L1); + return std::make_tuple(Q, error, L1); + }, arg("f"), arg("a") = 0.0, arg("b") = std::numeric_limits::infinity(), arg("tolerance") = root_eps, + arg("max_refinements") = 9, "quadrature::exp_sinh: (integral, error estimate, L1 norm) over a half-infinite interval"); + + m.def("sinh_sinh", [](nb::callable f, double tolerance, std::size_t max_refinements) { + double error = 0, L1 = 0; + bq::sinh_sinh integrator(max_refinements); + double Q = integrator.integrate(scalar_function{f}, tolerance, &error, &L1); + return std::make_tuple(Q, error, L1); + }, arg("f"), arg("tolerance") = root_eps, arg("max_refinements") = 9, + "quadrature::sinh_sinh: (integral, error estimate, L1 norm) of f over the whole real line"); + + m.def("trapezoidal", [](nb::callable f, double a, double b, double tolerance, std::size_t max_refinements) { + double error = 0, L1 = 0; + double Q = bq::trapezoidal(scalar_function{f}, a, b, tolerance, max_refinements, &error, &L1); + return std::make_tuple(Q, error, L1); + }, arg("f"), arg("a"), arg("b"), arg("tolerance") = root_eps, arg("max_refinements") = 12, + "quadrature::trapezoidal: (integral, error estimate, L1 norm); for periodic integrands over a period"); + + m.def("gauss", [](nb::callable f, double a, double b, unsigned points) { + scalar_function g{f}; + switch (points) + { + case 7: return gauss_n<7>(g, a, b); + case 10: return gauss_n<10>(g, a, b); + case 15: return gauss_n<15>(g, a, b); + case 20: return gauss_n<20>(g, a, b); + case 25: return gauss_n<25>(g, a, b); + case 30: return gauss_n<30>(g, a, b); + default: bad_points("gauss", "7, 10, 15, 20, 25, 30", points); + } + }, arg("f"), arg("a"), arg("b"), arg("points") = 7u, "quadrature::gauss: (integral, L1 norm)"); + + m.def("gauss_kronrod", [](nb::callable f, double a, double b, unsigned points, unsigned max_depth, double tolerance) { + scalar_function g{f}; + switch (points) + { + case 15: return gauss_kronrod_n<15>(g, a, b, max_depth, tolerance); + case 21: return gauss_kronrod_n<21>(g, a, b, max_depth, tolerance); + case 31: return gauss_kronrod_n<31>(g, a, b, max_depth, tolerance); + case 41: return gauss_kronrod_n<41>(g, a, b, max_depth, tolerance); + case 51: return gauss_kronrod_n<51>(g, a, b, max_depth, tolerance); + case 61: return gauss_kronrod_n<61>(g, a, b, max_depth, tolerance); + default: bad_points("gauss_kronrod", "15, 21, 31, 41, 51, 61", points); + } + }, arg("f"), arg("a"), arg("b"), arg("points") = 15u, arg("max_depth") = 15u, arg("tolerance") = root_eps, + "quadrature::gauss_kronrod: (integral, error estimate, L1 norm), adaptive"); + + m.def("gauss_hermite", [](nb::callable f, unsigned points) { + scalar_function g{f}; + switch (points) + { + case 7: return gauss_hermite_n<7>(g); + case 10: return gauss_hermite_n<10>(g); + case 15: return gauss_hermite_n<15>(g); + case 20: return gauss_hermite_n<20>(g); + case 30: return gauss_hermite_n<30>(g); + default: bad_points("gauss_hermite", "7, 10, 15, 20, 30", points); + } + }, arg("f"), arg("points") = 10u, "quadrature::gauss_hermite: (integral of exp(-x^2) f(x) over the real line, L1 norm)"); + + m.def("ooura_fourier_sin", [](nb::callable f, double omega, double tolerance, std::size_t levels) { + bq::ooura_fourier_sin integrator(tolerance, levels); + return integrator.integrate(scalar_function{f}, omega); + }, arg("f"), arg("omega"), arg("tolerance") = root_eps, arg("levels") = 8, + "quadrature::ooura_fourier_sin: (integral of f(t) sin(omega t) over [0, inf), relative error estimate)"); + + m.def("ooura_fourier_cos", [](nb::callable f, double omega, double tolerance, std::size_t levels) { + bq::ooura_fourier_cos integrator(tolerance, levels); + return integrator.integrate(scalar_function{f}, omega); + }, arg("f"), arg("omega"), arg("tolerance") = root_eps, arg("levels") = 8, + "quadrature::ooura_fourier_cos: (integral of f(t) cos(omega t) over [0, inf), relative error estimate)"); + + m.def("van_den_bos_unit_square", [](nb::callable f, double tolerance) { + double error = 0, L1 = 0; + double Q = bq::van_den_bos_unit_square(planar_function{f}, tolerance, &error, &L1); + return std::make_tuple(Q, error, L1); + }, arg("f"), arg("tolerance") = root_eps, + "quadrature::van_den_bos_unit_square: (integral of f(x, y) over [0, 1]^2, error estimate, L1 norm)"); +} + +} // namespace bmpy diff --git a/nanobind/src/ulps.cpp b/nanobind/src/ulps.cpp new file mode 100644 index 0000000000..1d1e266099 --- /dev/null +++ b/nanobind/src/ulps.cpp @@ -0,0 +1,233 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// ulps plots and heatmaps for boost.math.ulps: the double implementation against the same +// function at cpp_bin_float_50, or against a Python reference. + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bindings.hpp" +#include "ulps.hpp" + +namespace nb = bmpy::nb; + +namespace { + +using bmpy::ulps::Precise; +using plot1 = boost::math::tools::ulps_plot, Precise, double>; +using heatmap2 = boost::math::tools::ulps_heatmap, Precise, double>; + +bmpy::ulps::registry const& functions() { + static bmpy::ulps::registry const r = [] { + bmpy::ulps::registry r; + bmpy::ulps::register_gamma(r); + bmpy::ulps::register_special(r); + bmpy::ulps::register_elliptic(r); + return r; + }(); + return r; +} + +template +auto const& lookup(Map const& m, std::string const& name) { + auto it = m.find(name); + if (it == m.end()) { + throw nb::value_error(("no ulps reference for '" + name + "'").c_str()); + } + return it->second; +} + +// An RGB8 PNG: one IDAT, deflated by zlib. +std::vector encode_png(std::vector const& rgb, std::size_t width, std::size_t height) { + std::vector raw; + raw.reserve((3 * width + 1) * height); + for (std::size_t j = 0; j < height; ++j) { + raw.push_back(0); // filter: none + raw.insert(raw.end(), rgb.begin() + 3 * width * j, rgb.begin() + 3 * width * (j + 1)); + } + uLongf size = compressBound(static_cast(raw.size())); + std::vector deflated(size); + if (compress2(deflated.data(), &size, raw.data(), static_cast(raw.size()), Z_DEFAULT_COMPRESSION) != Z_OK) { + throw std::runtime_error("zlib: compress2 failed"); + } + deflated.resize(size); + + std::vector png = {0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n'}; + auto be32 = [](std::vector& v, std::uint32_t n) { + for (int s = 24; s >= 0; s -= 8) { + v.push_back(static_cast(n >> s)); + } + }; + auto chunk = [&](char const* type, std::vector const& data) { + be32(png, static_cast(data.size())); + std::size_t const start = png.size(); + png.insert(png.end(), type, type + 4); + png.insert(png.end(), data.begin(), data.end()); + be32(png, static_cast(crc32(0, png.data() + start, static_cast(png.size() - start)))); + }; + std::vector header; + be32(header, static_cast(width)); + be32(header, static_cast(height)); + header.insert(header.end(), {8, 2, 0, 0, 0}); // 8 bits, RGB, deflate, adaptive filtering, no interlace + chunk("IHDR", header); + chunk("IDAT", deflated); + chunk("IEND", {}); + return png; +} + +// A Python reference, called one at a time: not merely one holder of the GIL at a time, since the interpreter switches +// threads in the middle of a call, and mpmath keeps its working precision in a global, which its functions raise and +// restore. Arguments go as floats where they are doubles, and otherwise (the condition number's finite differences) as +// 55-digit strings, which boost.math.ulps turns into mpmath numbers. It returns a float or a decimal string; anything +// else, or an exception, is NaN. KeyboardInterrupt, SystemExit and a failed signal handler stop the run instead: every +// later call returns NaN at once, and rethrow() raises the error once the computation is over. +class python_reference { +public: + explicit python_reference(nb::handle f) : f_(f) {} + + template + Precise operator()(Args const&... args) { + std::lock_guard lock(mutex_); + if (abort_) { + return std::numeric_limits::quiet_NaN(); + } + nb::gil_scoped_acquire acquire; + bool signal = false; + try { + signal = PyErr_CheckSignals() != 0; + if (signal) { + throw nb::python_error(); + } + return from_python(f_(to_python(args)...)); + } catch (nb::python_error& e) { + if (!signal && !e.matches(PyExc_KeyboardInterrupt) && !e.matches(PyExc_SystemExit)) { + return std::numeric_limits::quiet_NaN(); + } + abort_ = true; + error_ = std::make_unique(std::move(e)); + return std::numeric_limits::quiet_NaN(); + } catch (std::exception const&) { + return std::numeric_limits::quiet_NaN(); + } + } + + // With the GIL held. + void rethrow() { + if (error_) { + nb::python_error e = std::move(*error_); + error_.reset(); + throw e; + } + } + +private: + static nb::object to_python(Precise const& x) { + double const d = static_cast(x); + if (Precise(d) == x) { + return nb::float_(d); + } + return nb::str(x.str(55, std::ios_base::scientific).c_str()); + } + + static Precise from_python(nb::handle r) { + if (nb::isinstance(r) || nb::isinstance(r)) { + return Precise(nb::cast(r)); + } + if (nb::isinstance(r)) { + return Precise(nb::cast(r).c_str()); + } + return std::numeric_limits::quiet_NaN(); + } + + nb::handle f_; + std::mutex mutex_; + bool abort_ = false; + std::unique_ptr error_; +}; + +std::tuple plot(std::string const& name, double a, double b, std::size_t samples, bool log_x, + std::string const& title, nb::handle reference, double clip, bool show_function, + unsigned threads) { + auto const& f = lookup(functions().unary, name); + std::function precise = f.precise; + python_reference py(reference); + if (!reference.is_none()) { + precise = [&py](Precise const& x) { return py(x); }; + } + std::string svg; + std::string summary; + { + nb::gil_scoped_release release; + plot1 p(precise, a, b, samples, false, 20261013, log_x, threads); + p.add_fn(f.coarse).title(title).show_function(show_function).png_encoder(encode_png); + if (clip > 0) { + p.clip(clip); + } + std::ostringstream os; + os << p; + svg = os.str(); + summary = p.summary(); + } + py.rethrow(); + return {svg, summary}; +} + +std::tuple heatmap(std::string const& name, double x_min, double x_max, double y_min, + double y_max, std::size_t width, std::size_t height, bool log_x, + bool log_y, std::string const& title, std::string const& x_label, + std::string const& y_label, bool log_scale, double clip, + nb::handle reference, bool show_function, unsigned threads) { + auto const& f = lookup(functions().binary, name); + std::function precise = f.precise; + python_reference py(reference); + if (!reference.is_none()) { + precise = [&py](Precise const& x, Precise const& y) { return py(x, y); }; + } + std::tuple result; + { + nb::gil_scoped_release release; + heatmap2 h(precise, x_min, x_max, y_min, y_max, width, height, log_x, log_y, threads); + h.add_fn(f.coarse).title(title).x_label(x_label).y_label(y_label).log_scale(log_scale).show_function(show_function) + .png_encoder(encode_png); + if (clip > 0) { + h.clip(clip); + } + result = {h.ulps_svg(), h.ulps_envelope_svg(), h.summary()}; + } + py.rethrow(); + return result; +} + +} // namespace + +void bmpy::bind_ulps(nb::module_& m) { + m.def("_ulps_plot", &plot, nb::arg("name"), nb::arg("a"), nb::arg("b"), nb::arg("samples"), nb::arg("log_x"), + nb::arg("title"), nb::arg("reference").none(), nb::arg("clip"), nb::arg("show_function"), nb::arg("threads"), + "(svg, summary) of an ulps_plot; see boost.math.ulps.plot"); + m.def("_ulps_heatmap", &heatmap, nb::arg("name"), nb::arg("x_min"), nb::arg("x_max"), nb::arg("y_min"), + nb::arg("y_max"), nb::arg("width"), nb::arg("height"), nb::arg("log_x"), nb::arg("log_y"), nb::arg("title"), + nb::arg("x_label"), nb::arg("y_label"), nb::arg("log_scale"), nb::arg("clip"), nb::arg("reference").none(), + nb::arg("show_function"), nb::arg("threads"), + "(ulps svg, ulps/envelope svg, summary) of an ulps_heatmap; see boost.math.ulps.heatmap"); + m.def("_ulps_functions", [] { + std::vector unary, binary; + for (auto const& kv : functions().unary) unary.push_back(kv.first); + for (auto const& kv : functions().binary) binary.push_back(kv.first); + return std::make_tuple(unary, binary); + }, "The names boost.math.ulps.plot and heatmap accept."); +} diff --git a/nanobind/src/ulps.hpp b/nanobind/src/ulps.hpp new file mode 100644 index 0000000000..dd73efd99a --- /dev/null +++ b/nanobind/src/ulps.hpp @@ -0,0 +1,59 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// The functions boost.math.ulps can plot: each at double (the implementation) and at +// cpp_bin_float_50 (the reference), type-erased so that ulps_plot and ulps_heatmap are +// instantiated once per arity. + +#ifndef BOOST_MATH_NANOBIND_ULPS_HPP +#define BOOST_MATH_NANOBIND_ULPS_HPP + +#include + +#include +#include +#include + +namespace bmpy::ulps { + +using Precise = boost::multiprecision::cpp_bin_float_50; + +struct fn1 { + std::function coarse; + std::function precise; +}; + +struct fn2 { + std::function coarse; + std::function precise; +}; + +struct registry { + std::map unary; + std::map binary; +}; + +template +fn1 make1(F f) { + return {[f](double x) { return static_cast(f(x)); }, + [f](Precise const& x) { return static_cast(f(x)); }}; +} + +template +fn2 make2(F f) { + return {[f](double x, double y) { return static_cast(f(x, y)); }, + [f](Precise const& x, Precise const& y) { return static_cast(f(x, y)); }}; +} + +// One entry per function; fn is called through bm::. +#define BMPY_ULPS1(fn) r.unary.emplace(#fn, bmpy::ulps::make1([](auto x) { return bm::fn(x); })) +#define BMPY_ULPS2(fn) r.binary.emplace(#fn, bmpy::ulps::make2([](auto x, auto y) { return bm::fn(x, y); })) + +void register_gamma(registry& r); +void register_special(registry& r); +void register_elliptic(registry& r); + +} // namespace bmpy::ulps + +#endif diff --git a/nanobind/src/ulps_elliptic.cpp b/nanobind/src/ulps_elliptic.cpp new file mode 100644 index 0000000000..cd9b976a61 --- /dev/null +++ b/nanobind/src/ulps_elliptic.cpp @@ -0,0 +1,56 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ulps.hpp" + +namespace bm = boost::math; + +void bmpy::ulps::register_elliptic(registry& r) { + BMPY_ULPS1(ellint_1); + BMPY_ULPS2(ellint_1); + BMPY_ULPS1(ellint_2); + BMPY_ULPS2(ellint_2); + BMPY_ULPS2(ellint_3); + BMPY_ULPS1(ellint_d); + BMPY_ULPS2(ellint_d); + BMPY_ULPS2(ellint_rc); + BMPY_ULPS2(jacobi_zeta); + BMPY_ULPS2(heuman_lambda); + + BMPY_ULPS2(jacobi_sn); + BMPY_ULPS2(jacobi_cn); + BMPY_ULPS2(jacobi_dn); + BMPY_ULPS2(jacobi_cd); + BMPY_ULPS2(jacobi_dc); + BMPY_ULPS2(jacobi_ns); + BMPY_ULPS2(jacobi_sd); + BMPY_ULPS2(jacobi_ds); + BMPY_ULPS2(jacobi_nc); + BMPY_ULPS2(jacobi_nd); + BMPY_ULPS2(jacobi_sc); + BMPY_ULPS2(jacobi_cs); + + BMPY_ULPS2(jacobi_theta1); + BMPY_ULPS2(jacobi_theta2); + BMPY_ULPS2(jacobi_theta3); + BMPY_ULPS2(jacobi_theta4); + BMPY_ULPS2(jacobi_theta3m1); + BMPY_ULPS2(jacobi_theta4m1); + BMPY_ULPS2(jacobi_theta1tau); + BMPY_ULPS2(jacobi_theta2tau); + BMPY_ULPS2(jacobi_theta3tau); + BMPY_ULPS2(jacobi_theta4tau); + BMPY_ULPS2(jacobi_theta3m1tau); + BMPY_ULPS2(jacobi_theta4m1tau); +} diff --git a/nanobind/src/ulps_gamma.cpp b/nanobind/src/ulps_gamma.cpp new file mode 100644 index 0000000000..6e886f949d --- /dev/null +++ b/nanobind/src/ulps_gamma.cpp @@ -0,0 +1,38 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +#include "ulps.hpp" + +namespace bm = boost::math; + +void bmpy::ulps::register_gamma(registry& r) { + BMPY_ULPS1(tgamma); + BMPY_ULPS1(tgamma1pm1); + BMPY_ULPS1(lgamma); + BMPY_ULPS1(digamma); + BMPY_ULPS1(trigamma); + + BMPY_ULPS2(tgamma); // upper incomplete + BMPY_ULPS2(tgamma_ratio); + BMPY_ULPS2(tgamma_delta_ratio); + BMPY_ULPS2(tgamma_lower); + BMPY_ULPS2(gamma_p); + BMPY_ULPS2(gamma_q); + BMPY_ULPS2(gamma_p_inv); + BMPY_ULPS2(gamma_q_inv); + BMPY_ULPS2(gamma_p_inva); + BMPY_ULPS2(gamma_q_inva); + BMPY_ULPS2(gamma_p_derivative); + BMPY_ULPS2(lgamma_p); + BMPY_ULPS2(lgamma_q); + BMPY_ULPS2(ligamma); + BMPY_ULPS2(ligamma_lower); + BMPY_ULPS2(beta); + BMPY_ULPS2(lbeta); +} diff --git a/nanobind/src/ulps_special.cpp b/nanobind/src/ulps_special.cpp new file mode 100644 index 0000000000..335ed59482 --- /dev/null +++ b/nanobind/src/ulps_special.cpp @@ -0,0 +1,86 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ulps.hpp" + +namespace bm = boost::math; + +void bmpy::ulps::register_special(registry& r) { + BMPY_ULPS1(erf); + BMPY_ULPS1(erfc); + BMPY_ULPS1(erf_inv); + BMPY_ULPS1(erfc_inv); + BMPY_ULPS1(expint); + BMPY_ULPS1(zeta); + BMPY_ULPS1(lambert_w0); + BMPY_ULPS1(lambert_wm1); + BMPY_ULPS1(lambert_w0_prime); + BMPY_ULPS1(lambert_wm1_prime); + BMPY_ULPS2(owens_t); + + BMPY_ULPS1(log1p); + BMPY_ULPS1(log1pmx); + BMPY_ULPS1(expm1); + BMPY_ULPS1(cbrt); + BMPY_ULPS1(sqrt1pm1); + BMPY_ULPS1(sin_pi); + BMPY_ULPS1(cos_pi); + BMPY_ULPS1(sinc_pi); + BMPY_ULPS1(sinhc_pi); + BMPY_ULPS1(asinh); + BMPY_ULPS1(acosh); + BMPY_ULPS1(atanh); + BMPY_ULPS1(rsqrt); + BMPY_ULPS1(logit); + BMPY_ULPS1(logistic_sigmoid); + BMPY_ULPS2(powm1); + BMPY_ULPS2(pow1p); + BMPY_ULPS2(hypot); + BMPY_ULPS2(logaddexp); + + BMPY_ULPS2(cyl_bessel_j); + BMPY_ULPS2(cyl_neumann); + BMPY_ULPS2(cyl_bessel_i); + BMPY_ULPS2(cyl_bessel_k); + BMPY_ULPS2(cyl_bessel_j_prime); + BMPY_ULPS2(cyl_neumann_prime); + BMPY_ULPS2(cyl_bessel_i_prime); + BMPY_ULPS2(cyl_bessel_k_prime); + BMPY_ULPS1(airy_ai); + BMPY_ULPS1(airy_bi); + BMPY_ULPS1(airy_ai_prime); + BMPY_ULPS1(airy_bi_prime); + + BMPY_ULPS2(hypergeometric_1F0); + BMPY_ULPS2(hypergeometric_0F1); +} diff --git a/nanobind/src/vectorize.hpp b/nanobind/src/vectorize.hpp new file mode 100644 index 0000000000..ad06b053fb --- /dev/null +++ b/nanobind/src/vectorize.hpp @@ -0,0 +1,263 @@ +// Copyright 2026 Nick Thompson +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Elementwise (NumPy-broadcasting) wrappers for scalar Boost.Math functions. +// +// def_vec(m, "name", f, {"arg", ...}) registers two overloads: +// 1. a fast scalar overload taking Python floats/ints and returning a float, +// which lets Boost.Math exceptions propagate (ValueError, OverflowError, ...); +// 2. a generic overload taking anything np.asarray understands. Arguments are +// broadcast against each other; real arguments are evaluated in float when +// np.result_type of the real arguments is float32 (or float16), otherwise in +// double. 0-d inputs return a NumPy scalar and raise like the scalar path; for +// arrays an element whose evaluation throws becomes NaN and one +// RuntimeWarning summarises the failures. +// +// Each marker describes one argument: Real is the floating-point type T, Int +// is an integer converted (with a range check) to I. f is a C++20 templated +// lambda `[](...)` called as f.template operator()(args...). + +#ifndef BOOST_MATH_NANOBIND_VECTORIZE_HPP +#define BOOST_MATH_NANOBIND_VECTORIZE_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace bmpy { + +namespace nb = nanobind; + +struct Real {}; +template struct Int {}; + +template struct marker; +template struct marker { + using storage = T; + using arg = T; + using scalar = double; + static constexpr bool is_real = true; +}; +template struct marker, T> { + using storage = std::int64_t; + using arg = I; + using scalar = std::int64_t; + static constexpr bool is_real = false; +}; + +template +inline I checked_int(std::int64_t v) { + if constexpr (std::is_signed_v) { + if (v < static_cast((std::numeric_limits::min)()) || v > static_cast((std::numeric_limits::max)())) + throw std::domain_error("integer argument out of range"); + } else { + if (v < 0 || static_cast(v) > static_cast((std::numeric_limits::max)())) + throw std::domain_error("integer argument out of range"); + } + return static_cast(v); +} + +template +inline typename marker::arg convert_scalar(typename marker::storage v) { + if constexpr (marker::is_real) + return v; + else + return checked_int::arg>(v); +} + +template +inline R nan_of() { + if constexpr (std::is_floating_point_v) + return std::numeric_limits::quiet_NaN(); + else { + using V = typename R::value_type; + return R(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); + } +} + +inline nb::module_& numpy() { + static nb::module_ np = nb::module_::import_("numpy"); + return np; +} + +// Converts obj to an ndarray of the storage type of marker M. +template +nb::object as_array(nb::handle obj, const char* argname) { + nb::module_& np = numpy(); + if constexpr (marker::is_real) { + nb::object dt = std::is_same_v ? np.attr("float32") : np.attr("float64"); + return np.attr("asarray")(obj, nb::arg("dtype") = dt); + } else { + nb::object a = np.attr("asarray")(obj); + std::string kind = nb::cast(a.attr("dtype").attr("kind")); + if (kind != "i" && kind != "u" && kind != "b") + throw nb::type_error((std::string("argument '") + argname + "' must be an integer or an integer array").c_str()); + return a.attr("astype")(np.attr("int64")); + } +} + +template +using view = nb::ndarray; + +template +nb::object call_array_impl(const char* name, const F& f, const std::array& objs, + const std::array& names, std::index_sequence) { + constexpr std::size_t N = sizeof...(Ms); + std::array arrays{as_array(objs[Is], names[Is])...}; + std::tuple::storage>...> views{nb::cast::storage>>(arrays[Is])...}; + + // Broadcast shape (NumPy rules). + std::size_t ndim = 0; + std::array nd{std::get(views).ndim()...}; + for (std::size_t k : nd) ndim = k > ndim ? k : ndim; + std::vector shape(ndim, 1); + std::array, N> strides; + auto fold_shape = [&](std::size_t a, const auto& v) { + std::size_t off = ndim - v.ndim(); + for (std::size_t d = 0; d < v.ndim(); ++d) { + std::size_t s = v.shape(d); + if (s != 1) { + if (shape[off + d] != 1 && shape[off + d] != s) + throw nb::value_error((std::string(name) + ": operands could not be broadcast together").c_str()); + shape[off + d] = s; + } + } + (void)a; + }; + (fold_shape(Is, std::get(views)), ...); + auto fold_strides = [&](std::size_t a, const auto& v) { + strides[a].assign(ndim, 0); + std::size_t off = ndim - v.ndim(); + for (std::size_t d = 0; d < v.ndim(); ++d) + strides[a][off + d] = v.shape(d) == 1 ? 0 : v.stride(d); + }; + (fold_strides(Is, std::get(views)), ...); + std::size_t size = 1; + for (std::size_t s : shape) size *= s; + + using R = decltype(f.template operator()(std::declval::arg>()...)); + std::tuple::storage*...> base{std::get(views).data()...}; + + R* out = new R[size ? size : 1]; + nb::capsule owner(out, [](void* p) noexcept { delete[] static_cast(p); }); + + if (ndim == 0) { + // Scalar semantics: let exceptions propagate. + out[0] = f.template operator()(convert_scalar(*std::get(base))...); + } else { + std::size_t nerr = 0; + std::string first; + { + nb::gil_scoped_release release; + std::vector idx(ndim, 0); + std::array pos{}; + for (std::size_t i = 0; i < size; ++i) { + try { + out[i] = f.template operator()(convert_scalar(std::get(base)[pos[Is]])...); + } catch (const std::exception& e) { + if constexpr (!std::is_integral_v) + out[i] = nan_of(); + if (nerr++ == 0) first = e.what(); + } + // Advance the odometer. + for (std::size_t d = ndim; d-- > 0;) { + if (++idx[d] < shape[d]) { + for (std::size_t a = 0; a < N; ++a) pos[a] += strides[a][d]; + break; + } + for (std::size_t a = 0; a < N; ++a) pos[a] -= strides[a][d] * static_cast(shape[d] - 1); + idx[d] = 0; + } + } + } + // Integer results have no NaN to mark a failed element, so raise instead. + if constexpr (std::is_integral_v) { + if (nerr) + throw std::domain_error(std::string(name) + ": " + first); + } + if (nerr) { + std::string msg = std::string(name) + ": " + std::to_string(nerr) + " of " + std::to_string(size) + + " evaluations raised and were set to NaN; first error: " + first; + if (PyErr_WarnEx(PyExc_RuntimeWarning, msg.c_str(), 1) != 0) + throw nb::python_error(); + } + } + nb::object result = nb::cast(nb::ndarray(out, ndim, shape.data(), owner)); + if (ndim == 0) + return result.attr("__getitem__")(nb::tuple()); + return result; +} + +template +nb::object call_array(const char* name, const F& f, const std::array& objs, + const std::array& names) { + // Choose the evaluation type from the real arguments only. + bool use_float = false; + constexpr bool any_real = (marker::is_real || ...); + if constexpr (any_real && AllowFloat) { + nb::module_& np = numpy(); + nb::list reals; + std::size_t a = 0; + // Python scalars stay weakly typed (NEP 50); anything else goes through + // np.asarray, since result_type would read a list as a dtype spec. + auto add = [&](nb::handle h) { + if (PyFloat_Check(h.ptr()) || PyLong_Check(h.ptr()) || PyComplex_Check(h.ptr())) + reals.append(h); + else + reals.append(np.attr("asarray")(h)); + }; + ((marker::is_real ? add(objs[a++]) : (void)a++), ...); + nb::object rt = np.attr("result_type")(*reals); + std::string kind = nb::cast(rt.attr("kind")); + if (kind == "c") + throw nb::type_error((std::string(name) + ": complex arguments are not supported").c_str()); + if (kind == "f" && nb::cast(rt.attr("itemsize")) <= 4) + use_float = true; + } + nb::object result = use_float + ? call_array_impl(name, f, objs, names, std::index_sequence_for{}) + : call_array_impl(name, f, objs, names, std::index_sequence_for{}); + // Plain Python numbers in, plain Python number out, as from the math module. + bool python_scalars = true; + for (nb::handle h : objs) + python_scalars = python_scalars && (PyFloat_Check(h.ptr()) || PyLong_Check(h.ptr())); + if (python_scalars) + return result.attr("item")(); + return result; +} + +template +void def_vec_impl(nb::module_& m, const char* name, F f, std::array names, + const char* doc, std::index_sequence) { + auto scalar = [f](typename marker::scalar... xs) { + return f.template operator()(convert_scalar(xs)...); + }; + m.def(name, scalar, nb::arg(names[Is])..., doc); + auto generic = [f, names, name](std::conditional_t... xs) { + return call_array(name, f, std::array{xs...}, names); + }; + m.def(name, generic, nb::arg(names[Is])...); +} + +// Registers `name` in m; see the comment at the top of this file. +template +void def_vec(nb::module_& m, const char* name, F f, std::array names, const char* doc = "") { + def_vec_impl(m, name, f, names, doc, std::index_sequence_for{}); +} + +} // namespace bmpy + +#endif diff --git a/nanobind/tests/test_smoke.py b/nanobind/tests/test_smoke.py new file mode 100644 index 0000000000..c232eb96d1 --- /dev/null +++ b/nanobind/tests/test_smoke.py @@ -0,0 +1,536 @@ +# Copyright 2026 Nick Thompson +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +"""Smoke tests: each binding once against mpmath (loose 1e-12), plus the conventions.""" + +import inspect +import math +import warnings + +import mpmath as mp +import numpy as np +import pytest + +import boost.math as bm + +mp.mp.dps = 30 +RTOL = 1e-12 + + +def d(f, x, n=1): + return mp.diff(f, x, n) + + +def fac2(n): + return mp.fac2(n) + + +def tangent(n): + # Boost's tangent_t2n(n) is the tangent number T_{2n-1}. + if n == 0: + return 0 + return (-1) ** (n - 1) * 2 ** (2 * n) * (2 ** (2 * n) - 1) * mp.bernoulli(2 * n) / (2 * n) + + +def heuman(k, phi): + m = k * k + mc = 1 - m + K, E = mp.ellipk(m), mp.ellipe(m) + return 2 / mp.pi * (E * mp.ellipf(phi, mc) + K * mp.ellipe(phi, mc) - K * mp.ellipf(phi, mc)) + + +def owens_t(h, a): + return mp.quad(lambda x: mp.exp(-h * h * (1 + x * x) / 2) / (1 + x * x), [0, a]) / (2 * mp.pi) + + +def sph(f, n, x): + return mp.sqrt(mp.pi / (2 * x)) * f(n + mp.mpf(1) / 2, x) + + +PRIMES = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] + +# (python name, args, mpmath reference) +CASES = [ + # gamma.cpp + ("tgamma", (2.5,), mp.gamma), + ("tgamma", (2.5, 1.5), lambda a, z: mp.gammainc(a, z)), + ("tgamma1pm1", (0.25,), lambda z: mp.gamma(1 + z) - 1), + ("lgamma", (7.5,), mp.loggamma), + ("digamma", (3.5,), mp.digamma), + ("trigamma", (3.5,), lambda z: mp.psi(1, z)), + ("polygamma", (3, 2.5), mp.psi), + ("tgamma_ratio", (5.5, 2.25), lambda a, b: mp.gamma(a) / mp.gamma(b)), + ("tgamma_delta_ratio", (5.5, 0.25), lambda a, dd: mp.gamma(a) / mp.gamma(a + dd)), + ("tgamma_lower", (2.5, 1.5), lambda a, z: mp.gammainc(a, 0, z)), + ("gamma_p", (2.5, 1.5), lambda a, z: mp.gammainc(a, 0, z, regularized=True)), + ("gamma_q", (2.5, 1.5), lambda a, z: mp.gammainc(a, z, regularized=True)), + ("gamma_p_inv", (2.5, 0.3), None), + ("gamma_q_inv", (2.5, 0.3), None), + ("gamma_p_inva", (1.5, 0.3), None), + ("gamma_q_inva", (1.5, 0.3), None), + ("gamma_p_derivative", (2.5, 1.5), lambda a, z: z ** (a - 1) * mp.exp(-z) / mp.gamma(a)), + ("lgamma_p", (2.5, 1.5), lambda a, z: mp.log(mp.gammainc(a, 0, z, regularized=True))), + ("lgamma_q", (2.5, 1.5), lambda a, z: mp.log(mp.gammainc(a, z, regularized=True))), + ("ligamma", (2.5, 1.5), lambda a, z: mp.log(mp.gammainc(a, z))), + ("ligamma_lower", (2.5, 1.5), lambda a, z: mp.log(mp.gammainc(a, 0, z))), + ("factorial", (10,), mp.factorial), + ("unchecked_factorial", (10,), mp.factorial), + ("double_factorial", (9,), fac2), + ("rising_factorial", (2.5, 4), mp.rf), + ("falling_factorial", (6.5, 3), mp.ff), + ("binomial_coefficient", (10, 4), mp.binomial), + ("bernoulli_b2n", (3,), lambda n: mp.bernoulli(2 * n)), + ("tangent_t2n", (4,), tangent), + # beta.cpp + ("beta", (2.5, 1.5), mp.beta), + ("beta", (2.5, 1.5, 0.3), lambda a, b, x: mp.betainc(a, b, 0, x)), + ("betac", (2.5, 1.5, 0.3), lambda a, b, x: mp.betainc(a, b, x, 1)), + ("lbeta", (25.5, 31.5), lambda a, b: mp.log(mp.beta(a, b))), + ("ibeta", (2.5, 1.5, 0.3), lambda a, b, x: mp.betainc(a, b, 0, x, regularized=True)), + ("ibetac", (2.5, 1.5, 0.3), lambda a, b, x: mp.betainc(a, b, x, 1, regularized=True)), + ("libeta", (2.5, 1.5, 0.3), lambda a, b, x: mp.log(mp.betainc(a, b, 0, x, regularized=True))), + ("libetac", (2.5, 1.5, 0.3), lambda a, b, x: mp.log(mp.betainc(a, b, x, 1, regularized=True))), + ("ibeta_inv", (2.5, 1.5, 0.3), None), + ("ibetac_inv", (2.5, 1.5, 0.3), None), + ("ibeta_inva", (1.5, 0.3, 0.4), None), + ("ibeta_invb", (2.5, 0.3, 0.4), None), + ("ibetac_inva", (1.5, 0.3, 0.4), None), + ("ibetac_invb", (2.5, 0.3, 0.4), None), + ("ibeta_derivative", (2.5, 1.5, 0.3), lambda a, b, x: x ** (a - 1) * (1 - x) ** (b - 1) / mp.beta(a, b)), + # erf_expint_zeta.cpp + ("erf", (0.3,), mp.erf), + ("erfc", (2.5,), mp.erfc), + ("erf_inv", (0.3,), mp.erfinv), + ("erfc_inv", (0.3,), lambda q: mp.erfinv(1 - mp.mpf(q))), + ("expint", (1.5,), mp.ei), + ("expint", (3, 1.5), mp.expint), + ("zeta", (2.5,), mp.zeta), + ("owens_t", (0.5, 0.75), owens_t), + ("lambert_w0", (1.5,), lambda z: mp.lambertw(z, 0)), + ("lambert_wm1", (-0.2,), lambda z: mp.lambertw(z, -1)), + ("lambert_w0_prime", (1.5,), lambda z: (lambda w: w / (z * (1 + w)))(mp.lambertw(z, 0))), + ("lambert_wm1_prime", (-0.2,), lambda z: (lambda w: w / (z * (1 + w)))(mp.lambertw(z, -1))), + # elementary.cpp + ("log1p", (1e-5,), lambda x: mp.log1p(x)), + ("log1pmx", (0.25,), lambda x: mp.log1p(x) - x), + ("expm1", (1e-5,), mp.expm1), + ("cbrt", (5.5,), mp.cbrt), + ("sqrt1pm1", (1e-5,), lambda x: mp.sqrt(1 + mp.mpf(x)) - 1), + ("powm1", (1.5, 1e-3), lambda x, y: mp.power(x, y) - 1), + ("pow1p", (1e-3, 2.5), lambda x, y: mp.power(1 + mp.mpf(x), y)), + ("sin_pi", (0.3,), mp.sinpi), + ("cos_pi", (0.3,), mp.cospi), + ("sinc_pi", (0.3,), lambda x: mp.sin(x) / x), + ("sinhc_pi", (0.3,), lambda x: mp.sinh(x) / x), + ("asinh", (0.3,), mp.asinh), + ("acosh", (1.3,), mp.acosh), + ("atanh", (0.3,), mp.atanh), + ("hypot", (3.0, 4.5), mp.hypot), + ("rsqrt", (2.5,), lambda x: 1 / mp.sqrt(x)), + ("logit", (0.3,), lambda p: mp.log(p / (1 - mp.mpf(p)))), + ("logistic_sigmoid", (0.3,), lambda x: 1 / (1 + mp.exp(-x))), + ("logaddexp", (0.3, 2.5), lambda x, y: mp.log(mp.exp(x) + mp.exp(y))), + ("float_next", (1.0,), lambda x: np.nextafter(1.0, 2.0)), + ("float_prior", (1.0,), lambda x: np.nextafter(1.0, 0.0)), + ("float_distance", (1.0, 1.0 + 2**-50), lambda a, b: 4), + ("float_advance", (1.0, 4), lambda x, n: 1 + 4 * 2**-52), + ("nextafter", (1.0, 2.0), lambda x, y: np.nextafter(1.0, 2.0)), + ("ulp", (1.0,), lambda x: 2**-52), + ("relative_difference", (1.0, 1.5), lambda a, b: 0.5), + ("epsilon_difference", (1.0, 1.0 + 2**-51), lambda a, b: 2), + ("fibonacci", (30,), mp.fib), + ("prime", (9,), lambda n: PRIMES[n]), + # bessel.cpp + ("cyl_bessel_j", (2.5, 1.5), mp.besselj), + ("cyl_neumann", (2.5, 1.5), mp.bessely), + ("cyl_bessel_i", (2.5, 1.5), mp.besseli), + ("cyl_bessel_k", (2.5, 1.5), mp.besselk), + ("cyl_bessel_j_prime", (2.5, 1.5), lambda v, x: mp.besselj(v, x, derivative=1)), + ("cyl_neumann_prime", (2.5, 1.5), lambda v, x: d(lambda t: mp.bessely(v, t), x)), + ("cyl_bessel_i_prime", (2.5, 1.5), lambda v, x: mp.besseli(v, x, derivative=1)), + ("cyl_bessel_k_prime", (2.5, 1.5), lambda v, x: d(lambda t: mp.besselk(v, t), x)), + ("sph_bessel", (3, 1.5), lambda n, x: sph(mp.besselj, n, x)), + ("sph_neumann", (3, 1.5), lambda n, x: sph(mp.bessely, n, x)), + ("sph_bessel_prime", (3, 1.5), lambda n, x: d(lambda t: sph(mp.besselj, n, t), x)), + ("sph_neumann_prime", (3, 1.5), lambda n, x: d(lambda t: sph(mp.bessely, n, t), x)), + ("cyl_bessel_j_zero", (2.5, 3), mp.besseljzero), + ("cyl_neumann_zero", (2.5, 3), mp.besselyzero), + ("cyl_hankel_1", (2.5, 1.5), mp.hankel1), + ("cyl_hankel_2", (2.5, 1.5), mp.hankel2), + ("sph_hankel_1", (2.5, 1.5), lambda v, x: sph(mp.hankel1, v, x)), + ("sph_hankel_2", (2.5, 1.5), lambda v, x: sph(mp.hankel2, v, x)), + ("airy_ai", (1.5,), mp.airyai), + ("airy_bi", (1.5,), mp.airybi), + ("airy_ai_prime", (1.5,), lambda x: mp.airyai(x, derivative=1)), + ("airy_bi_prime", (1.5,), lambda x: mp.airybi(x, derivative=1)), + ("airy_ai_zero", (3,), mp.airyaizero), + ("airy_bi_zero", (3,), mp.airybizero), + # elliptic.cpp (Boost takes the modulus k, mpmath the parameter m = k^2) + ("ellint_1", (0.5,), lambda k: mp.ellipk(k * k)), + ("ellint_1", (0.5, 0.7), lambda k, phi: mp.ellipf(phi, k * k)), + ("ellint_2", (0.5,), lambda k: mp.ellipe(k * k)), + ("ellint_2", (0.5, 0.7), lambda k, phi: mp.ellipe(phi, k * k)), + ("ellint_3", (0.5, 0.25), lambda k, n: mp.ellippi(n, k * k)), + ("ellint_3", (0.5, 0.25, 0.7), lambda k, n, phi: mp.ellippi(n, phi, k * k)), + ("ellint_d", (0.5,), lambda k: (mp.ellipk(k * k) - mp.ellipe(k * k)) / (k * k)), + ("ellint_d", (0.5, 0.7), lambda k, phi: (mp.ellipf(phi, k * k) - mp.ellipe(phi, k * k)) / (k * k)), + ("ellint_rc", (1.5, 2.5), mp.elliprc), + ("ellint_rd", (1.5, 2.5, 3.5), mp.elliprd), + ("ellint_rf", (1.5, 2.5, 3.5), mp.elliprf), + ("ellint_rg", (1.5, 2.5, 3.5), mp.elliprg), + ("ellint_rj", (1.5, 2.5, 3.5, 4.5), mp.elliprj), + ("jacobi_zeta", (0.5, 0.7), lambda k, phi: mp.ellipe(phi, k * k) - mp.ellipe(k * k) / mp.ellipk(k * k) * mp.ellipf(phi, k * k)), + ("heuman_lambda", (0.5, 0.7), heuman), +] + [ + ("jacobi_" + f, (0.5, 0.7), (lambda f: lambda k, u: mp.ellipfun(f, u, m=k * k))(f)) + for f in ("sn", "cn", "dn", "cd", "dc", "ns", "sd", "ds", "nc", "nd", "sc", "cs") +] + [ + # jacobi_theta.cpp + ("jacobi_theta%d" % n, (0.3, 0.2), (lambda n: lambda z, q: mp.jtheta(n, z, q))(n)) for n in (1, 2, 3, 4) +] + [ + ("jacobi_theta%dtau" % n, (0.3, 1.2), (lambda n: lambda z, t: mp.jtheta(n, z, mp.exp(-mp.pi * t)))(n)) for n in (1, 2, 3, 4) +] + [ + ("jacobi_theta3m1", (0.3, 0.2), lambda z, q: mp.jtheta(3, z, q) - 1), + ("jacobi_theta4m1", (0.3, 0.2), lambda z, q: mp.jtheta(4, z, q) - 1), + ("jacobi_theta3m1tau", (0.3, 1.2), lambda z, t: mp.jtheta(3, z, mp.exp(-mp.pi * t)) - 1), + ("jacobi_theta4m1tau", (0.3, 1.2), lambda z, t: mp.jtheta(4, z, mp.exp(-mp.pi * t)) - 1), + # polynomials.cpp + ("legendre_p", (5, 0.3), mp.legendre), + ("legendre_p", (5, 2, 0.3), mp.legenp), + ("legendre_p_prime", (5, 0.3), lambda l, x: d(lambda t: mp.legendre(l, t), x)), + ("legendre_q", (5, 0.3), lambda l, x: mp.legenq(l, 0, x)), + ("laguerre", (5, 0.3), lambda n, x: mp.laguerre(n, 0, x)), + ("laguerre", (5, 2, 0.3), mp.laguerre), + ("hermite", (5, 0.3), mp.hermite), + ("chebyshev_t", (5, 0.3), mp.chebyt), + ("chebyshev_u", (5, 0.3), mp.chebyu), + ("chebyshev_t_prime", (5, 0.3), lambda n, x: d(lambda t: mp.chebyt(n, t), x)), + ("gegenbauer", (5, 1.5, 0.3), mp.gegenbauer), + ("gegenbauer_prime", (5, 1.5, 0.3), lambda n, a, x: d(lambda t: mp.gegenbauer(n, a, t), x)), + ("gegenbauer_derivative", (5, 1.5, 0.3, 2), lambda n, a, x, k: d(lambda t: mp.gegenbauer(n, a, t), x, k)), + ("jacobi", (5, 1.5, 0.5, 0.3), mp.jacobi), + ("jacobi_prime", (5, 1.5, 0.5, 0.3), lambda n, a, b, x: d(lambda t: mp.jacobi(n, a, b, t), x)), + ("jacobi_derivative", (5, 1.5, 0.5, 0.3, 2), lambda n, a, b, x, k: d(lambda t: mp.jacobi(n, a, b, t), x, k)), + ("spherical_harmonic", (3, 1, 0.3, 0.4), mp.spherharm), + ("spherical_harmonic_r", (3, 1, 0.3, 0.4), lambda n, m, t, p: mp.re(mp.spherharm(n, m, t, p))), + ("spherical_harmonic_i", (3, 1, 0.3, 0.4), lambda n, m, t, p: mp.im(mp.spherharm(n, m, t, p))), + # hypergeometric.cpp + ("hypergeometric_1F0", (2.5, 0.3), lambda a, z: mp.hyper([a], [], z)), + ("hypergeometric_0F1", (2.5, 0.3), mp.hyp0f1), + ("hypergeometric_2F0", (-3.0, 2.5, 0.3), mp.hyp2f0), + ("hypergeometric_1F1", (2.5, 1.5, 0.3), mp.hyp1f1), + ("hypergeometric_1F1_regularized", (2.5, 1.5, 0.3), lambda a, b, z: mp.hyp1f1(a, b, z) / mp.gamma(b)), + ("log_hypergeometric_1F1", (2.5, 1.5, 0.3), lambda a, b, z: mp.log(mp.hyp1f1(a, b, z))), + ("hypergeometric_pFq", ([1.5, 2.5], [3.5], 0.3), lambda a, b, z: mp.hyper(a, b, z)), +] + +# Inverses are checked by round trip: (inverse, forward, which argument of the +# forward function the inverse returns, which argument it consumes as target). +INVERSES = { + "gamma_p_inv": lambda a, p, x: bm.gamma_p(a, x) - p, + "gamma_q_inv": lambda a, q, x: bm.gamma_q(a, x) - q, + "gamma_p_inva": lambda z, p, a: bm.gamma_p(a, z) - p, + "gamma_q_inva": lambda z, q, a: bm.gamma_q(a, z) - q, + "ibeta_inv": lambda a, b, p, x: bm.ibeta(a, b, x) - p, + "ibetac_inv": lambda a, b, q, x: bm.ibetac(a, b, x) - q, + "ibeta_inva": lambda b, x, p, a: bm.ibeta(a, b, x) - p, + "ibeta_invb": lambda a, x, p, b: bm.ibeta(a, b, x) - p, + "ibetac_inva": lambda b, x, q, a: bm.ibetac(a, b, x) - q, + "ibetac_invb": lambda a, x, q, b: bm.ibetac(a, b, x) - q, +} + + +def close(got, want, rtol=RTOL): + want = complex(want) if isinstance(want, mp.mpc) or isinstance(want, complex) else float(want) + return abs(got - want) <= rtol * max(abs(want), 1e-300) + + +def case_id(c): + return "%s/%d" % (c[0], len(c[1])) + + +@pytest.mark.parametrize("case", CASES, ids=case_id) +def test_scalar_value(case): + name, args, ref = case + got = getattr(bm, name)(*args) + if ref is None: + assert abs(INVERSES[name](*args, got)) < 1e-12 + else: + want = ref(*[mp.mpf(a) if isinstance(a, float) else a for a in args]) + assert close(got, want), (got, want) + + +@pytest.mark.parametrize("case", [c for c in CASES if c[0] != "hypergeometric_pFq"], ids=case_id) +def test_array_matches_scalar(case): + """The ndarray overload broadcasts and agrees with the scalar overload.""" + name, args, _ = case + f = getattr(bm, name) + # Turn the last argument into a (2, 3) array of identical values. + last = args[-1] + arr = np.full((2, 3), last) + got = f(*args[:-1], arr) + assert got.shape == (2, 3) + want = f(*args) + assert np.all(got == want) + + +# Not elementwise, so tested on their own below. +SIEVE = {"prime_sieve", "prime_range", "prime_count", "polynomial_roots", "polynomial_roots_aberth", "polynomial_roots_companion_matrix"} +QUADRATURE = {"tanh_sinh", "exp_sinh", "sinh_sinh", "trapezoidal", "gauss", "gauss_kronrod", "gauss_hermite", + "ooura_fourier_sin", "ooura_fourier_cos", "van_den_bos_unit_square"} +OPTIMIZATION = {"differential_evolution", "jso", "random_search", "cma_es"} + + +def test_every_function_has_a_case(): + names = {n for n in bm.__all__ if not inspect.isclass(getattr(bm, n))} + covered = {c[0] for c in CASES} | SIEVE | QUADRATURE | OPTIMIZATION + assert names - covered == set() + + +def test_optimization(): + def f(x): + return (x[0] - 1) ** 2 + (x[1] + 2) ** 2 + lo, hi = [-5.0, -5.0], [5.0, 5.0] + runs = [bm.differential_evolution(f, lo, hi, population=50, max_generations=200, threads=4), bm.jso(f, lo, hi), + bm.random_search(f, lo, hi, max_function_calls=20000)] + if hasattr(bm, "cma_es"): # Only where Eigen was found. + runs.append(bm.cma_es(f, lo, hi, max_generations=200)) + for x in runs: + assert f(x) < 1e-2 + def bad(x): + raise RuntimeError("boom") + with pytest.raises(RuntimeError): + bm.differential_evolution(bad, lo, hi, threads=4) + with pytest.raises(ValueError): + bm.jso(f, [0.0], [1.0, 2.0]) + + +def test_quadrature(): + cases = [ + (bm.tanh_sinh(lambda x: 1 / math.sqrt(x), 0, 1), 2.0), + (bm.exp_sinh(lambda x: math.exp(-x)), 1.0), + (bm.sinh_sinh(lambda x: math.exp(-x * x)), math.sqrt(math.pi)), + (bm.trapezoidal(lambda x: 1 / (5 - 4 * math.cos(x)), 0, 2 * math.pi), 2 * math.pi / 3), + (bm.gauss(lambda x: x * x, 0, 1, points=7), 1 / 3), + (bm.gauss_kronrod(math.sin, 0, math.pi, points=61), 2.0), + (bm.gauss_hermite(lambda x: x * x), math.sqrt(math.pi) / 2), + (bm.ooura_fourier_sin(lambda t: 1 / t, 1.0), math.pi / 2), + (bm.ooura_fourier_cos(lambda t: 1 / (1 + t * t), 1.0), math.pi / (2 * math.e)), + (bm.van_den_bos_unit_square(lambda x, y: x * y), 0.25), + ] + for result, exact in cases: + assert math.isclose(result[0], exact, rel_tol=1e-12) + with pytest.raises(ValueError): + bm.gauss(math.sin, 0, 1, points=8) + with pytest.raises(ZeroDivisionError): + bm.tanh_sinh(lambda x: 1 / 0, 0, 1) + + +def test_sieve(): + want = [p for p in range(2, 100) if all(p % d for d in range(2, p))] + got = bm.prime_sieve(100) + assert got.dtype == np.uint64 and list(got) == want + assert list(bm.prime_range(50, 100)) == [p for p in want if p >= 50] + assert bm.prime_count(100) == len(want) and bm.prime_count(50, 100) == len([p for p in want if p >= 50]) + assert bm.prime_count(10**7) == 664579 + assert list(bm.prime_range(2**63 - 100, 2**63)) == [9223372036854775783] + + +def test_integer_results(): + assert type(bm.prime(3)) is int and bm.prime(3) == 7 + assert bm.prime(np.arange(4)).dtype == np.uint64 + assert bm.fibonacci(93) == 12200160415121876738 and bm.fibonacci(np.arange(3)).dtype == np.uint64 + with pytest.raises(ValueError): + bm.prime(np.array([1, 20000])) + + +def test_python_scalars_give_python_floats(): + assert type(bm.libeta(1, 2, 0.1)) is float + assert type(bm.tgamma(np.float32(3))) is np.float32 + # log(0) is an exact infinity, which goes to the overflow policy: + with pytest.raises(OverflowError): + bm.libeta(1, 2, 0) + + +# --- conventions ------------------------------------------------------------ + + +def test_float32_is_evaluated_in_float(): + x = np.linspace(0.5, 3, 7, dtype=np.float32) + y = bm.tgamma(x) + assert y.dtype == np.float32 + assert isinstance(bm.tgamma(np.float32(0.5)), np.float32) + # Python scalars do not upcast float32 arrays (NEP 50). + assert bm.gamma_p(x, 1.5).dtype == np.float32 + assert bm.gamma_p(x, np.float64(1.5)).dtype == np.float64 + # float_distance is counted in float ulps. + assert bm.float_distance(np.float32(1), np.nextafter(np.float32(1), np.float32(2))) == 1 + + +def test_int_and_list_inputs(): + assert bm.tgamma(3) == 2.0 + assert np.allclose(bm.tgamma([1, 2, 3]), [1, 1, 2]) + assert bm.legendre_p(np.arange(3), 0.5).tolist() == [1.0, 0.5, -0.125] + + +def test_broadcasting_and_strides(): + a = np.array([[1.0], [2.0]]) + b = np.array([1.0, 2.0, 3.0]) + got = bm.ibeta(a, b, 0.5) + assert got.shape == (2, 3) + assert np.allclose(got, [[0.5, 0.75, 0.875], [0.25, 0.5, 0.6875]]) + base = np.arange(12.0).reshape(3, 4) + 1 + view = base[::2, ::-2] + assert np.array_equal(bm.lgamma(view), bm.lgamma(np.ascontiguousarray(view))) + with pytest.raises(ValueError): + bm.beta(np.ones(2), np.ones(3)) + + +def test_complex_results(): + got = bm.cyl_hankel_1(0.5, np.array([1.0, 2.0])) + assert got.dtype == np.complex128 + assert close(got[1], mp.hankel1(0.5, 2)) + + +def test_scalar_errors_raise(): + with pytest.raises(ValueError): + bm.tgamma(-1.0) + with pytest.raises(OverflowError): + bm.tgamma(1e10) + with pytest.raises(ValueError): + bm.tgamma(np.array(-1.0)) # 0-d arrays behave like scalars + with pytest.raises(TypeError): + bm.legendre_p(1.5, 0.5) + with pytest.raises(ValueError): + bm.sph_bessel(-1, 0.5) + + +def test_array_errors_warn_and_give_nan(): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + got = bm.tgamma(np.array([-1.0, 1.5, -2.0])) + assert np.isnan(got[0]) and np.isnan(got[2]) and close(got[1], mp.gamma(1.5)) + assert len(w) == 1 and issubclass(w[0].category, RuntimeWarning) + assert "2 of 3" in str(w[0].message) + + +# --- distributions ---------------------------------------------------------- + +CONTINUOUS = [ + ("arcsine_distribution", ()), + ("beta_distribution", (2.5, 1.5)), + ("cauchy_distribution", ()), + ("chi_squared_distribution", (3.5,)), + ("exponential_distribution", (2.0,)), + ("extreme_value_distribution", ()), + ("generalized_extreme_value_distribution", (0.5, 2.0, 0.1)), + ("fisher_f_distribution", (3.0, 7.0)), + ("gamma_distribution", (2.5, 1.5)), + ("inverse_chi_squared_distribution", (4.0,)), + ("inverse_gamma_distribution", (3.0, 2.0)), + ("inverse_gaussian_distribution", (1.5, 2.0)), + ("laplace_distribution", ()), + ("logistic_distribution", ()), + ("lognormal_distribution", ()), + ("normal_distribution", (1.0, 2.0)), + ("pareto_distribution", (1.0, 3.0)), + ("rayleigh_distribution", (1.5,)), + ("skew_normal_distribution", (0.0, 1.0, 2.0)), + ("students_t_distribution", (4.5,)), + ("triangular_distribution", ()), + ("uniform_distribution", (1.0, 3.0)), + ("weibull_distribution", (2.0, 1.5)), + ("holtsmark_distribution", ()), + ("landau_distribution", ()), + ("mapairy_distribution", ()), + ("saspoint5_distribution", ()), + ("von_mises_distribution", (0.5, 2.0)), + ("kolmogorov_smirnov_distribution", (10.0,)), + ("hyperexponential_distribution", ([0.3, 0.7], [1.0, 3.0])), + ("non_central_beta_distribution", (2.5, 1.5, 1.0)), + ("non_central_chi_squared_distribution", (3.0, 1.5)), + ("non_central_f_distribution", (3.0, 7.0, 1.5)), + ("non_central_t_distribution", (5.0, 1.0)), +] + +DISCRETE = [ + ("bernoulli_distribution", (0.3,)), + ("binomial_distribution", (20.0, 0.3)), + ("geometric_distribution", (0.3,)), + ("hypergeometric_distribution", (10, 20, 50)), + ("negative_binomial_distribution", (5.0, 0.3)), + ("poisson_distribution", (4.5,)), +] + + +# Classes that are not distributions. +TRANSFORMS = {"fft", "real_fft", "dct_ii"} + + +def test_every_distribution_has_a_case(): + names = {n for n in bm.__all__ if inspect.isclass(getattr(bm, n))} + assert names - TRANSFORMS == {c[0] for c in CONTINUOUS + DISCRETE} + assert TRANSFORMS <= names + + +@pytest.mark.parametrize("case", CONTINUOUS, ids=lambda c: c[0]) +def test_continuous_distribution(case): + name, params = case + dist = getattr(bm, name)(*params) + p = np.array([0.1, 0.5, 0.9]) + x = dist.quantile(p) + assert np.allclose(dist.cdf(x), p, rtol=1e-9) + assert np.allclose(dist.quantile_complement(1 - p), x, rtol=1e-9) + assert np.allclose(dist.cdf(x) + dist.cdf_complement(x), 1, rtol=1e-12) + pdf = dist.pdf(x) + assert np.all(pdf > 0) + assert np.allclose(dist.logpdf(x), np.log(pdf), rtol=1e-9) + assert np.allclose(dist.logcdf(x), np.log(p), rtol=1e-9) + assert np.allclose(dist.logcdf_complement(x), np.log1p(-p), rtol=1e-9) + assert np.allclose(dist.hazard(x), pdf / (1 - p), rtol=1e-9) + assert np.allclose(dist.chf(x), -np.log1p(-p), rtol=1e-9) + lo, hi = dist.support() + assert lo <= x[0] and x[-1] <= hi + assert math.isfinite(dist.median()) + + +@pytest.mark.parametrize("case", DISCRETE, ids=lambda c: c[0]) +def test_discrete_distribution(case): + name, params = case + dist = getattr(bm, name)(*params) + k = np.arange(0.0, 2.0 if name == "bernoulli_distribution" else 4.0) + assert np.allclose(np.cumsum(dist.pdf(k)), dist.cdf(k), rtol=1e-12) + assert np.allclose(dist.cdf(k) + dist.cdf_complement(k), 1, rtol=1e-12) + q = dist.quantile(0.5) + assert dist.cdf(q) >= 0.5 - 1e-12 + assert math.isfinite(dist.mean()) and math.isfinite(dist.variance()) + + +@pytest.mark.parametrize("case", CONTINUOUS + DISCRETE, ids=lambda c: c[0]) +def test_distribution_repr(case): + # The repr names the constructor's arguments, each a property, and rebuilds the distribution. + name, params = case + dist = getattr(bm, name)(*params) + r = repr(dist) + assert r.startswith(name + "(") + again = eval(r, vars(bm)) + assert repr(again) == r + assert np.allclose(again.cdf(dist.quantile(0.3)), 0.3, rtol=1e-12) or name in {c[0] for c in DISCRETE} + for i, value in enumerate(params): + arg = r[len(name) + 1:-1].split(", ")[i].split("=")[0] if name != "hyperexponential_distribution" else None + if arg is not None and not isinstance(value, (list, tuple)): + got = getattr(dist, arg) + assert (got() if callable(got) else got) == value + + +def test_normal_against_mpmath(): + dist = bm.normal_distribution(1.0, 2.0) + for x in (-3.0, 0.5, 4.0): + assert close(dist.cdf(x), mp.ncdf(x, 1, 2)) + assert close(dist.pdf(x), mp.npdf(x, 1, 2)) + assert dist.mean() == 1.0 and dist.standard_deviation() == 2.0 + + +def test_undefined_moment_raises(): + with pytest.raises(ValueError): + bm.cauchy_distribution().mean() diff --git a/nanobind/tests/test_ulps.py b/nanobind/tests/test_ulps.py new file mode 100644 index 0000000000..b1302c94b9 --- /dev/null +++ b/nanobind/tests/test_ulps.py @@ -0,0 +1,76 @@ +# Copyright 2026 Nick Thompson +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +import importlib.util + +import mpmath as mp +import pytest + +import boost.math as bm +from boost.math import ulps + +pytestmark = pytest.mark.skipif(not hasattr(bm._ext, "_ulps_plot"), reason="built without boost.math.ulps") + + +def check(svg): + assert str(svg).startswith((" 10000 + assert svg.summary + + +def test_plot(tmp_path): + svg = ulps.plot(bm.digamma, -5, 5, samples=2000) + check(svg) + assert "samples=2000" in svg.summary + assert svg._repr_svg_() == str(svg) + path = tmp_path / "digamma.svg" + svg.save(path) + assert path.read_text() == str(svg) + + +def test_heatmap(): + u, e = ulps.heatmap("lgamma_p", (1, 1e3), (0.01, 1e3), width=40, height=30, log_x=True, log_y=True) + check(u) + check(e) + assert str(u) != str(e) + assert "1200 pixels" in u.summary + + +def test_python_reference(): + svg = ulps.plot(bm.erf, -3, 3, samples=200, reference=mp.erf) + check(svg) + assert "worst_ulps=" in svg.summary + # A reference that raises leaves the points without a value: + svg = ulps.plot(bm.erf, -3, 3, samples=50, reference=lambda x: 1 / 0) + assert "undefined=50" in svg.summary + + +def test_reference_interrupt(): + def ref(x): + raise KeyboardInterrupt + + with pytest.raises(KeyboardInterrupt): + ulps.plot(bm.erf, -3, 3, samples=50, reference=ref) + + +def test_only_bound_functions(): + def digamma(x): + return bm.digamma(x) + + with pytest.raises(TypeError, match="arbitrary Python callables"): + ulps.plot(digamma, 1, 2) + + +def test_unknown_name(): + with pytest.raises(ValueError, match="no ulps reference for 'nonesuch'"): + ulps.plot("nonesuch", 0, 1) + with pytest.raises(ValueError, match="no ulps reference for 'digamma'"): + ulps.heatmap(bm.digamma, (0, 1), (0, 1)) + + +@pytest.mark.skipif(ulps._chrome() is None and importlib.util.find_spec("cairosvg") is None, + reason="needs Chrome or cairosvg") +def test_render_to_png(tmp_path): + path = ulps.render_to_png(ulps.plot(bm.digamma, 1, 2, samples=100), tmp_path / "digamma.png") + with open(path, "rb") as f: + assert f.read(8) == b"\x89PNG\r\n\x1a\n" diff --git a/reporting/accuracy/Jamfile.v2 b/reporting/accuracy/Jamfile.v2 index 0d961e66c5..42080d3408 100644 --- a/reporting/accuracy/Jamfile.v2 +++ b/reporting/accuracy/Jamfile.v2 @@ -182,3 +182,6 @@ run erfc_error_plot.cpp /boost/multiprecision//boost_multiprecision mpfr gmp : : explicit erfc_error_plot_cpp_bin_float_50 ; run erfc_error_plot.cpp /boost/multiprecision//boost_multiprecision mpfr gmp quadmath : : : release 17 gnu TEST_TYPE=float128 [ check-target-builds ../../config//has_mpfr : : no ] : erfc_error_plot_float128 ; explicit erfc_error_plot_cpp_bin_float_50 ; + +run pow1p_ulps_plot.cpp : : : release 17 : pow1p_ulps_plot ; +explicit pow1p_ulps_plot ; diff --git a/reporting/accuracy/ligamma_ulps_heatmap.cpp b/reporting/accuracy/ligamma_ulps_heatmap.cpp new file mode 100644 index 0000000000..d748491c7d --- /dev/null +++ b/reporting/accuracy/ligamma_ulps_heatmap.cpp @@ -0,0 +1,37 @@ +// (C) Copyright Nick Thompson 2026. +// 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) +// +// Writes 2D ulps plots of ligamma(a, x) in double over a log-log grid. +// The reference is log(tgamma(a, x)) in 50 digits, which can't underflow. +// Requires lodepng: link lodepng.cpp and put lodepng.h on the include path. + +#define BOOST_MATH_USE_LODEPNG +#include +#include +#include +#include + +using boost::math::tools::ulps_heatmap; +using PreciseReal = boost::multiprecision::cpp_bin_float_50; +using CoarseReal = double; + +int main() +{ + auto precise = [](PreciseReal const & a, PreciseReal const & x) { return log(boost::math::tgamma(a, x)); }; + auto ligamma = [](CoarseReal a, CoarseReal x) { return boost::math::ligamma(a, x); }; + + auto h = ulps_heatmap(precise, 1e-3, 1e4, 1e-3, 1e4, 600, 400, true, true); + h.add_fn(ligamma); + std::cout << h.summary(); + h.x_label("a").y_label("x"); + + h.title("ligamma(a, x), double: error in ulps"); + h.log_scale(false).write_ulps("ligamma_ulps.svg"); + h.log_scale(true).write_ulps("ligamma_ulps_log.svg"); + + h.title("ligamma(a, x), double: error relative to the conditioning envelope"); + h.log_scale(false).write_ulps_envelope("ligamma_ulps_envelope.svg"); + h.log_scale(true).write_ulps_envelope("ligamma_ulps_envelope_log.svg"); +} diff --git a/reporting/accuracy/plot_jacobi_theta_q.cpp b/reporting/accuracy/plot_jacobi_theta_q.cpp index 437fc3b593..be9d0264ba 100644 --- a/reporting/accuracy/plot_jacobi_theta_q.cpp +++ b/reporting/accuracy/plot_jacobi_theta_q.cpp @@ -47,7 +47,7 @@ int main() { PreciseReal clip = 100; std::string filename1 = "jacobi_theta1q_" + boost::core::demangle(typeid(CoarseReal).name()) + ".svg"; - auto plot1 = ulps_plot(jacobi_theta1_precise, CoarseReal(0), CoarseReal(0.999999), samples); + auto plot1 = ulps_plot(jacobi_theta1_precise, CoarseReal(0.000001), CoarseReal(0.999999), samples); plot1.clip(clip).width(width); std::string title1 = "jacobi_theta1(5.0, q) ULP plot at " + boost::core::demangle(typeid(CoarseReal).name()) + " precision"; plot1.title(title1); @@ -56,7 +56,7 @@ int main() { plot1.write(filename1); std::string filename2 = "jacobi_theta2q_" + boost::core::demangle(typeid(CoarseReal).name()) + ".svg"; - auto plot2 = ulps_plot(jacobi_theta2_precise, CoarseReal(0), CoarseReal(0.999999), samples); + auto plot2 = ulps_plot(jacobi_theta2_precise, CoarseReal(0.000001), CoarseReal(0.999999), samples); plot2.clip(clip).width(width); std::string title2 = "jacobi_theta2(0.4, q) ULP plot at " + boost::core::demangle(typeid(CoarseReal).name()) + " precision"; plot2.title(title2); @@ -65,7 +65,7 @@ int main() { plot2.write(filename2); std::string filename3 = "jacobi_theta3q_" + boost::core::demangle(typeid(CoarseReal).name()) + ".svg"; - auto plot3 = ulps_plot(jacobi_theta3_precise, CoarseReal(0), CoarseReal(0.999999), samples); + auto plot3 = ulps_plot(jacobi_theta3_precise, CoarseReal(0.000001), CoarseReal(0.999999), samples); plot3.clip(clip).width(width); std::string title3 = "jacobi_theta3(0.4, q) ULP plot at " + boost::core::demangle(typeid(CoarseReal).name()) + " precision"; plot3.title(title3); @@ -74,7 +74,7 @@ int main() { plot3.write(filename3); std::string filename4 = "jacobi_theta4q_" + boost::core::demangle(typeid(CoarseReal).name()) + ".svg"; - auto plot4 = ulps_plot(jacobi_theta4_precise, CoarseReal(0), CoarseReal(0.999999), samples); + auto plot4 = ulps_plot(jacobi_theta4_precise, CoarseReal(0.000001), CoarseReal(0.999999), samples); plot4.clip(clip).width(width); std::string title4 = "jacobi_theta4(5.0, q) ULP plot at " + boost::core::demangle(typeid(CoarseReal).name()) + " precision"; plot4.title(title4); diff --git a/reporting/accuracy/plot_van_den_bos_unit_square_convergence.py b/reporting/accuracy/plot_van_den_bos_unit_square_convergence.py new file mode 100644 index 0000000000..d1ae8db5a1 --- /dev/null +++ b/reporting/accuracy/plot_van_den_bos_unit_square_convergence.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python3 +# Copyright Nicholas Thompson 2026. +# 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) + +# /// script +# requires-python = ">=3.9" +# dependencies = [ +# "matplotlib>=3.8", +# ] +# /// + +import argparse +import math +import re +from pathlib import Path + +import matplotlib + +matplotlib.use("Agg") +import matplotlib.pyplot as plt + + +REPOSITORY_ROOT = Path(__file__).resolve().parents[2] +DEFAULT_TRACE = ( + REPOSITORY_ROOT + / "build" + / "vdb" + / "van_den_bos_unit_square_convergence.csv" +) +DEFAULT_OUTPUT = DEFAULT_TRACE.with_suffix(".png") + +DISPLAY_NAMES = { + "quadratic": "Quadratic", + "exp_x_plus_y": r"$e^{x+y}$", + "exp_xy": r"$e^{xy}$", + "one_over_1_plus_x_plus_y": r"$1/(1+x+y)$", + "complex_exp_5ixy": r"$e^{5ixy}$", + "cos_5xy": r"$\cos(5xy)$", + "sqrt_x_plus_y": r"$\sqrt{x+y}$", + "inv_sqrt_xy": r"$1/\sqrt{xy}$", +} + + +def parse_value(s): + s = s.strip() + if s.startswith("(") and s.endswith(")") and "," in s: + a, b = s[1:-1].split(",", 1) + return complex(float(a), float(b)) + return float(s) + +def parse_trace(path): + cases = {} + current = None + + for raw in Path(path).read_text().splitlines(): + if raw.startswith("VDB_CASE,"): + match = re.fullmatch(r"VDB_CASE,name=([^,]+),exact=(.+)", raw) + if not match: + raise ValueError(f"cannot parse case record: {raw}") + current = match.group(1) + cases[current] = { + "exact": parse_value(match.group(2)), + "levels": [], + } + elif raw.startswith("VDB_LEVEL,") and current is not None: + match = re.fullmatch( + r"VDB_LEVEL,level=(\d+),nodes=(\d+),evaluations=(\d+)," + r"value=(\([^)]*\)|[^,]+)," + r"delta=([^,]+),error_estimate=(.+)", + raw, + ) + if not match: + raise ValueError(f"cannot parse level record: {raw}") + + value = parse_value(match.group(4)) + exact = cases[current]["exact"] + actual_error = abs(value - exact) + error_text = match.group(6) + cases[current]["levels"].append({ + "level": int(match.group(1)), + "nodes": int(match.group(2)), + "evaluations": int(match.group(3)), + "value": value, + "actual_error": actual_error, + "estimated_error": float(error_text) + if error_text != "nan" + else math.nan, + }) + elif raw.startswith("VDB_END,"): + current = None + + return cases + +def main(): + ap = argparse.ArgumentParser( + description="Plot van den Bos unit-square convergence traces.", + ) + ap.add_argument( + "trace", + nargs="?", + type=Path, + default=DEFAULT_TRACE, + help=f"trace CSV (default: {DEFAULT_TRACE})", + ) + ap.add_argument( + "--out", + type=Path, + default=DEFAULT_OUTPUT, + help=f"output image (default: {DEFAULT_OUTPUT})", + ) + ap.add_argument( + "--separate", + action="store_true", + help="also write one convergence plot per integrand", + ) + args = ap.parse_args() + + cases = parse_trace(args.trace) + if not cases: + raise ValueError(f"no van den Bos trace records found in {args.trace}") + + args.out.parent.mkdir(parents=True, exist_ok=True) + + plt.style.use("dark_background") + fig, ax = plt.subplots(figsize=(10.5, 6.2)) + + for name, case in cases.items(): + xs = [row["evaluations"] for row in case["levels"]] + ys = [max(row["actual_error"], 1e-18) for row in case["levels"]] + ax.plot( + xs, + ys, + marker="o", + markersize=5, + linewidth=1.8, + label=DISPLAY_NAMES.get(name, name.replace("_", " ")), + ) + + ax.set_yscale("log") + ax.set_xlabel("Function evaluations") + ax.set_ylabel("Absolute error") + ax.set_title("van den Bos unit-square convergence") + ax.grid(True, which="major", color="white", alpha=0.18) + ax.grid(True, which="minor", axis="y", color="white", alpha=0.07) + ax.legend( + title="Integrand", + loc="upper left", + bbox_to_anchor=(1.02, 1), + borderaxespad=0, + frameon=False, + ) + fig.tight_layout() + fig.savefig(args.out, dpi=180) + plt.close(fig) + print(f"wrote {args.out}") + + if args.separate: + out = args.out + for name, case in cases.items(): + fig, ax = plt.subplots() + xs = [row["evaluations"] for row in case["levels"]] + ys = [max(row["actual_error"], 1e-18) for row in case["levels"]] + estimates = [ + max(row["estimated_error"], 1e-18) + if math.isfinite(row["estimated_error"]) + else math.nan + for row in case["levels"] + ] + ax.plot(xs, ys, marker="o", label="actual error") + ax.plot(xs, estimates, marker="x", label="estimated error") + ax.set_yscale("log") + ax.set_xlabel("Function evaluations") + ax.set_ylabel("Absolute error") + ax.set_title(DISPLAY_NAMES.get(name, name.replace("_", " "))) + ax.grid(True, which="both", alpha=0.25) + ax.legend() + fig.tight_layout() + fig.savefig( + out.with_name(f"{out.stem}_{name}{out.suffix}"), + dpi=180, + ) + plt.close(fig) + +if __name__ == "__main__": + main() diff --git a/reporting/accuracy/pow1p_ulps_plot.cpp b/reporting/accuracy/pow1p_ulps_plot.cpp new file mode 100644 index 0000000000..63dca71fae --- /dev/null +++ b/reporting/accuracy/pow1p_ulps_plot.cpp @@ -0,0 +1,38 @@ +// (C) Copyright Nick Thompson 2026. +// 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) +// +// Writes the ULPs plots of pow1p used in doc/sf/pow1p.qbk. +// pow1p is drawn in steelblue and the naive pow(1 + x, y) in orange. + +#include +#include +#include +#include +#include + +using boost::math::tools::ulps_plot; +using PreciseReal = boost::multiprecision::cpp_bin_float_100; +using CoarseReal = double; + +void plot(CoarseReal y, CoarseReal a, CoarseReal b, std::string const & title, std::string const & filename) +{ + auto precise = [y](PreciseReal const & x) { return exp(PreciseReal(y) * log1p(x)); }; + auto pow1p = [y](CoarseReal x) { return boost::math::pow1p(x, y); }; + auto naive = [y](CoarseReal x) { return std::pow(1 + x, y); }; + + auto p = ulps_plot(precise, a, b, 2000, false, 42); + p.clip(100).width(700).vertical_lines(6); + p.background_color("white").font_color("black"); + p.title(title); + p.add_fn(naive, "orange"); + p.add_fn(pow1p, "steelblue"); + p.write(filename); +} + +int main() +{ + plot(1000, -0.5, 0.5, "pow1p(x, 1000) vs pow(1 + x, 1000), double", "pow1p_ulps_y1000.svg"); + plot(1048576, -1e-4, 1e-4, "pow1p(x, 2^20) vs pow(1 + x, 2^20), double", "pow1p_ulps_y2e20.svg"); +} diff --git a/reporting/accuracy/test_log1p_expm1.cpp b/reporting/accuracy/test_log1p_expm1.cpp index 24016e3855..2f0ce999f2 100644 --- a/reporting/accuracy/test_log1p_expm1.cpp +++ b/reporting/accuracy/test_log1p_expm1.cpp @@ -6,7 +6,7 @@ #define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error #include "bindings.hpp" -#include "../../test/log1p_expm1_test.hpp" +#include "../../test/test_log1p_expm1.hpp" #include #include #define BOOST_TEST_MAIN diff --git a/reporting/accuracy/test_powm1.cpp b/reporting/accuracy/test_powm1.cpp index 378a11d32e..30fc56d1fc 100644 --- a/reporting/accuracy/test_powm1.cpp +++ b/reporting/accuracy/test_powm1.cpp @@ -6,7 +6,7 @@ #define BOOST_TEST_MAIN #include "bindings.hpp" -#include "../../test/powm1_sqrtp1m1_test.hpp" +#include "../../test/test_powm1_sqrtp1m1.hpp" #include #include #include diff --git a/reporting/accuracy/van_den_bos_unit_square_convergence.cpp b/reporting/accuracy/van_den_bos_unit_square_convergence.cpp new file mode 100644 index 0000000000..1d1985dae1 --- /dev/null +++ b/reporting/accuracy/van_den_bos_unit_square_convergence.cpp @@ -0,0 +1,152 @@ +// Copyright Nicholas Thompson 2026. +// 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) + +/* + * Convergence trace driver for van_den_bos_unit_square. + * + * Build: + * c++ -O3 -DNDEBUG -DBOOST_MATH_INSTRUMENT -std=c++17 -Iinclude \ + * reporting/accuracy/van_den_bos_unit_square_convergence.cpp \ + * -o vdb_unit_square_convergence + * + * Run: + * ./vdb_unit_square_convergence > van_den_bos_unit_square_convergence.csv + */ + +#include + +#include +#include +#include +#include +#include +#include + +namespace { + +using boost::math::quadrature::van_den_bos_unit_square; + +template +void run_case(char const* name, F const& f, Exact const& exact, double tol = 1e-12) +{ + double error = 0; + double l1 = 0; + std::size_t evaluations = 0; + + std::cout << std::setprecision(std::numeric_limits::max_digits10) + << "VDB_CASE,name=" << name << ",exact=" << exact << '\n'; + (void)van_den_bos_unit_square( + f, tol, &error, &l1, &evaluations); + std::cout << "VDB_END,name=" << name + << ",error_estimate=" << error + << ",evaluations=" << evaluations << '\n'; +} + +std::complex exact_exp_5ixy() +{ + std::complex exact(0, 0); + std::complex power(1, 0); + double factorial = 1; + + for (unsigned k = 0; k < 100; ++k) + { + if (k > 0) + { + power *= std::complex(0, 5); + factorial *= double(k); + } + const double kp1 = double(k + 1); + const auto term = power / (factorial * kp1 * kp1); + exact += term; + if (std::abs(term) < 1e-18) + break; + } + return exact; +} + +} // namespace + +int main() +{ + run_case( + "quadratic", + [](double x, double y) + { + return x * x + y * y + x * y; + }, + 11.0 / 12.0); + + run_case( + "exp_x_plus_y", + [](double x, double y) + { + return std::exp(x + y); + }, + std::pow(std::expm1(1.0), 2)); + + run_case( + "exp_xy", + [](double x, double y) + { + return std::exp(x * y); + }, + [] { + double s = 0; + double factorial = 1; + for (unsigned k = 0; k < 100; ++k) + { + if (k > 0) + factorial *= double(k); + const double kp1 = double(k + 1); + const double term = 1.0 / (factorial * kp1 * kp1); + s += term; + if (term < 1e-18) + break; + } + return s; + }()); + + run_case( + "one_over_1_plus_x_plus_y", + [](double x, double y) + { + return 1.0 / (1.0 + x + y); + }, + 3.0 * std::log(3.0) - 4.0 * std::log(2.0)); + + run_case( + "complex_exp_5ixy", + [](double x, double y) + { + return std::exp(std::complex(0, 5 * x * y)); + }, + exact_exp_5ixy()); + + run_case( + "cos_5xy", + [](double x, double y) + { + return std::cos(5.0 * x * y); + }, + exact_exp_5ixy().real()); + + run_case( + "sqrt_x_plus_y", + [](double x, double y) + { + return std::sqrt(x + y); + }, + (4.0 / 15.0) * (std::pow(2.0, 2.5) - 2.0)); + + run_case( + "inv_sqrt_xy", + [](double x, double y) + { + return 1 / std::sqrt(x * y); + }, + 4.0); + + return 0; +} diff --git a/reporting/accuracy/von_mises_ulps.cpp b/reporting/accuracy/von_mises_ulps.cpp new file mode 100644 index 0000000000..3b67120dd2 --- /dev/null +++ b/reporting/accuracy/von_mises_ulps.cpp @@ -0,0 +1,90 @@ +// Copyright Philipp C. J. Muenster, 2020. +// Copyright Matt Borland, 2022. + +// 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) + +#include + +#include +#include +#include + +using precise_real = boost::multiprecision::cpp_bin_float_50; + +template +void generate_ulps_plot_pdf(CoarseReal concentration) +{ + auto hi_conc = static_cast(concentration); + auto high_precision = [hi_conc](precise_real x) + { + boost::math::von_mises_distribution dist(0, hi_conc); + return boost::math::pdf(dist, x); + }; + + auto low_precision = [concentration](CoarseReal x) + { + boost::math::von_mises_distribution dist(0, concentration); + return boost::math::pdf(dist, x); + }; + + using hp_func = decltype (high_precision); + + auto pi = boost::math::constants::pi(); + boost::math::tools::ulps_plot plot( + high_precision, -pi, +pi); + plot.add_fn(low_precision); + std::string filename = "von_mises_ulps_pdf_" + + std::to_string(static_cast(concentration)) + + typeid(CoarseReal).name() + + ".svg"; + plot.write(filename); +} + +template +void generate_ulps_plot_cdf(CoarseReal concentration) +{ + auto hi_conc = static_cast(concentration); + auto high_precision = [hi_conc](precise_real x) + { + boost::math::von_mises_distribution dist(0, hi_conc); + return boost::math::cdf(dist, x); + }; + + auto low_precision = [concentration](CoarseReal x) + { + boost::math::von_mises_distribution dist(0, concentration); + return boost::math::cdf(dist, x); + }; + + using hp_func = decltype (high_precision); + + auto pi = boost::math::constants::pi(); + boost::math::tools::ulps_plot plot( + high_precision, -pi, +pi); + plot.add_fn(low_precision); + std::string filename = "von_mises_ulps_cdf_" + + std::to_string(static_cast(concentration)) + + typeid(CoarseReal).name() + + ".svg"; + plot.write(filename); +} + +void generate_ulps_plots(double concentration) +{ + auto fconc = static_cast(concentration); + generate_ulps_plot_pdf(fconc); + generate_ulps_plot_cdf(fconc); + + generate_ulps_plot_pdf(concentration); + generate_ulps_plot_cdf(concentration); +} + +int main() +{ + generate_ulps_plots(4); + generate_ulps_plots(64); + + return 0; +} diff --git a/reporting/performance/float_distance_performance.cpp b/reporting/performance/float_distance_performance.cpp new file mode 100644 index 0000000000..81ca901034 --- /dev/null +++ b/reporting/performance/float_distance_performance.cpp @@ -0,0 +1,36 @@ +// (C) Copyright Matt Borland 2022. +// 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) + +#include +#include + +template +void float_distance(benchmark::State& state) +{ + const auto difference = static_cast(state.range(0)); + T left = 2; + T right = boost::math::float_advance(left, difference); + + for (auto _ : state) + { + benchmark::DoNotOptimize(left); + benchmark::DoNotOptimize(right); + benchmark::DoNotOptimize(boost::math::float_distance(left, right)); + } + state.SetComplexityN(state.range(0)); +} + +BENCHMARK_TEMPLATE(float_distance, float)->RangeMultiplier(2)->Range(1 << 1, 1 << 14)->Complexity()->UseRealTime(); +BENCHMARK_TEMPLATE(float_distance, double)->RangeMultiplier(2)->Range(1 << 1, 1 << 14)->Complexity()->UseRealTime(); + +BENCHMARK_MAIN(); + +/* +Apple M-series, Homebrew clang 23, -O3 (Sept 2026), time per call: + + generic code bit patterns +float_distance 14.8 ns 2.3 ns +float_distance 14.5 ns 2.2 ns +*/ diff --git a/reporting/performance/generalized_extreme_value_performance.cpp b/reporting/performance/generalized_extreme_value_performance.cpp new file mode 100644 index 0000000000..a6b48a9b7c --- /dev/null +++ b/reporting/performance/generalized_extreme_value_performance.cpp @@ -0,0 +1,109 @@ +// (C) Copyright Nick Thompson 2026. +// 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) + +// +// The generalized extreme value distribution's pdf, cdf and quantile at shape xi = 0.2, against the +// Gumbel distribution (extreme_value, which is xi = 0) as the baseline, and its skewness, whose +// moment series is the expensive part of the moments. +// +// Promotion is disabled so that each type is timed in its own arithmetic: by default, +// float is evaluated in double, and double in long double where that is wider. +// + +#include +#include +#include +#include +#include + +using no_promotion = boost::math::policies::policy, boost::math::policies::promote_double>; + +template +std::vector abscissas() +{ + std::mt19937_64 mt {42}; + std::uniform_real_distribution dis(-2, 20); + std::vector v(1024); + for (auto& x : v) + { + x = static_cast(dis(mt)); + } + return v; +} + +template +std::vector probabilities() +{ + std::mt19937_64 mt {42}; + std::uniform_real_distribution dis(0.001, 0.999); + std::vector v(1024); + for (auto& p : v) + { + p = static_cast(dis(mt)); + } + return v; +} + +template +auto gev() +{ + return boost::math::generalized_extreme_value_distribution(Real(0.5), Real(2), Real(0.2)); +} + +template +auto gumbel() +{ + return boost::math::extreme_value_distribution(Real(0.5), Real(2)); +} + +#define BENCH(name, make, fn, points) \ +template \ +void name(benchmark::State& state) \ +{ \ + auto d = make(); \ + auto v = points(); \ + std::size_t i = 0; \ + for (auto _ : state) \ + { \ + benchmark::DoNotOptimize(fn(d, v[i++ & 1023])); \ + } \ +} + +BENCH(gev_pdf, gev, boost::math::pdf, abscissas) +BENCH(gumbel_pdf, gumbel, boost::math::pdf, abscissas) +BENCH(gev_cdf, gev, boost::math::cdf, abscissas) +BENCH(gumbel_cdf, gumbel, boost::math::cdf, abscissas) +BENCH(gev_quantile, gev, boost::math::quantile, probabilities) +BENCH(gumbel_quantile, gumbel, boost::math::quantile, probabilities) + +template +void gev_skewness(benchmark::State& state) +{ + std::mt19937_64 mt {42}; + std::uniform_real_distribution dis(-0.5, 0.3); + std::vector> v; + for (int i = 0; i < 1024; ++i) + { + v.emplace_back(Real(0), Real(1), static_cast(dis(mt))); + } + std::size_t i = 0; + for (auto _ : state) + { + benchmark::DoNotOptimize(boost::math::skewness(v[i++ & 1023])); + } +} + +BENCHMARK_TEMPLATE(gev_pdf, float); +BENCHMARK_TEMPLATE(gev_pdf, double); +BENCHMARK_TEMPLATE(gumbel_pdf, double); +BENCHMARK_TEMPLATE(gev_cdf, float); +BENCHMARK_TEMPLATE(gev_cdf, double); +BENCHMARK_TEMPLATE(gumbel_cdf, double); +BENCHMARK_TEMPLATE(gev_quantile, float); +BENCHMARK_TEMPLATE(gev_quantile, double); +BENCHMARK_TEMPLATE(gumbel_quantile, double); +BENCHMARK_TEMPLATE(gev_skewness, double); + +BENCHMARK_MAIN(); diff --git a/reporting/performance/ibeta_performance.cpp b/reporting/performance/ibeta_performance.cpp new file mode 100644 index 0000000000..487a16ac20 --- /dev/null +++ b/reporting/performance/ibeta_performance.cpp @@ -0,0 +1,116 @@ +// (C) Copyright Nick Thompson 2026. +// 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) + +// +// Times ibeta, ibetac and ibeta_invb over the regions whose evaluation was changed to meet the +// accuracy of the issue "Inverse incomplete gamma and beta functions are 10-35x less accurate than +// conditioning allows": +// +// small: a and b log-uniform in [0.01, 1], x uniform in (0, 1): the series, summed compensated +// cf: a log-uniform in [1, 15], b log-uniform in [1, 40], x within 10% of the mean a / (a + b): the +// continued fraction, evaluated from the tail, in place of a sidestep to the series +// mean: a and b log-uniform in [15, 100], x within 5% of the mean: the power terms in the prefix +// +// Promotion is disabled so that each type is timed in its own arithmetic: by default, +// float is evaluated in double, and double in long double where that is wider. +// + +#include +#include +#include +#include +#include +#include + +using no_promotion = boost::math::policies::policy, boost::math::policies::promote_double>; + +template +std::vector> arguments(double a_min, double a_max, double b_min, double b_max, double mean_jitter) +{ + std::mt19937_64 mt {42}; + std::uniform_real_distribution u(0, 1); + std::vector> v(1024); + for (auto& t : v) + { + double a = a_min * std::pow(a_max / a_min, u(mt)); + double b = b_min * std::pow(b_max / b_min, u(mt)); + double x = mean_jitter > 0 ? a / (a + b) * (1 + mean_jitter * (2 * u(mt) - 1)) : u(mt); + t = std::make_tuple(static_cast(a), static_cast(b), static_cast(x)); + } + return v; +} + +template +void ibeta_small(benchmark::State& state) +{ + auto v = arguments(0.01, 1, 0.01, 1, 0); + std::size_t i = 0; + for (auto _ : state) + { + auto const & t = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::ibeta(std::get<0>(t), std::get<1>(t), std::get<2>(t), no_promotion())); + } +} + +template +void ibetac_small(benchmark::State& state) +{ + auto v = arguments(0.01, 1, 0.01, 1, 0); + std::size_t i = 0; + for (auto _ : state) + { + auto const & t = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::ibetac(std::get<0>(t), std::get<1>(t), std::get<2>(t), no_promotion())); + } +} + +template +void ibeta_cf(benchmark::State& state) +{ + auto v = arguments(1, 15, 1, 40, 0.1); + std::size_t i = 0; + for (auto _ : state) + { + auto const & t = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::ibeta(std::get<0>(t), std::get<1>(t), std::get<2>(t), no_promotion())); + } +} + +template +void ibeta_mean(benchmark::State& state) +{ + auto v = arguments(15, 100, 15, 100, 0.05); + std::size_t i = 0; + for (auto _ : state) + { + auto const & t = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::ibeta(std::get<0>(t), std::get<1>(t), std::get<2>(t), no_promotion())); + } +} + +template +void ibeta_invb_small(benchmark::State& state) +{ + // b is found from a, x and p = ibeta(a, b, x) for b in (0.01, 1): + auto v = arguments(0.01, 1, 0.01, 1, 0); + for (auto& t : v) + std::get<1>(t) = boost::math::ibeta(std::get<0>(t), std::get<1>(t), std::get<2>(t), no_promotion()); + std::size_t i = 0; + for (auto _ : state) + { + auto const & t = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::ibeta_invb(std::get<0>(t), std::get<2>(t), std::get<1>(t), no_promotion())); + } +} + +BENCHMARK_TEMPLATE(ibeta_small, float); +BENCHMARK_TEMPLATE(ibeta_small, double); +BENCHMARK_TEMPLATE(ibetac_small, double); +BENCHMARK_TEMPLATE(ibeta_cf, float); +BENCHMARK_TEMPLATE(ibeta_cf, double); +BENCHMARK_TEMPLATE(ibeta_mean, double); +BENCHMARK_TEMPLATE(ibeta_invb_small, double); + +BENCHMARK_MAIN(); diff --git a/reporting/performance/jacobi_theta_performance.cpp b/reporting/performance/jacobi_theta_performance.cpp index a1eea6ad0f..71aecd8e3f 100644 --- a/reporting/performance/jacobi_theta_performance.cpp +++ b/reporting/performance/jacobi_theta_performance.cpp @@ -6,13 +6,17 @@ #include #include #include +#ifdef BOOST_HAS_FLOAT128 #include +#endif #include #include using boost::multiprecision::number; using boost::multiprecision::mpfr_float_backend; +#ifdef BOOST_HAS_FLOAT128 using boost::multiprecision::float128; +#endif using boost::multiprecision::cpp_bin_float_50; using boost::multiprecision::cpp_bin_float_100; using boost::math::jacobi_theta1; @@ -37,7 +41,9 @@ void JacobiTheta1(benchmark::State& state) BENCHMARK_TEMPLATE(JacobiTheta1, float); BENCHMARK_TEMPLATE(JacobiTheta1, double); BENCHMARK_TEMPLATE(JacobiTheta1, long double); +#ifdef BOOST_HAS_FLOAT128 BENCHMARK_TEMPLATE(JacobiTheta1, float128); +#endif BENCHMARK_TEMPLATE(JacobiTheta1, number>); BENCHMARK_TEMPLATE(JacobiTheta1, number>); BENCHMARK_TEMPLATE(JacobiTheta1, number>); @@ -65,7 +71,9 @@ void JacobiTheta1Tau(benchmark::State& state) BENCHMARK_TEMPLATE(JacobiTheta1Tau, float); BENCHMARK_TEMPLATE(JacobiTheta1Tau, double); BENCHMARK_TEMPLATE(JacobiTheta1Tau, long double); +#ifdef BOOST_HAS_FLOAT128 BENCHMARK_TEMPLATE(JacobiTheta1Tau, float128); +#endif BENCHMARK_TEMPLATE(JacobiTheta1Tau, number>); BENCHMARK_TEMPLATE(JacobiTheta1Tau, number>); BENCHMARK_TEMPLATE(JacobiTheta1Tau, number>); @@ -74,4 +82,50 @@ BENCHMARK_TEMPLATE(JacobiTheta1Tau, number>); BENCHMARK_TEMPLATE(JacobiTheta1Tau, cpp_bin_float_50); BENCHMARK_TEMPLATE(JacobiTheta1Tau, cpp_bin_float_100); +// The evaluation regimes, as (z, tau) pairs: the double-sided Gaussian sums +// used for tau < 1 and z != 0, the single-sided transformed series used for +// tau < 1 and z == 0, and the direct Fourier series used for tau >= 1. The +// argument index selects the pair. +static const double jacobi_theta_regimes[][2] = { + { 0.5, 0.3 }, // Gaussian sums + { 0.3, 0.05 }, // Gaussian sums, small tau + { 0.0, 0.3 }, // z == 0 shortcut + { 0.5, 3.0 }, // direct series + { 0.0, 5.0 }, // direct series, one or two terms +}; + +struct theta1tau { template Real operator()(Real z, Real tau) const { return boost::math::jacobi_theta1tau(z, tau); } }; +struct theta2tau { template Real operator()(Real z, Real tau) const { return boost::math::jacobi_theta2tau(z, tau); } }; +struct theta3tau { template Real operator()(Real z, Real tau) const { return boost::math::jacobi_theta3tau(z, tau); } }; +struct theta4tau { template Real operator()(Real z, Real tau) const { return boost::math::jacobi_theta4tau(z, tau); } }; +struct theta4m1tau { template Real operator()(Real z, Real tau) const { return boost::math::jacobi_theta4m1tau(z, tau); } }; +// theta4(z, q) with q = exp(-pi tau), i.e. the q parameterization of the same point +struct theta4q { template Real operator()(Real z, Real tau) const { return boost::math::jacobi_theta4(z, exp(-boost::math::constants::pi() * tau)); } }; + +template +void JacobiThetaRegime(benchmark::State& state) +{ + const double* regime = jacobi_theta_regimes[state.range(0)]; + Real z = static_cast(regime[0]); + Real tau = static_cast(regime[1]); + F f; + for (auto _ : state) + { + benchmark::DoNotOptimize(f(z, tau)); + tau += std::numeric_limits::epsilon(); + } +} + +#define JACOBI_THETA_REGIMES(F, Real) BENCHMARK_TEMPLATE(JacobiThetaRegime, Real, F)->DenseRange(0, 4) + +JACOBI_THETA_REGIMES(theta1tau, float); +JACOBI_THETA_REGIMES(theta1tau, double); +JACOBI_THETA_REGIMES(theta2tau, double); +JACOBI_THETA_REGIMES(theta3tau, double); +JACOBI_THETA_REGIMES(theta4tau, float); +JACOBI_THETA_REGIMES(theta4tau, double); +JACOBI_THETA_REGIMES(theta4m1tau, double); +JACOBI_THETA_REGIMES(theta4q, double); +JACOBI_THETA_REGIMES(theta4tau, cpp_bin_float_50); + BENCHMARK_MAIN(); diff --git a/reporting/performance/lbeta_performance.cpp b/reporting/performance/lbeta_performance.cpp new file mode 100644 index 0000000000..d17da2dc17 --- /dev/null +++ b/reporting/performance/lbeta_performance.cpp @@ -0,0 +1,86 @@ +// (C) Copyright Nick Thompson 2026. +// 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) + +// +// Compares lbeta(a, b) with the two obvious alternatives, log(beta(a, b)) and +// lgamma(a) + lgamma(b) - lgamma(a + b), with a and b log-uniform in [1e-3, 1e6]: +// the range where neither alternative fails outright for most pairs. +// +// Promotion is disabled so that each type is timed in its own arithmetic: by default, +// float is evaluated in double, and double in long double where that is wider. +// + +#include +#include +#include +#include +#include +#include +#include + +using no_promotion = boost::math::policies::policy, boost::math::policies::promote_double>; + +template +std::vector> arguments() +{ + std::mt19937_64 mt {42}; + std::uniform_real_distribution dist(-3, 6); + std::vector> v(1024); + for (auto& p : v) + { + p = {static_cast(std::pow(10.0, dist(mt))), static_cast(std::pow(10.0, dist(mt)))}; + } + return v; +} + +template +void lbeta_performance(benchmark::State& state) +{ + auto v = arguments(); + std::size_t i = 0; + for (auto _ : state) + { + auto const & p = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::lbeta(p.first, p.second, no_promotion())); + } +} + +template +void log_beta_performance(benchmark::State& state) +{ + using std::log; + auto v = arguments(); + std::size_t i = 0; + for (auto _ : state) + { + auto const & p = v[i++ & 1023]; + benchmark::DoNotOptimize(log(boost::math::beta(p.first, p.second, no_promotion()))); + } +} + +template +void lgamma_sum_performance(benchmark::State& state) +{ + using boost::math::lgamma; + auto v = arguments(); + std::size_t i = 0; + for (auto _ : state) + { + auto const & p = v[i++ & 1023]; + benchmark::DoNotOptimize(lgamma(p.first, no_promotion()) + lgamma(p.second, no_promotion()) - lgamma(p.first + p.second, no_promotion())); + } +} + +BENCHMARK_TEMPLATE(lbeta_performance, float); +BENCHMARK_TEMPLATE(lbeta_performance, double); +BENCHMARK_TEMPLATE(lbeta_performance, long double); +BENCHMARK_TEMPLATE(log_beta_performance, float); +BENCHMARK_TEMPLATE(log_beta_performance, double); +BENCHMARK_TEMPLATE(log_beta_performance, long double); +BENCHMARK_TEMPLATE(lgamma_sum_performance, float); +BENCHMARK_TEMPLATE(lgamma_sum_performance, double); +BENCHMARK_TEMPLATE(lgamma_sum_performance, long double); + +BENCHMARK_MAIN(); diff --git a/reporting/performance/libeta_performance.cpp b/reporting/performance/libeta_performance.cpp new file mode 100644 index 0000000000..376fa267a5 --- /dev/null +++ b/reporting/performance/libeta_performance.cpp @@ -0,0 +1,100 @@ +// (C) Copyright Nick Thompson 2026. +// 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) + +// +// Compares libeta(a, b, x) with log(ibeta(a, b, x)) where both are finite: a and b log-uniform +// in [0.5, 1000], x uniform in (0, 1). Then times libeta alone in the left tail of large a = b, +// where ibeta underflows and log(ibeta) is -infinity. +// +// Promotion is disabled so that each type is timed in its own arithmetic: by default, +// float is evaluated in double, and double in long double where that is wider. +// + +#include +#include +#include +#include +#include +#include + +using no_promotion = boost::math::policies::policy, boost::math::policies::promote_double>; + +template +std::vector> ordinary_arguments() +{ + std::mt19937_64 mt {42}; + std::uniform_real_distribution log_ab(std::log10(0.5), 3); + std::uniform_real_distribution unit(0, 1); + std::vector> v(1024); + for (auto& t : v) + { + t = {static_cast(std::pow(10.0, log_ab(mt))), static_cast(std::pow(10.0, log_ab(mt))), static_cast(unit(mt))}; + } + return v; +} + +template +std::vector> underflow_arguments() +{ + std::mt19937_64 mt {42}; + std::uniform_real_distribution log_a(4, 5); + std::uniform_real_distribution fraction(0.05, 0.4); + std::vector> v(1024); + for (auto& t : v) + { + Real a = static_cast(std::pow(10.0, log_a(mt))); + t = {a, a, static_cast(fraction(mt))}; + } + return v; +} + +template +void libeta_performance(benchmark::State& state) +{ + auto v = ordinary_arguments(); + std::size_t i = 0; + for (auto _ : state) + { + auto const & t = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::libeta(std::get<0>(t), std::get<1>(t), std::get<2>(t), no_promotion())); + } +} + +template +void log_ibeta_performance(benchmark::State& state) +{ + using std::log; + auto v = ordinary_arguments(); + std::size_t i = 0; + for (auto _ : state) + { + auto const & t = v[i++ & 1023]; + benchmark::DoNotOptimize(log(boost::math::ibeta(std::get<0>(t), std::get<1>(t), std::get<2>(t), no_promotion()))); + } +} + +template +void libeta_underflow_performance(benchmark::State& state) +{ + auto v = underflow_arguments(); + std::size_t i = 0; + for (auto _ : state) + { + auto const & t = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::libeta(std::get<0>(t), std::get<1>(t), std::get<2>(t), no_promotion())); + } +} + +BENCHMARK_TEMPLATE(libeta_performance, float); +BENCHMARK_TEMPLATE(libeta_performance, double); +BENCHMARK_TEMPLATE(libeta_performance, long double); +BENCHMARK_TEMPLATE(log_ibeta_performance, float); +BENCHMARK_TEMPLATE(log_ibeta_performance, double); +BENCHMARK_TEMPLATE(log_ibeta_performance, long double); +BENCHMARK_TEMPLATE(libeta_underflow_performance, float); +BENCHMARK_TEMPLATE(libeta_underflow_performance, double); +BENCHMARK_TEMPLATE(libeta_underflow_performance, long double); + +BENCHMARK_MAIN(); diff --git a/reporting/performance/ligamma_performance.cpp b/reporting/performance/ligamma_performance.cpp new file mode 100644 index 0000000000..a332a0214b --- /dev/null +++ b/reporting/performance/ligamma_performance.cpp @@ -0,0 +1,97 @@ +// (C) Copyright Nick Thompson 2026. +// 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) + +// +// Compares ligamma(a, x) with log(tgamma(a, x)) where both are finite, even in float: a log-uniform in [0.5, 30], +// x/a log-uniform in [0.1, 10]. Then, for a log-uniform in [1e3, 1e5], where tgamma(a, x) overflows, +// compares ligamma with lgamma(a) + lgamma_q(a, x). +// +// Promotion is disabled so that each type is timed in its own arithmetic: by default, +// float is evaluated in double, and double in long double where that is wider. +// + +#include +#include +#include +#include +#include +#include + +using no_promotion = boost::math::policies::policy, boost::math::policies::promote_double>; + +template +std::vector> arguments(double log_a_min, double log_a_max) +{ + std::mt19937_64 mt {42}; + std::uniform_real_distribution log_a(log_a_min, log_a_max); + std::uniform_real_distribution log_ratio(-1, 1); + std::vector> v(1024); + for (auto& p : v) + { + double a = std::pow(10.0, log_a(mt)); + p = {static_cast(a), static_cast(a * std::pow(10.0, log_ratio(mt)))}; + } + return v; +} + +template +void ligamma_performance(benchmark::State& state) +{ + auto v = arguments(std::log10(0.5), std::log10(30.0)); + std::size_t i = 0; + for (auto _ : state) + { + auto const & p = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::ligamma(p.first, p.second, no_promotion())); + } +} + +template +void log_tgamma_performance(benchmark::State& state) +{ + using std::log; + auto v = arguments(std::log10(0.5), std::log10(30.0)); + std::size_t i = 0; + for (auto _ : state) + { + auto const & p = v[i++ & 1023]; + benchmark::DoNotOptimize(log(boost::math::tgamma(p.first, p.second, no_promotion()))); + } +} + +template +void ligamma_large_a_performance(benchmark::State& state) +{ + auto v = arguments(3, 5); + std::size_t i = 0; + for (auto _ : state) + { + auto const & p = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::ligamma(p.first, p.second, no_promotion())); + } +} + +template +void lgamma_plus_lgamma_q_large_a_performance(benchmark::State& state) +{ + auto v = arguments(3, 5); + std::size_t i = 0; + for (auto _ : state) + { + auto const & p = v[i++ & 1023]; + benchmark::DoNotOptimize(boost::math::lgamma(p.first, no_promotion()) + boost::math::lgamma_q(p.first, p.second, no_promotion())); + } +} + +BENCHMARK_TEMPLATE(ligamma_performance, float); +BENCHMARK_TEMPLATE(ligamma_performance, double); +BENCHMARK_TEMPLATE(ligamma_performance, long double); +BENCHMARK_TEMPLATE(log_tgamma_performance, float); +BENCHMARK_TEMPLATE(log_tgamma_performance, double); +BENCHMARK_TEMPLATE(log_tgamma_performance, long double); +BENCHMARK_TEMPLATE(ligamma_large_a_performance, double); +BENCHMARK_TEMPLATE(lgamma_plus_lgamma_q_large_a_performance, double); + +BENCHMARK_MAIN(); diff --git a/reporting/performance/pow1p_performance.cpp b/reporting/performance/pow1p_performance.cpp new file mode 100644 index 0000000000..e01b1ab90e --- /dev/null +++ b/reporting/performance/pow1p_performance.cpp @@ -0,0 +1,93 @@ +// (C) Copyright Nick Thompson 2026. +// 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) + +#include +#include +#include +#include +#include +#include +#ifdef BOOST_HAS_FLOAT128 +#include +#endif +#include + +#ifdef BOOST_HAS_FLOAT128 +using boost::multiprecision::float128; +#endif +using boost::multiprecision::cpp_bin_float_50; + +// Moderate arguments: x in (-1/2, 1/2), y in (-50, 50). +template +std::vector> moderate_arguments() +{ + std::mt19937_64 mt(12345); + std::uniform_real_distribution ux(-0.5, 0.5); + std::uniform_real_distribution uy(-50, 50); + std::vector> v(1024); + for (auto& p : v) + { + p = {static_cast(ux(mt)), static_cast(uy(mt))}; + } + return v; +} + +// Tiny x and huge y with y*x of order 10: 1+x is inexact, so pow1p takes its double-T branch. +template +std::vector> tiny_x_arguments() +{ + std::mt19937_64 mt(12345); + std::uniform_real_distribution ue(-18, -8); + std::uniform_real_distribution uw(-10, 10); + std::vector> v(1024); + for (auto& p : v) + { + double x = std::pow(10.0, ue(mt)); + p = {static_cast(x), static_cast(uw(mt) / x)}; + } + return v; +} + +template +void Pow1p(benchmark::State& state) +{ + auto v = state.range(0) ? tiny_x_arguments() : moderate_arguments(); + std::size_t i = 0; + for (auto _ : state) + { + benchmark::DoNotOptimize(boost::math::pow1p(v[i].first, v[i].second)); + i = (i + 1) & 1023; + } +} + +// The naive, inaccurate evaluation, for comparison. +template +void PowOnePlusX(benchmark::State& state) +{ + using std::pow; + auto v = state.range(0) ? tiny_x_arguments() : moderate_arguments(); + std::size_t i = 0; + for (auto _ : state) + { + benchmark::DoNotOptimize(Real(pow(Real(1 + v[i].first), v[i].second))); + i = (i + 1) & 1023; + } +} + +// Argument 0: moderate x and y. Argument 1: tiny x, huge y. +BENCHMARK_TEMPLATE(Pow1p, float)->Arg(0)->Arg(1); +BENCHMARK_TEMPLATE(PowOnePlusX, float)->Arg(0)->Arg(1); +BENCHMARK_TEMPLATE(Pow1p, double)->Arg(0)->Arg(1); +BENCHMARK_TEMPLATE(PowOnePlusX, double)->Arg(0)->Arg(1); +BENCHMARK_TEMPLATE(Pow1p, long double)->Arg(0)->Arg(1); +BENCHMARK_TEMPLATE(PowOnePlusX, long double)->Arg(0)->Arg(1); +#ifdef BOOST_HAS_FLOAT128 +BENCHMARK_TEMPLATE(Pow1p, float128)->Arg(0)->Arg(1); +BENCHMARK_TEMPLATE(PowOnePlusX, float128)->Arg(0)->Arg(1); +#endif +BENCHMARK_TEMPLATE(Pow1p, cpp_bin_float_50)->Arg(0)->Arg(1); +BENCHMARK_TEMPLATE(PowOnePlusX, cpp_bin_float_50)->Arg(0)->Arg(1); + +BENCHMARK_MAIN(); diff --git a/reporting/performance/prime_sieve_performance.cpp b/reporting/performance/prime_sieve_performance.cpp new file mode 100644 index 0000000000..31d29087a1 --- /dev/null +++ b/reporting/performance/prime_sieve_performance.cpp @@ -0,0 +1,134 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Benchmarks of boost::math::prime_sieve / prime_count against primesieve +// (https://github.com/kimwalisch/primesieve). Built by hand, for example: +// +// clang++ -std=c++17 -O3 -march=native -DNDEBUG -DBOOST_MATH_STANDALONE -fexperimental-library \ +// -I/libs/math/include -I/include -I/opt/homebrew/include \ +// prime_sieve_performance.cpp /build/libprimesieve.a \ +// -L/opt/homebrew/lib -lbenchmark -lpthread -o prime_sieve_performance +// +// Define BOOST_MATH_BENCH_NO_PRIMESIEVE to build without the reference library. + +#include +#include +#ifndef BOOST_MATH_BENCH_NO_PRIMESIEVE +#include +#endif +#include +#include +#include + +namespace bm = boost::math; + +#ifdef BOOST_MATH_PRIME_SIEVE_HAS_STD_EXECUTION +// Policies are not default constructible in every standard library, so select them by tag +template +constexpr decltype(auto) policy() +{ + if constexpr (Parallel) + { + return (std::execution::par); + } + else + { + return (std::execution::seq); + } +} + +template +void count_ours(benchmark::State& state) +{ + const std::uint64_t n {static_cast(state.range(0))}; + for (auto _ : state) + { + benchmark::DoNotOptimize(bm::prime_count(policy(), n)); + } + state.SetItemsProcessed(static_cast(state.iterations()) * static_cast(n)); +} + +template +void generate_ours(benchmark::State& state) +{ + const std::uint64_t n {static_cast(state.range(0))}; + std::vector primes; + bm::prime_reserve(n, primes); + for (auto _ : state) + { + primes.clear(); + bm::prime_sieve(policy(), n, primes); + benchmark::DoNotOptimize(primes.data()); + } + state.SetItemsProcessed(static_cast(state.iterations()) * static_cast(n)); +} + +template +void window_ours(benchmark::State& state) +{ + const std::uint64_t lo {static_cast(state.range(0))}; + const std::uint64_t width {static_cast(state.range(1))}; + for (auto _ : state) + { + benchmark::DoNotOptimize(bm::prime_count(policy(), lo, lo + width)); + } +} +#endif + +#ifndef BOOST_MATH_BENCH_NO_PRIMESIEVE +void count_primesieve(benchmark::State& state) +{ + const std::uint64_t n {static_cast(state.range(0))}; + // range(1) == 0 means all hardware threads + const int threads {state.range(1) == 0 ? static_cast(std::thread::hardware_concurrency()) : static_cast(state.range(1))}; + primesieve::set_num_threads(threads); + for (auto _ : state) + { + benchmark::DoNotOptimize(primesieve::count_primes(0, n)); + } + state.SetItemsProcessed(static_cast(state.iterations()) * static_cast(n)); +} + +void generate_primesieve(benchmark::State& state) +{ + const std::uint64_t n {static_cast(state.range(0))}; + std::vector primes; + for (auto _ : state) + { + primes.clear(); + primesieve::generate_primes(n, &primes); + benchmark::DoNotOptimize(primes.data()); + } + state.SetItemsProcessed(static_cast(state.iterations()) * static_cast(n)); +} + +void window_primesieve(benchmark::State& state) +{ + const std::uint64_t lo {static_cast(state.range(0))}; + const std::uint64_t width {static_cast(state.range(1))}; + primesieve::set_num_threads(1); + for (auto _ : state) + { + benchmark::DoNotOptimize(primesieve::count_primes(lo, lo + width - 1)); + } +} +#endif + +#ifdef BOOST_MATH_PRIME_SIEVE_HAS_STD_EXECUTION +BENCHMARK_TEMPLATE(count_ours, false)->RangeMultiplier(10)->Range(100000000, 100000000000)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(count_ours, true)->RangeMultiplier(10)->Range(100000000, 100000000000)->Unit(benchmark::kMillisecond)->UseRealTime(); +BENCHMARK_TEMPLATE(generate_ours, false)->RangeMultiplier(10)->Range(100000000, 10000000000)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(generate_ours, true)->RangeMultiplier(10)->Range(100000000, 10000000000)->Unit(benchmark::kMillisecond)->UseRealTime(); +BENCHMARK_TEMPLATE(window_ours, false)->Args({1000000000000, 1000000000})->Args({1000000000000000, 1000000000})->Args({1000000000000000000, 1000000000})->Unit(benchmark::kMillisecond); +#endif + +#ifndef BOOST_MATH_BENCH_NO_PRIMESIEVE +BENCHMARK(count_primesieve)->ArgsProduct({{100000000, 1000000000, 10000000000, 100000000000}, {1}})->Unit(benchmark::kMillisecond); +BENCHMARK(count_primesieve)->ArgsProduct({{100000000, 1000000000, 10000000000, 100000000000}, {0}})->Unit(benchmark::kMillisecond)->UseRealTime(); +BENCHMARK(generate_primesieve)->RangeMultiplier(10)->Range(100000000, 10000000000)->Unit(benchmark::kMillisecond); +BENCHMARK(window_primesieve)->Args({1000000000000, 1000000000})->Args({1000000000000000, 1000000000})->Args({1000000000000000000, 1000000000})->Unit(benchmark::kMillisecond); +#endif + +BENCHMARK_MAIN(); diff --git a/reporting/performance/van_den_bos_unit_square_performance.cpp b/reporting/performance/van_den_bos_unit_square_performance.cpp new file mode 100644 index 0000000000..be57eaef1d --- /dev/null +++ b/reporting/performance/van_den_bos_unit_square_performance.cpp @@ -0,0 +1,110 @@ +// Copyright Nicholas Thompson 2026. +// 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) + +/* + * Google Benchmark suite for van_den_bos_unit_square integrands. + * + * Example: + * c++ -O3 -DNDEBUG -std=c++17 -Iinclude \ + * reporting/performance/van_den_bos_unit_square_performance.cpp \ + * -lbenchmark -lpthread -o vdb_bench + */ + +#include +#include + +#include +#include +#include + +namespace { + +using boost::math::quadrature::van_den_bos_unit_square; + +template +void benchmark_integrand(benchmark::State& state, F const& f, double tol) +{ + for (auto _ : state) + { + const auto value = van_den_bos_unit_square(f, tol); + benchmark::DoNotOptimize(value); + } +} + +static void BM_quadratic(benchmark::State& state) +{ + benchmark_integrand( + state, + [](double x, double y) + { + return x * x + y * y + x * y; + }, + 1e-12); +} +BENCHMARK(BM_quadratic); + +static void BM_exp_x_plus_y(benchmark::State& state) +{ + benchmark_integrand( + state, + [](double x, double y) + { + return std::exp(x + y); + }, + 1e-10); +} +BENCHMARK(BM_exp_x_plus_y); + +static void BM_exp_xy(benchmark::State& state) +{ + benchmark_integrand( + state, + [](double x, double y) + { + return std::exp(x * y); + }, + 1e-10); +} +BENCHMARK(BM_exp_xy); + +static void BM_one_over_1_plus_x_plus_y(benchmark::State& state) +{ + benchmark_integrand( + state, + [](double x, double y) + { + return 1.0 / (1.0 + x + y); + }, + 1e-10); +} +BENCHMARK(BM_one_over_1_plus_x_plus_y); + +static void BM_cos_5xy(benchmark::State& state) +{ + benchmark_integrand( + state, + [](double x, double y) + { + return std::cos(5.0 * x * y); + }, + 1e-8); +} +BENCHMARK(BM_cos_5xy); + +static void BM_complex_exp_5ixy(benchmark::State& state) +{ + benchmark_integrand( + state, + [](double x, double y) + { + return std::exp(std::complex(0, 5 * x * y)); + }, + 1e-8); +} +BENCHMARK(BM_complex_exp_5ixy); + +} // namespace + +BENCHMARK_MAIN(); diff --git a/src/tr1/c_policy.hpp b/src/tr1/c_policy.hpp index cf1951334e..6f8c798238 100644 --- a/src/tr1/c_policy.hpp +++ b/src/tr1/c_policy.hpp @@ -6,7 +6,7 @@ #include #include -namespace boost{ namespace math{ namespace policies{ +BOOST_MATH_NAMESPACE_BEGIN namespace policies{ template <> struct policy< @@ -106,17 +106,17 @@ struct normalise, pole_error typedef policy, pole_error, overflow_error, evaluation_error, rounding_error, detail::forwarding_arg1, detail::forwarding_arg2> type; }; -}}} // namespaces +} BOOST_MATH_NAMESPACE_END namespace c_policies{ -using boost::math::policies::policy; -using boost::math::policies::errno_on_error; -using boost::math::policies::domain_error; -using boost::math::policies::pole_error; -using boost::math::policies::overflow_error; -using boost::math::policies::rounding_error; -using boost::math::policies::evaluation_error; +using BOOST_MATH_NAMESPACE::policies::policy; +using BOOST_MATH_NAMESPACE::policies::errno_on_error; +using BOOST_MATH_NAMESPACE::policies::domain_error; +using BOOST_MATH_NAMESPACE::policies::pole_error; +using BOOST_MATH_NAMESPACE::policies::overflow_error; +using BOOST_MATH_NAMESPACE::policies::rounding_error; +using BOOST_MATH_NAMESPACE::policies::evaluation_error; typedef policy< domain_error, diff --git a/src/tr1/copysign.cpp b/src/tr1/copysign.cpp index 6d57dc84de..751e61e96f 100644 --- a/src/tr1/copysign.cpp +++ b/src/tr1/copysign.cpp @@ -13,7 +13,7 @@ extern "C" double BOOST_MATH_TR1_DECL boost_copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) BOOST_MATH_C99_THROW_SPEC { - return boost::math::copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); + return BOOST_MATH_NAMESPACE::copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } diff --git a/src/tr1/copysignf.cpp b/src/tr1/copysignf.cpp index 4e791f25e5..9478de0332 100644 --- a/src/tr1/copysignf.cpp +++ b/src/tr1/copysignf.cpp @@ -13,7 +13,7 @@ extern "C" float BOOST_MATH_TR1_DECL boost_copysignf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) BOOST_MATH_C99_THROW_SPEC { - return boost::math::copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); + return BOOST_MATH_NAMESPACE::copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } diff --git a/src/tr1/copysignl.cpp b/src/tr1/copysignl.cpp index d7b394087b..61e5d7b4a7 100644 --- a/src/tr1/copysignl.cpp +++ b/src/tr1/copysignl.cpp @@ -13,7 +13,7 @@ extern "C" long double BOOST_MATH_TR1_DECL boost_copysignl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) BOOST_MATH_C99_THROW_SPEC { - return boost::math::copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); + return BOOST_MATH_NAMESPACE::copysign BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } diff --git a/src/tr1/fmax.cpp b/src/tr1/fmax.cpp index 23f44606e7..917a5b257e 100644 --- a/src/tr1/fmax.cpp +++ b/src/tr1/fmax.cpp @@ -13,9 +13,9 @@ extern "C" double BOOST_MATH_TR1_DECL boost_fmax BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) BOOST_MATH_C99_THROW_SPEC { - if((boost::math::isnan)(x)) + if((BOOST_MATH_NAMESPACE::isnan)(x)) return y; - if((boost::math::isnan)(y)) + if((BOOST_MATH_NAMESPACE::isnan)(y)) return x; return (std::max)(x, y); } diff --git a/src/tr1/fmaxf.cpp b/src/tr1/fmaxf.cpp index 8ce6b822a3..152a9978b9 100644 --- a/src/tr1/fmaxf.cpp +++ b/src/tr1/fmaxf.cpp @@ -13,9 +13,9 @@ extern "C" float BOOST_MATH_TR1_DECL boost_fmaxf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) BOOST_MATH_C99_THROW_SPEC { - if((boost::math::isnan)(x)) + if((BOOST_MATH_NAMESPACE::isnan)(x)) return y; - if((boost::math::isnan)(y)) + if((BOOST_MATH_NAMESPACE::isnan)(y)) return x; return (std::max)(x, y); } diff --git a/src/tr1/fmaxl.cpp b/src/tr1/fmaxl.cpp index 29d917eaae..835c71aad8 100644 --- a/src/tr1/fmaxl.cpp +++ b/src/tr1/fmaxl.cpp @@ -13,9 +13,9 @@ extern "C" long double BOOST_MATH_TR1_DECL boost_fmaxl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) BOOST_MATH_C99_THROW_SPEC { - if((boost::math::isnan)(x)) + if((BOOST_MATH_NAMESPACE::isnan)(x)) return y; - if((boost::math::isnan)(y)) + if((BOOST_MATH_NAMESPACE::isnan)(y)) return x; return (std::max)(x, y); } diff --git a/src/tr1/fmin.cpp b/src/tr1/fmin.cpp index c5d1d0a0be..793b6a46b8 100644 --- a/src/tr1/fmin.cpp +++ b/src/tr1/fmin.cpp @@ -13,9 +13,9 @@ extern "C" double BOOST_MATH_TR1_DECL boost_fmin BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) BOOST_MATH_C99_THROW_SPEC { - if((boost::math::isnan)(x)) + if((BOOST_MATH_NAMESPACE::isnan)(x)) return y; - if((boost::math::isnan)(y)) + if((BOOST_MATH_NAMESPACE::isnan)(y)) return x; return (std::min)(x, y); } diff --git a/src/tr1/fminf.cpp b/src/tr1/fminf.cpp index 2af7662c55..07dcf45088 100644 --- a/src/tr1/fminf.cpp +++ b/src/tr1/fminf.cpp @@ -13,9 +13,9 @@ extern "C" float BOOST_MATH_TR1_DECL boost_fminf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) BOOST_MATH_C99_THROW_SPEC { - if((boost::math::isnan)(x)) + if((BOOST_MATH_NAMESPACE::isnan)(x)) return y; - if((boost::math::isnan)(y)) + if((BOOST_MATH_NAMESPACE::isnan)(y)) return x; return (std::min)(x, y); } diff --git a/src/tr1/fminl.cpp b/src/tr1/fminl.cpp index bdf6654e83..fd03e47938 100644 --- a/src/tr1/fminl.cpp +++ b/src/tr1/fminl.cpp @@ -13,9 +13,9 @@ extern "C" long double BOOST_MATH_TR1_DECL boost_fminl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) BOOST_MATH_C99_THROW_SPEC { - if((boost::math::isnan)(x)) + if((BOOST_MATH_NAMESPACE::isnan)(x)) return y; - if((boost::math::isnan)(y)) + if((BOOST_MATH_NAMESPACE::isnan)(y)) return x; return (std::min)(x, y); } diff --git a/src/tr1/fpclassify.cpp b/src/tr1/fpclassify.cpp index 4ede398e07..04187c82f6 100644 --- a/src/tr1/fpclassify.cpp +++ b/src/tr1/fpclassify.cpp @@ -17,39 +17,39 @@ # pragma warning (disable: 4800) // 'int' : forcing value to bool 'true' or 'false' (performance warning) #endif -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ template<> bool BOOST_MATH_TR1_DECL signbit BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) { - return static_cast((boost::math::signbit)(x)); + return static_cast((BOOST_MATH_NAMESPACE::signbit)(x)); } template<> int BOOST_MATH_TR1_DECL fpclassify BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) { - return (boost::math::fpclassify)(x); + return (BOOST_MATH_NAMESPACE::fpclassify)(x); } template<> bool BOOST_MATH_TR1_DECL isfinite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) { - return (boost::math::isfinite)(x); + return (BOOST_MATH_NAMESPACE::isfinite)(x); } template<> bool BOOST_MATH_TR1_DECL isinf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) { - return (boost::math::isinf)(x); + return (BOOST_MATH_NAMESPACE::isinf)(x); } template<> bool BOOST_MATH_TR1_DECL isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) { - return (boost::math::isnan)(x); + return (BOOST_MATH_NAMESPACE::isnan)(x); } template<> bool BOOST_MATH_TR1_DECL isnormal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) { - return (boost::math::isnormal)(x); + return (BOOST_MATH_NAMESPACE::isnormal)(x); } -}}} // namespace boost{ namespace math{ namespace tr1{ +} BOOST_MATH_NAMESPACE_END // namespace boost{ namespace math{ namespace tr1{ #if defined (_MSC_VER) # pragma warning(pop) diff --git a/src/tr1/fpclassifyf.cpp b/src/tr1/fpclassifyf.cpp index c5ed4ebde0..e618fe0ce4 100644 --- a/src/tr1/fpclassifyf.cpp +++ b/src/tr1/fpclassifyf.cpp @@ -17,39 +17,39 @@ # pragma warning (disable: 4800) // 'int' : forcing value to bool 'true' or 'false' (performance warning) #endif -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ template<> bool BOOST_MATH_TR1_DECL signbit BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) { - return static_cast((boost::math::signbit)(x)); + return static_cast((BOOST_MATH_NAMESPACE::signbit)(x)); } template<> int BOOST_MATH_TR1_DECL fpclassify BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) { - return (boost::math::fpclassify)(x); + return (BOOST_MATH_NAMESPACE::fpclassify)(x); } template<> bool BOOST_MATH_TR1_DECL isfinite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) { - return (boost::math::isfinite)(x); + return (BOOST_MATH_NAMESPACE::isfinite)(x); } template<> bool BOOST_MATH_TR1_DECL isinf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) { - return (boost::math::isinf)(x); + return (BOOST_MATH_NAMESPACE::isinf)(x); } template<> bool BOOST_MATH_TR1_DECL isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) { - return (boost::math::isnan)(x); + return (BOOST_MATH_NAMESPACE::isnan)(x); } template<> bool BOOST_MATH_TR1_DECL isnormal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) { - return (boost::math::isnormal)(x); + return (BOOST_MATH_NAMESPACE::isnormal)(x); } -}}} // namespace boost{ namespace math{ namespace tr1{ +} BOOST_MATH_NAMESPACE_END // namespace boost{ namespace math{ namespace tr1{ #if defined (_MSC_VER) # pragma warning(pop) diff --git a/src/tr1/fpclassifyl.cpp b/src/tr1/fpclassifyl.cpp index b42ac5a331..d1d4a01e3d 100644 --- a/src/tr1/fpclassifyl.cpp +++ b/src/tr1/fpclassifyl.cpp @@ -17,39 +17,39 @@ # pragma warning (disable: 4800) // 'int' : forcing value to bool 'true' or 'false' (performance warning) #endif -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ template<> bool BOOST_MATH_TR1_DECL signbit BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) { - return static_cast((boost::math::signbit)(x)); + return static_cast((BOOST_MATH_NAMESPACE::signbit)(x)); } template<> int BOOST_MATH_TR1_DECL fpclassify BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) { - return (boost::math::fpclassify)(x); + return (BOOST_MATH_NAMESPACE::fpclassify)(x); } template<> bool BOOST_MATH_TR1_DECL isfinite BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) { - return (boost::math::isfinite)(x); + return (BOOST_MATH_NAMESPACE::isfinite)(x); } template<> bool BOOST_MATH_TR1_DECL isinf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) { - return (boost::math::isinf)(x); + return (BOOST_MATH_NAMESPACE::isinf)(x); } template<> bool BOOST_MATH_TR1_DECL isnan BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) { - return (boost::math::isnan)(x); + return (BOOST_MATH_NAMESPACE::isnan)(x); } template<> bool BOOST_MATH_TR1_DECL isnormal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) { - return (boost::math::isnormal)(x); + return (BOOST_MATH_NAMESPACE::isnormal)(x); } -}}} // namespace boost{ namespace math{ namespace tr1{ +} BOOST_MATH_NAMESPACE_END // namespace boost{ namespace math{ namespace tr1{ #if defined (_MSC_VER) # pragma warning(pop) diff --git a/src/tr1/hypot.cpp b/src/tr1/hypot.cpp index 4ef879e6bb..41f7e4d92e 100644 --- a/src/tr1/hypot.cpp +++ b/src/tr1/hypot.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" double BOOST_MATH_TR1_DECL boost_hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) BOOST_MATH_C99_THROW_SPEC { return c_policies::hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/hypotf.cpp b/src/tr1/hypotf.cpp index b19e44fb79..9080d6e84e 100644 --- a/src/tr1/hypotf.cpp +++ b/src/tr1/hypotf.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" float BOOST_MATH_TR1_DECL boost_hypotf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) BOOST_MATH_C99_THROW_SPEC { return c_policies::hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/hypotl.cpp b/src/tr1/hypotl.cpp index 03a96e65d7..f71936a7b5 100644 --- a/src/tr1/hypotl.cpp +++ b/src/tr1/hypotl.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long double BOOST_MATH_TR1_DECL boost_hypotl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) BOOST_MATH_C99_THROW_SPEC { return c_policies::hypot BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/lgamma.cpp b/src/tr1/lgamma.cpp index ceed6d949d..353a1f7404 100644 --- a/src/tr1/lgamma.cpp +++ b/src/tr1/lgamma.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" double BOOST_MATH_TR1_DECL boost_lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/lgammaf.cpp b/src/tr1/lgammaf.cpp index 596512d0e7..eb2832320f 100644 --- a/src/tr1/lgammaf.cpp +++ b/src/tr1/lgammaf.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" float BOOST_MATH_TR1_DECL boost_lgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) BOOST_MATH_C99_THROW_SPEC { return c_policies::lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/lgammal.cpp b/src/tr1/lgammal.cpp index 00b2d23425..8a415cc24f 100644 --- a/src/tr1/lgammal.cpp +++ b/src/tr1/lgammal.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long double BOOST_MATH_TR1_DECL boost_lgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::lgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/llround.cpp b/src/tr1/llround.cpp index 1835c34cc9..f90140e791 100644 --- a/src/tr1/llround.cpp +++ b/src/tr1/llround.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long long BOOST_MATH_TR1_DECL boost_llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/llroundf.cpp b/src/tr1/llroundf.cpp index 0a00a2f091..9aa273e5ef 100644 --- a/src/tr1/llroundf.cpp +++ b/src/tr1/llroundf.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long long BOOST_MATH_TR1_DECL boost_llroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) BOOST_MATH_C99_THROW_SPEC { return c_policies::llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/llroundl.cpp b/src/tr1/llroundl.cpp index 4c1756ba02..a91b7fdec2 100644 --- a/src/tr1/llroundl.cpp +++ b/src/tr1/llroundl.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long long BOOST_MATH_TR1_DECL boost_llroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::llround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/log1p.cpp b/src/tr1/log1p.cpp index 34701366ab..81cc866928 100644 --- a/src/tr1/log1p.cpp +++ b/src/tr1/log1p.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" double BOOST_MATH_TR1_DECL boost_log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/log1pf.cpp b/src/tr1/log1pf.cpp index 0550081a96..1287dd8b6c 100644 --- a/src/tr1/log1pf.cpp +++ b/src/tr1/log1pf.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" float BOOST_MATH_TR1_DECL boost_log1pf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) BOOST_MATH_C99_THROW_SPEC { return c_policies::log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/log1pl.cpp b/src/tr1/log1pl.cpp index 6346c0cabc..59b5357fdd 100644 --- a/src/tr1/log1pl.cpp +++ b/src/tr1/log1pl.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long double BOOST_MATH_TR1_DECL boost_log1pl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::log1p BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/lround.cpp b/src/tr1/lround.cpp index f813713006..5616cb2eb2 100644 --- a/src/tr1/lround.cpp +++ b/src/tr1/lround.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long BOOST_MATH_TR1_DECL boost_lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/lroundf.cpp b/src/tr1/lroundf.cpp index 4fc093db9f..bf563221ea 100644 --- a/src/tr1/lroundf.cpp +++ b/src/tr1/lroundf.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long BOOST_MATH_TR1_DECL boost_lroundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) BOOST_MATH_C99_THROW_SPEC { return c_policies::lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/lroundl.cpp b/src/tr1/lroundl.cpp index ea0f29a5ff..aa46a1e723 100644 --- a/src/tr1/lroundl.cpp +++ b/src/tr1/lroundl.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long BOOST_MATH_TR1_DECL boost_lroundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::lround BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/nextafter.cpp b/src/tr1/nextafter.cpp index d62a7be73e..c5bc1edb8c 100644 --- a/src/tr1/nextafter.cpp +++ b/src/tr1/nextafter.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" double BOOST_MATH_TR1_DECL boost_nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, double y) BOOST_MATH_C99_THROW_SPEC { return c_policies::nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/nextafterf.cpp b/src/tr1/nextafterf.cpp index 5364b4d45c..014e4ecaab 100644 --- a/src/tr1/nextafterf.cpp +++ b/src/tr1/nextafterf.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" float BOOST_MATH_TR1_DECL boost_nextafterf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, float y) BOOST_MATH_C99_THROW_SPEC { return c_policies::nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/nextafterl.cpp b/src/tr1/nextafterl.cpp index 28f0515318..5551880618 100644 --- a/src/tr1/nextafterl.cpp +++ b/src/tr1/nextafterl.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long double BOOST_MATH_TR1_DECL boost_nextafterl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) BOOST_MATH_C99_THROW_SPEC { return c_policies::nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/nexttoward.cpp b/src/tr1/nexttoward.cpp index 8b347e5ff4..873712eae3 100644 --- a/src/tr1/nexttoward.cpp +++ b/src/tr1/nexttoward.cpp @@ -11,7 +11,7 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" double BOOST_MATH_TR1_DECL boost_nexttoward BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x, long double y) BOOST_MATH_C99_THROW_SPEC { @@ -22,6 +22,6 @@ extern "C" double BOOST_MATH_TR1_DECL boost_nexttoward BOOST_MATH_PREVENT_MACRO_ #endif } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/nexttowardf.cpp b/src/tr1/nexttowardf.cpp index c356094545..394b6044d0 100644 --- a/src/tr1/nexttowardf.cpp +++ b/src/tr1/nexttowardf.cpp @@ -11,7 +11,7 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" float BOOST_MATH_TR1_DECL boost_nexttowardf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x, long double y) BOOST_MATH_C99_THROW_SPEC { @@ -22,6 +22,6 @@ extern "C" float BOOST_MATH_TR1_DECL boost_nexttowardf BOOST_MATH_PREVENT_MACRO_ #endif } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/nexttowardl.cpp b/src/tr1/nexttowardl.cpp index e39580f847..ed377d0829 100644 --- a/src/tr1/nexttowardl.cpp +++ b/src/tr1/nexttowardl.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long double BOOST_MATH_TR1_DECL boost_nexttowardl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x, long double y) BOOST_MATH_C99_THROW_SPEC { return c_policies::nextafter BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x, y); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/round.cpp b/src/tr1/round.cpp index 584b651be3..72783c1cc2 100644 --- a/src/tr1/round.cpp +++ b/src/tr1/round.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" double BOOST_MATH_TR1_DECL boost_round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/roundf.cpp b/src/tr1/roundf.cpp index f68249454c..121ec732c7 100644 --- a/src/tr1/roundf.cpp +++ b/src/tr1/roundf.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" float BOOST_MATH_TR1_DECL boost_roundf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) BOOST_MATH_C99_THROW_SPEC { return c_policies::round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/roundl.cpp b/src/tr1/roundl.cpp index df45571e6c..21eacee33b 100644 --- a/src/tr1/roundl.cpp +++ b/src/tr1/roundl.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long double BOOST_MATH_TR1_DECL boost_roundl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::round BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/tgamma.cpp b/src/tr1/tgamma.cpp index 7268151a0f..1fb09e250d 100644 --- a/src/tr1/tgamma.cpp +++ b/src/tr1/tgamma.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" double BOOST_MATH_TR1_DECL boost_tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/tgammaf.cpp b/src/tr1/tgammaf.cpp index 8dc26797b2..d66830a7d6 100644 --- a/src/tr1/tgammaf.cpp +++ b/src/tr1/tgammaf.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" float BOOST_MATH_TR1_DECL boost_tgammaf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) BOOST_MATH_C99_THROW_SPEC { return c_policies::tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/tgammal.cpp b/src/tr1/tgammal.cpp index aa090b5178..2c925eae01 100644 --- a/src/tr1/tgammal.cpp +++ b/src/tr1/tgammal.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long double BOOST_MATH_TR1_DECL boost_tgammal BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::tgamma BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/trunc.cpp b/src/tr1/trunc.cpp index ec1619d58b..e32f8ec8a7 100644 --- a/src/tr1/trunc.cpp +++ b/src/tr1/trunc.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" double BOOST_MATH_TR1_DECL boost_trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/truncf.cpp b/src/tr1/truncf.cpp index ffb5aa09c0..b9bbb378b3 100644 --- a/src/tr1/truncf.cpp +++ b/src/tr1/truncf.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" float BOOST_MATH_TR1_DECL boost_truncf BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(float x) BOOST_MATH_C99_THROW_SPEC { return c_policies::trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/src/tr1/truncl.cpp b/src/tr1/truncl.cpp index 9182a322b6..3eaef68eb5 100644 --- a/src/tr1/truncl.cpp +++ b/src/tr1/truncl.cpp @@ -11,13 +11,13 @@ #include #include "c_policy.hpp" -namespace boost{ namespace math{ namespace tr1{ +BOOST_MATH_NAMESPACE_BEGIN namespace tr1{ extern "C" long double BOOST_MATH_TR1_DECL boost_truncl BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(long double x) BOOST_MATH_C99_THROW_SPEC { return c_policies::trunc BOOST_MATH_PREVENT_MACRO_SUBSTITUTION(x); } -}}} +} BOOST_MATH_NAMESPACE_END diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9d673adc7d..f03362f7a9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -38,12 +38,24 @@ if(HAVE_BOOST_TEST) message(STATUS "Building boost.math with SYCL") + # icpx defaults to -fp-model=fast, which flushes denormals to zero and reassociates arithmetic, + # defeating the error-free transforms and compensated sums the library relies on; test as + # the other compilers do (contraction stays on). + set(CMAKE_CXX_COMPILER "icpx") set(CMAKE_C_COMPILER "icx") enable_testing() - boost_test_jamfile(FILE sycl_jamfile LINK_LIBRARIES Boost::math Boost::assert Boost::concept_check Boost::config Boost::core Boost::integer Boost::lexical_cast Boost::multiprecision Boost::predef Boost::random Boost::throw_exception Boost::unit_test_framework sycl COMPILE_DEFINITIONS BOOST_MATH_ENABLE_SYCL=1 COMPILE_OPTIONS -fsycl ) + boost_test_jamfile(FILE sycl_jamfile LINK_LIBRARIES Boost::math Boost::assert Boost::concept_check Boost::config Boost::core Boost::integer Boost::lexical_cast Boost::multiprecision Boost::predef Boost::random Boost::throw_exception Boost::unit_test_framework sycl COMPILE_DEFINITIONS BOOST_MATH_ENABLE_SYCL=1 COMPILE_OPTIONS -fsycl -fp-model=precise ) + elseif (BOOST_MATH_BUILD_MODULE) + + message(STATUS "Building boost.math as a C++20 module") + + enable_testing() + + add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../module" module) + else() boost_test(SOURCES check_cmake_version.cpp ARGUMENTS ${PROJECT_VERSION} LINK_LIBRARIES Boost::core Boost::config) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 18d5d9ae01..aec73a5d77 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -144,49 +144,50 @@ test-suite special_fun : [ run test_pFq.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_hdr_initializer_list cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_smart_ptr ] TEST=5 release clang:-Wno-literal-range : test_pFq_real_concept ] - [ run hypot_test.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] - [ run pow_test.cpp /boost/test//boost_unit_test_framework ] - [ run logaddexp_test.cpp /boost/test//boost_unit_test_framework ] - [ run logsumexp_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_hdr_initializer_list cxx11_variadic_templates ] ] - [ run ccmath_sqrt_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_isinf_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_isnan_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_abs_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_isfinite_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_isnormal_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_fpclassify_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_frexp_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_ldexp_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_div_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_logb_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_ilogb_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_scalbn_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_scalbln_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_floor_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_ceil_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_trunc_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_modf_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_round_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_fmod_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_remainder_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_copysign_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_hypot_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_fdim_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_fmax_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_fmin_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_isgreater_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_isgreaterequal_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_isless_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_islessequal_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_isunordered_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_next_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_fma_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run ccmath_signbit_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] - [ run log1p_expm1_test.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] - [ run log1p_expm1_extra_test.cpp pch_light /boost/test//boost_unit_test_framework : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] ] - [ run log1p_expm1_stdfloat_test.cpp pch_light /boost/test//boost_unit_test_framework ] + [ run test_hypot.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] + [ run test_pow.cpp /boost/test//boost_unit_test_framework ] + [ run test_pow1p.cpp ] + [ run test_logaddexp.cpp /boost/test//boost_unit_test_framework ] + [ run test_logsumexp.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_hdr_initializer_list cxx11_variadic_templates ] ] + [ run test_ccmath_sqrt.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_isinf.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_isnan.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_abs.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_isfinite.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_isnormal.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_fpclassify.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_frexp.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_ldexp.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_div.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_logb.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_ilogb.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_scalbn.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_scalbln.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_floor.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_ceil.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_trunc.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_modf.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_round.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_fmod.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_remainder.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_copysign.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_hypot.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_fdim.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_fmax.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_fmin.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_isgreater.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_isgreaterequal.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_isless.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_islessequal.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_isunordered.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_next.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_fma.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_ccmath_signbit.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] $(float128_type) ] + [ run test_log1p_expm1.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] + [ run test_log1p_expm1_extra.cpp pch_light /boost/test//boost_unit_test_framework : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] ] + [ run test_log1p_expm1_stdfloat.cpp pch_light /boost/test//boost_unit_test_framework ] [ run test_log1p_simple.cpp ] - [ run powm1_sqrtp1m1_test.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] + [ run test_powm1_sqrtp1m1.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run git_issue_705.cpp /boost/test//boost_unit_test_framework ] [ run git_issue_810.cpp /boost/test//boost_unit_test_framework ] [ run git_issue_826.cpp /boost/test//boost_unit_test_framework ] @@ -204,7 +205,7 @@ test-suite special_fun : [ run git_issue_1308.cpp /boost/test//boost_unit_test_framework ] [ run git_issue_1412.cpp ] [ run git_issue_1412_pt_2.cpp ] - [ run special_functions_test.cpp /boost/test//boost_unit_test_framework ] + [ run test_special_functions.cpp /boost/test//boost_unit_test_framework ] [ run test_airy.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run test_bessel_j.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run test_bessel_y.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] @@ -214,8 +215,10 @@ test-suite special_fun : [ run test_bessel_y_prime.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run test_bessel_i_prime.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run test_bessel_k_prime.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] - [ run bessel_iterator_test.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] + [ run test_bessel_iterator.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run test_beta.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] + [ run test_lbeta.cpp ] + [ run test_libeta.cpp ] [ run test_bessel_airy_zeros.cpp /boost/test//boost_unit_test_framework ] [ run test_bernoulli_constants.cpp /boost/test//boost_unit_test_framework ] [ run test_binomial_coeff.cpp pch /boost/test//boost_unit_test_framework ] @@ -254,7 +257,7 @@ test-suite special_fun : [ run test_jacobi_zeta.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run test_heuman_lambda.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run test_erf.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] - [ run erf_limits_test.cpp ] + [ run test_erf_limits.cpp ] [ run test_expint.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run test_factorials.cpp pch /boost/test//boost_unit_test_framework ] [ run test_lanczos.cpp /boost/test//boost_unit_test_framework : : : $(float128_type) ] @@ -486,6 +489,7 @@ test-suite special_fun : intel:off : test_ibeta_inv_ab_real_concept3 ] [ run test_igamma.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] + [ run test_ligamma.cpp ] [ run test_igamma_inv.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework : # command line : # input files @@ -548,34 +552,36 @@ test-suite special_fun : [ run test_jacobi.cpp pch_light /boost/test//boost_unit_test_framework ] [ run test_laguerre.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] - [ run test_lambert_w.cpp /boost/test//boost_unit_test_framework ] - [ run test_lambert_w.cpp /boost/test//boost_unit_test_framework : : : BOOST_MATH_TEST_MULTIPRECISION=1 $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : test_lambert_w_multiprecision_1 ] - [ run test_lambert_w.cpp /boost/test//boost_unit_test_framework : : : BOOST_MATH_TEST_MULTIPRECISION=2 $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : test_lambert_w_multiprecision_2 ] - [ run test_lambert_w.cpp /boost/test//boost_unit_test_framework : : : BOOST_MATH_TEST_MULTIPRECISION=3 $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : test_lambert_w_multiprecision_3 ] - [ run test_lambert_w.cpp /boost/test//boost_unit_test_framework : : : BOOST_MATH_TEST_MULTIPRECISION=4 BOOST_MATH_TEST_FLOAT128 $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : test_lambert_w_multiprecision_4 ] - [ run test_lambert_w_integrals_float128.cpp /boost/test//boost_unit_test_framework : : : release [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" : no ] [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run test_lambert_w_integrals_quad.cpp /boost/test//boost_unit_test_framework : : : release [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run test_lambert_w_integrals_long_double.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] ] - [ run test_lambert_w_integrals_double.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] ] - [ run test_lambert_w_integrals_float.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] ] - [ run test_lambert_w_derivative.cpp /boost/test//boost_unit_test_framework : : : BOOST_MATH_TEST_MULTIPRECISION $(float128_type_gcc) ] + [ run test_lambert_w.cpp ] + [ run test_lambert_w.cpp : : : BOOST_MATH_TEST_MULTIPRECISION=1 $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : test_lambert_w_multiprecision_1 ] + [ run test_lambert_w.cpp : : : BOOST_MATH_TEST_MULTIPRECISION=2 $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : test_lambert_w_multiprecision_2 ] + [ run test_lambert_w.cpp : : : BOOST_MATH_TEST_MULTIPRECISION=3 $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : test_lambert_w_multiprecision_3 ] + [ run test_lambert_w.cpp : : : BOOST_MATH_TEST_MULTIPRECISION=4 BOOST_MATH_TEST_FLOAT128 $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : test_lambert_w_multiprecision_4 ] + [ run test_lambert_w_integrals_float128.cpp : : : release [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" : no ] [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run test_lambert_w_integrals_quad.cpp : : : release [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run test_lambert_w_integrals_long_double.cpp : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] ] + [ run test_lambert_w_integrals_double.cpp : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] ] + [ run test_lambert_w_integrals_float.cpp : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] ] + [ run test_lambert_w_derivative.cpp : : : BOOST_MATH_TEST_MULTIPRECISION $(float128_type_gcc) ] [ run test_legendre.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework : : : $(float128_type) ] - [ run chebyshev_test.cpp : : : [ requires cxx11_inline_namespaces cxx11_unified_initialization_syntax cxx11_hdr_tuple cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for cxx11_constexpr ] $(float128_type) ] - [ run chebyshev_transform_test.cpp ../config//fftw3f : : : TEST1 [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_fftw3 "libfftw3" : : no ] : chebyshev_transform_test_1 ] - [ run chebyshev_transform_test.cpp ../config//fftw3 : : : TEST2 [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_fftw3 "libfftw3" : : no ] : chebyshev_transform_test_2 ] - [ run chebyshev_transform_test.cpp ../config//fftw3l : : : TEST3 [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_fftw3 "libfftw3" : : no ] : chebyshev_transform_test_3 ] - [ run chebyshev_transform_test.cpp ../config//fftw3q ../config//quadmath : : : TEST4 [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_fftw3 "libfftw3" : : no ] [ check-target-builds ../config//has_float128 "__float128" : : no ] : chebyshev_transform_test_4 ] + [ run test_chebyshev.cpp : : : [ requires cxx11_inline_namespaces cxx11_unified_initialization_syntax cxx11_hdr_tuple cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for cxx11_constexpr ] $(float128_type) ] + [ run test_chebyshev_transform.cpp : : : TEST1 [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for ] : chebyshev_transform_test_1 ] + [ run test_chebyshev_transform.cpp : : : TEST2 [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for ] : chebyshev_transform_test_2 ] + [ run test_chebyshev_transform.cpp : : : TEST3 [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for ] : chebyshev_transform_test_3 ] + [ run test_chebyshev_transform.cpp ../config//quadmath : : : TEST4 [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_float128 "__float128" : : no ] : chebyshev_transform_test_4 ] + [ run test_chebyshev_transform.cpp : : : TEST5 [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_range_based_for ] : chebyshev_transform_test_5 ] - [ run cardinal_trigonometric_test.cpp ../config//fftw3f : : : TEST1 [ requires cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_fftw3 "libfftw3" : : no ] : cardinal_trigonometric_test_1 ] - [ run cardinal_trigonometric_test.cpp ../config//fftw3 : : : TEST2 [ requires cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_fftw3 "libfftw3" : : no ] : cardinal_trigonometric_test_2 ] - [ run cardinal_trigonometric_test.cpp ../config//fftw3l : : : TEST3 [ requires cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_fftw3 "libfftw3" : : no ] : cardinal_trigonometric_test_3 ] - [ run cardinal_trigonometric_test.cpp ../config//fftw3q ../config//quadmath : : : TEST4 [ requires cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_fftw3 "libfftw3" : : no ] [ check-target-builds ../config//has_float128 "__float128" : : no ] : cardinal_trigonometric_test_4 ] + [ run test_cardinal_trigonometric.cpp : : : TEST1 [ requires cxx11_auto_declarations cxx11_range_based_for ] : cardinal_trigonometric_test_1 ] + [ run test_cardinal_trigonometric.cpp : : : TEST2 [ requires cxx11_auto_declarations cxx11_range_based_for ] : cardinal_trigonometric_test_2 ] + [ run test_cardinal_trigonometric.cpp : : : TEST3 [ requires cxx11_auto_declarations cxx11_range_based_for ] : cardinal_trigonometric_test_3 ] + [ run test_cardinal_trigonometric.cpp ../config//quadmath : : : TEST4 [ requires cxx11_auto_declarations cxx11_range_based_for ] [ check-target-builds ../config//has_float128 "__float128" : : no ] : cardinal_trigonometric_test_4 ] + [ run test_cardinal_trigonometric.cpp : : : TEST5 [ requires cxx11_auto_declarations cxx11_range_based_for ] : cardinal_trigonometric_test_5 ] [ run test_ldouble_simple.cpp /boost/test//boost_unit_test_framework ] # Needs to run in release mode, as it's rather slow: - [ run test_next.cpp pch /boost/test//boost_unit_test_framework ] + [ run test_next.cpp pch /boost/test//boost_unit_test_framework : : : $(float128_type_gcc) ] [ run test_next_decimal.cpp pch /boost/test//boost_unit_test_framework : : : release ] [ run test_owens_t.cpp /boost/test//boost_unit_test_framework ] [ run test_polygamma.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] @@ -591,7 +597,7 @@ test-suite special_fun : [ run test_trig.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ] [ run test_zeta.cpp /boost/test//boost_unit_test_framework test_instances//test_instances pch_light ] [ run test_sinc.cpp /boost/test//boost_unit_test_framework pch_light ] - [ run test_fibonacci.cpp /boost/test//boost_unit_test_framework ] + [ run test_fibonacci.cpp ] [ run test_prime.cpp /boost/test//boost_unit_test_framework ] [ run test_logistic_sigmoid.cpp ] [ run test_logit.cpp ] @@ -599,10 +605,10 @@ test-suite special_fun : test-suite distribution_tests : [ run test_arcsine.cpp pch /boost/test//boost_unit_test_framework ] - [ run test_landau.cpp pch : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" ] ] - [ run test_saspoint5.cpp pch : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" ] ] - [ run test_holtsmark.cpp pch : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" ] ] - [ run test_mapairy.cpp pch : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" ] ] + [ run test_landau.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" ] ] + [ run test_saspoint5.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" ] ] + [ run test_holtsmark.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" ] ] + [ run test_mapairy.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" ] ] [ run test_bernoulli.cpp /boost/test//boost_unit_test_framework ] [ run test_beta_dist.cpp /boost/test//boost_unit_test_framework ] [ run test_binomial.cpp /boost/test//boost_unit_test_framework @@ -687,6 +693,7 @@ test-suite distribution_tests : [ run test_dist_overloads.cpp /boost/test//boost_unit_test_framework ] [ run test_exponential_dist.cpp /boost/test//boost_unit_test_framework ] [ run test_extreme_value.cpp /boost/test//boost_unit_test_framework ] + [ run test_generalized_extreme_value.cpp ] [ run test_find_location.cpp pch /boost/test//boost_unit_test_framework ] [ run test_find_scale.cpp pch /boost/test//boost_unit_test_framework ] [ run test_fisher_f.cpp /boost/test//boost_unit_test_framework ] @@ -742,29 +749,30 @@ test-suite distribution_tests : [ run test_laplace.cpp /boost/test//boost_unit_test_framework ] [ run test_inv_hyp.cpp pch /boost/test//boost_unit_test_framework ] [ run test_logistic_dist.cpp /boost/test//boost_unit_test_framework ] + [ run test_logcdf.cpp ] [ run test_lognormal.cpp /boost/test//boost_unit_test_framework ] - [ run test_negative_binomial.cpp /boost/test//boost_unit_test_framework + [ run test_negative_binomial.cpp : # command line : # input files : # requirements TEST_FLOAT intel:off : test_negative_binomial_float ] - [ run test_negative_binomial.cpp /boost/test//boost_unit_test_framework + [ run test_negative_binomial.cpp : # command line : # input files : # requirements TEST_DOUBLE intel:off : test_negative_binomial_double ] - [ run test_negative_binomial.cpp /boost/test//boost_unit_test_framework + [ run test_negative_binomial.cpp : # command line : # input files : # requirements TEST_LDOUBLE intel:off : test_negative_binomial_long_double ] - [ run test_negative_binomial.cpp /boost/test//boost_unit_test_framework + [ run test_negative_binomial.cpp : # command line : # input files : # requirements @@ -902,6 +910,7 @@ test-suite distribution_tests : [ run test_triangular.cpp pch /boost/test//boost_unit_test_framework ] [ run test_uniform.cpp pch /boost/test//boost_unit_test_framework ] [ run test_weibull.cpp /boost/test//boost_unit_test_framework ] + [ run test_von_mises.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : "-Bstatic -lquadmath -Bdynamic" ] ] [ run test_legacy_nonfinite.cpp /boost/test//boost_unit_test_framework ] [ run test_basic_nonfinite.cpp /boost/test//boost_unit_test_framework ] @@ -909,7 +918,7 @@ test-suite distribution_tests : [ run test_lexical_cast.cpp /boost/test//boost_unit_test_framework ] [ run test_nonfinite_trap.cpp /boost/test//boost_unit_test_framework : : : off:no ] [ run test_signed_zero.cpp /boost/test//boost_unit_test_framework ] - [ run complex_test.cpp /boost/test//boost_unit_test_framework ] + [ run test_complex.cpp /boost/test//boost_unit_test_framework ] [ compile test_dist_deduction_guides.cpp : [ requires cpp_deduction_guides cpp_variadic_templates ] ] [ run git_issue_800.cpp /boost/test//boost_unit_test_framework ] @@ -919,6 +928,8 @@ test-suite distribution_tests : [ run scipy_issue_15101.cpp /boost/test//boost_unit_test_framework ] [ run scipy_issue_17146.cpp /boost/test//boost_unit_test_framework ] [ run scipy_issue_17388.cpp /boost/test//boost_unit_test_framework ] + [ run git_issue_935.cpp ] + [ run git_issue_1203.cpp ] [ run scipy_issue_17916.cpp /boost/test//boost_unit_test_framework ] [ run scipy_issue_17916_nct.cpp /boost/test//boost_unit_test_framework ] [ run scipy_issue_18302.cpp /boost/test//boost_unit_test_framework ] @@ -938,9 +949,9 @@ test-suite new_floats : test-suite mp : [ run test_nc_t_quad.cpp pch /boost/test//boost_unit_test_framework : : : release gcc-mingw:-Wa,-mbig-obj off [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] ] - [ run test_polynomial.cpp /boost/test//boost_unit_test_framework : : : TEST1 : test_polynomial_1 ] - [ run test_polynomial.cpp /boost/test//boost_unit_test_framework : : : TEST2 : test_polynomial_2 ] - [ run test_polynomial.cpp /boost/test//boost_unit_test_framework : : : TEST3 : test_polynomial_3 ] + [ run test_polynomial.cpp : : : TEST1 : test_polynomial_1 ] + [ run test_polynomial.cpp : : : TEST2 : test_polynomial_2 ] + [ run test_polynomial.cpp : : : TEST3 : test_polynomial_3 ] [ run test_estrin.cpp ] [ run polynomial_concept_check.cpp ] @@ -949,7 +960,7 @@ test-suite mp : ; test-suite misc : - [ run header_deprecated_test.cpp ] + [ run test_header_deprecated.cpp ] [ run threading_sanity_check.cpp ] [ run test_tr1.cpp ../build//boost_math_tr1 @@ -992,15 +1003,15 @@ test-suite misc : test_tr1_c_long_double ] [ run test_constants.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run simple_continued_fraction_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run centered_continued_fraction_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run luroth_expansion_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run engel_expansion_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run test_classify.cpp pch /boost/test//boost_unit_test_framework : : : msvc:/bigobj ] + [ run test_simple_continued_fraction.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_centered_continued_fraction.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_luroth_expansion.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_engel_expansion.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_classify.cpp : : : msvc:/bigobj ] [ run test_error_handling.cpp /boost/test//boost_unit_test_framework ] - [ run legendre_stieltjes_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_auto_declarations cxx11_range_based_for ] $(float128_type) ] + [ run test_legendre_stieltjes.cpp : : : [ requires cxx11_auto_declarations cxx11_range_based_for ] $(float128_type) ] [ run test_minima.cpp pch /boost/test//boost_unit_test_framework ] - [ run test_rationals.cpp /boost/test//boost_unit_test_framework + [ run test_rationals.cpp test_rational_instances/test_rational_double1.cpp test_rational_instances/test_rational_double2.cpp test_rational_instances/test_rational_double3.cpp @@ -1030,6 +1041,7 @@ test-suite misc : [ run test_policy_7.cpp /boost/test//boost_unit_test_framework ] [ run test_policy_8.cpp /boost/test//boost_unit_test_framework ] [ compile test_policy_9.cpp ] + [ compile test_policy_9.cpp : BOOST_MATH_PROMOTE_FLOAT_POLICY=false BOOST_MATH_PROMOTE_DOUBLE_POLICY=false : test_policy_9_no_promotion ] [ run test_policy_10.cpp /boost/test//boost_unit_test_framework ] [ run test_policy_sf.cpp /boost/test//boost_unit_test_framework ] [ run test_long_double_support.cpp /boost/test//boost_unit_test_framework @@ -1039,940 +1051,551 @@ test-suite misc : [ run test_recurrence.cpp : : : TEST=3 release $(float128_type) [ requires cxx11_unified_initialization_syntax cxx11_hdr_tuple cxx11_auto_declarations cxx11_decltype ] : test_recurrence_3 ] [ run test_print_info_on_type.cpp ] - [ run univariate_statistics_test.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run univariate_statistics_backwards_compatible_test.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_hdr_forward_list cxx11_hdr_atomic cxx11_hdr_thread cxx11_hdr_tuple cxx11_hdr_future cxx11_sfinae_expr ] ] - [ run ooura_fourier_integral_test.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] $(float128_type) [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run empirical_cumulative_distribution_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run norms_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run signal_statistics_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run anderson_darling_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run ljung_box_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run cubic_roots_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run quartic_roots_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_univariate_statistics.cpp /boost/test//boost_unit_test_framework + : : : + gcc,windows:-Wa,-mbig-obj + off + msvc:/bigobj + [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] + [ requires cxx17_if_constexpr cxx17_std_apply ] + ] + [ run test_univariate_statistics_backwards_compatible.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_hdr_forward_list cxx11_hdr_atomic cxx11_hdr_thread cxx11_hdr_tuple cxx11_hdr_future cxx11_sfinae_expr ] ] + [ run test_ooura_fourier_integral.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] $(float128_type) [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_prime_sieve.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_prime_sieve_mp.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_prime_sieve_mp.cpp ../tools//gmp : : : BOOST_MATH_TEST_GMP [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//has_gmp : : no ] : test_prime_sieve_gmp ] + [ run test_empirical_cumulative_distribution.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_norms.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_signal_statistics.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_anderson_darling.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_ljung_box.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_cubic_roots.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_quartic_roots.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_fft.cpp : : : $(float128_type) ] + [ run test_polynomial_roots.cpp : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_range_based_for ] ] [ run test_t_test.cpp : : : $(float128_type) [ requires cxx11_hdr_forward_list cxx11_hdr_atomic cxx11_hdr_thread cxx11_hdr_tuple cxx11_hdr_future cxx11_sfinae_expr ] ] [ run test_z_test.cpp : : : $(float128_type) [ requires cxx11_hdr_forward_list cxx11_hdr_atomic cxx11_hdr_thread cxx11_hdr_tuple cxx11_hdr_future cxx11_sfinae_expr ] ] - [ run bivariate_statistics_test.cpp : : : [ requires cxx11_hdr_forward_list cxx11_hdr_atomic cxx11_hdr_thread cxx11_hdr_tuple cxx11_hdr_future cxx11_sfinae_expr ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] - [ run linear_regression_test.cpp : : : [ requires cxx11_hdr_forward_list cxx11_hdr_atomic cxx11_hdr_thread cxx11_hdr_tuple cxx11_hdr_future cxx11_sfinae_expr ] ] + [ run test_bivariate_statistics.cpp + : : : + gcc,windows:-Wa,-mbig-obj + off + msvc:/bigobj + [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] + [ requires cxx17_if_constexpr cxx17_std_apply ] + ] + [ run test_linear_regression.cpp : : : [ requires cxx11_hdr_forward_list cxx11_hdr_atomic cxx11_hdr_thread cxx11_hdr_tuple cxx11_hdr_future cxx11_sfinae_expr ] ] [ run test_runs_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] [ run test_chatterjee_correlation.cpp /boost/test//boost_unit_test_framework ] [ run test_rank.cpp /boost/test//boost_unit_test_framework ] - [ run lanczos_smoothing_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run condition_number_test.cpp /boost/test//boost_unit_test_framework : : : TEST=1 msvc:/bigobj $(float128_type) : condition_number_test_1 ] - [ run condition_number_test.cpp /boost/test//boost_unit_test_framework : : : TEST=2 msvc:/bigobj $(float128_type) : condition_number_test_2 ] - [ run condition_number_test.cpp /boost/test//boost_unit_test_framework : : : TEST=3 msvc:/bigobj $(float128_type) : condition_number_test_3 ] + [ run test_lanczos_smoothing.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_condition_number.cpp /boost/test//boost_unit_test_framework : : : TEST=1 msvc:/bigobj $(float128_type) : condition_number_test_1 ] + [ run test_condition_number.cpp /boost/test//boost_unit_test_framework : : : TEST=2 msvc:/bigobj $(float128_type) : condition_number_test_2 ] + [ run test_condition_number.cpp /boost/test//boost_unit_test_framework : : : TEST=3 msvc:/bigobj $(float128_type) : condition_number_test_3 ] + [ run test_ulps_plot.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] [ run test_real_concept.cpp /boost/test//boost_unit_test_framework ] + [ run test_real_concept_neg_bin.cpp ] + [ run test_math_fwd.cpp ] [ run test_remez.cpp pch /boost/test//boost_unit_test_framework ] [ run test_roots.cpp pch /boost/test//boost_unit_test_framework ] [ run test_root_iterations.cpp pch /boost/test//boost_unit_test_framework : : : [ requires cxx11_hdr_tuple ] ] [ run test_root_finding_concepts.cpp /boost/test//boost_unit_test_framework ] [ run test_toms748_solve.cpp pch /boost/test//boost_unit_test_framework ] - [ run compile_test/interpolators_cubic_spline_incl_test.cpp compile_test_main : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/interpolators_barycentric_rational_incl_test.cpp compile_test_main : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run octonion_test.cpp + [ run compile_test/test_interpolators_cubic_spline_incl.cpp compile_test_main : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_interpolators_barycentric_rational_incl.cpp compile_test_main : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run test_octonion.cpp /boost/test//boost_unit_test_framework ] [ run octonion_test_simple.cpp ] - [ run quaternion_constexpr_test.cpp ] - [ run quaternion_test.cpp + [ run test_quaternion_constexpr.cpp ] + [ run test_quaternion.cpp /boost/test//boost_unit_test_framework : : : msvc-14.0:off $(float128_type) ] - [ run quaternion_mult_incl_test.cpp + [ run test_quaternion_mult_incl.cpp quaternion_mi1.cpp quaternion_mi2.cpp /boost/test//boost_unit_test_framework ] [ run test_ulp.cpp /boost/test//boost_unit_test_framework ] + [ run git_issue_1419.cpp ] + [ compile-fail git_issue_1421.cpp ] # [ run __temporary_test.cpp test_instances//test_instances : : : always_show_run_output off ] ; test-suite interpolators : - [ run test_barycentric_rational.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_unified_initialization_syntax ] $(float128_type) ] - [ run test_vector_barycentric_rational.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_unified_initialization_syntax ] [ check-target-builds ../../multiprecision/config//has_eigen : : no ] ] - [ run cardinal_cubic_b_spline_test.cpp /boost/test//boost_unit_test_framework : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions ] off msvc:/bigobj release ] - [ run cardinal_b_spline_test.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] $(float128_type) ] - [ run jacobi_test.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] $(float128_type) ] - [ run gegenbauer_test.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] $(float128_type) ] - [ run daubechies_scaling_test.cpp /boost/hana//boost_hana : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] - [ run daubechies_wavelet_test.cpp /boost/hana//boost_hana : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] - [ run fourier_transform_daubechies_test.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] - [ run wavelet_transform_test.cpp /boost/hana//boost_hana : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run agm_test.cpp : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run rsqrt_test.cpp : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run cohen_acceleration_test.cpp : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ compile compile_test/filters_daubechies_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ compile compile_test/sf_daubechies_scaling_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run whittaker_shannon_test.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] ] - [ run cardinal_quadratic_b_spline_test.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] ] - [ run cardinal_quintic_b_spline_test.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] $(float128_type) ] - [ run makima_test.cpp /boost/circular_buffer//boost_circular_buffer : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run pchip_test.cpp /boost/circular_buffer//boost_circular_buffer : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run septic_hermite_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run quintic_hermite_test.cpp /boost/circular_buffer//boost_circular_buffer : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run cubic_hermite_test.cpp /boost/circular_buffer//boost_circular_buffer : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run bilinear_uniform_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run bezier_polynomial_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] - [ run catmull_rom_test.cpp /boost/test//boost_unit_test_framework : : : TEST=1 [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] : catmull_rom_test_1 ] - [ run catmull_rom_test.cpp /boost/test//boost_unit_test_framework : : : TEST=2 [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] : catmull_rom_test_2 ] - [ run catmull_rom_test.cpp /boost/test//boost_unit_test_framework : : : TEST=3 [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] : catmull_rom_test_3 ] - [ run compile_test/interpolators_catmull_rom_incl_test.cpp compile_test_main : : : [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] ] - [ run compile_test/interpolators_catmull_rom_concept_test.cpp compile_test_main : : : [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] ] + [ run test_barycentric_rational.cpp : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_unified_initialization_syntax ] $(float128_type) ] + [ run test_vector_barycentric_rational.cpp : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations cxx11_unified_initialization_syntax ] [ check-target-builds ../../multiprecision/config//has_eigen : : no ] ] + [ run test_cardinal_cubic_b_spline.cpp : : : [ requires cxx11_smart_ptr cxx11_defaulted_functions ] off msvc:/bigobj release ] + [ run test_cardinal_b_spline.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] $(float128_type) ] + [ run test_jacobi_polynomial.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] $(float128_type) ] + [ run test_gegenbauer.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] $(float128_type) ] + [ run test_daubechies_scaling.cpp /boost/hana//boost_hana : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] + [ run test_daubechies_wavelet.cpp /boost/hana//boost_hana : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] + [ run test_fourier_transform_daubechies.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] ] + [ run test_wavelet_transform.cpp /boost/hana//boost_hana : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run test_agm.cpp : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_rsqrt.cpp : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_cohen_acceleration.cpp : : : msvc:/bigobj [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ compile compile_test/test_filters_daubechies_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ compile compile_test/test_sf_daubechies_scaling_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_whittaker_shannon.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] $(float128_type) ] + [ run test_cardinal_quadratic_b_spline.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] ] + [ run test_cardinal_quintic_b_spline.cpp : : : [ requires cxx11_auto_declarations cxx11_constexpr cxx11_smart_ptr cxx11_defaulted_functions ] $(float128_type) ] + [ run test_makima.cpp /boost/circular_buffer//boost_circular_buffer : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_pchip.cpp /boost/circular_buffer//boost_circular_buffer : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_septic_hermite.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_quintic_hermite.cpp /boost/circular_buffer//boost_circular_buffer : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_cubic_hermite.cpp /boost/circular_buffer//boost_circular_buffer : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_bilinear_uniform.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_bezier_polynomial.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) ] + [ run test_catmull_rom.cpp : : : TEST=1 [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] : catmull_rom_test_1 ] + [ run test_catmull_rom.cpp : : : TEST=2 [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] : catmull_rom_test_2 ] + [ run test_catmull_rom.cpp : : : TEST=3 [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] : catmull_rom_test_3 ] + [ run compile_test/test_interpolators_catmull_rom_incl.cpp compile_test_main : : : [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] ] + [ run compile_test/test_interpolators_catmull_rom_concept.cpp compile_test_main : : : [ requires cxx11_hdr_array cxx11_hdr_initializer_list ] ] [ run test_standalone_asserts.cpp ] - [ run differential_evolution_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run jso_test.cpp : : : clang:-fno-fast-math gcc:-fno-fast-math msvc:/fp:precise [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run random_search_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ run cma_es_test.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../../multiprecision/config//has_eigen : : no ] ] - [ compile compile_test/random_search_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ compile compile_test/differential_evolution_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] - [ compile compile_test/jso_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_differential_evolution.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_jso.cpp : : : clang:-fno-fast-math gcc:-fno-fast-math msvc:"/fp:precise" [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_random_search.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ run test_cma_es.cpp : : : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../../multiprecision/config//has_eigen : : no ] ] + [ compile compile_test/test_random_search_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ compile compile_test/test_differential_evolution_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] + [ compile compile_test/test_jso_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] ] ; test-suite quadrature : - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : msvc:/bigobj TEST1 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] : tanh_sinh_quadrature_test_1 ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : msvc:/bigobj TEST1A $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] : tanh_sinh_quadrature_test_1a ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : release msvc:/bigobj TEST1B $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] : tanh_sinh_quadrature_test_1b ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : msvc:/bigobj TEST2 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] : tanh_sinh_quadrature_test_2 ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : release msvc:/bigobj TEST2A $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] : tanh_sinh_quadrature_test_2a ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : msvc:/bigobj TEST3 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : tanh_sinh_quadrature_test_3 ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : release msvc:/bigobj TEST3A $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : tanh_sinh_quadrature_test_3a ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : release msvc:/bigobj TEST4 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : tanh_sinh_quadrature_test_4 ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : release msvc:/bigobj TEST5 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : tanh_sinh_quadrature_test_5 ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : msvc:/bigobj TEST6 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : tanh_sinh_quadrature_test_6 ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : release msvc:/bigobj TEST6A $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : tanh_sinh_quadrature_test_6a ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : release msvc:/bigobj TEST7 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : tanh_sinh_quadrature_test_7 ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : release msvc:/bigobj TEST8 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : tanh_sinh_quadrature_test_8 ] - [ run tanh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_tanh_sinh_quadrature.cpp : : : release msvc:/bigobj TEST9 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : tanh_sinh_quadrature_test_9 ] [ run tanh_sinh_mpfr.cpp ../tools//mpfr ../tools//gmp : : : [ check-target-builds ../config//has_mpfr : : no ] [ check-target-builds ../config//has_gmp : : no ] [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_hdr_initializer_list cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_smart_ptr ] release clang:-Wno-literal-range [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run sinh_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_sinh_sinh_quadrature.cpp : : : release $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : TEST1 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] : exp_sinh_quadrature_test_1 ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : release TEST2 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] : exp_sinh_quadrature_test_2 ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : TEST3 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : exp_sinh_quadrature_test_3 ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : release TEST4 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : exp_sinh_quadrature_test_4 ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : release TEST5 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : exp_sinh_quadrature_test_5 ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : release TEST6 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : exp_sinh_quadrature_test_6 ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : release TEST7 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : exp_sinh_quadrature_test_7 ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : release TEST8 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : exp_sinh_quadrature_test_8 ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : release TEST9 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : exp_sinh_quadrature_test_9 ] - [ run exp_sinh_quadrature_test.cpp /boost/test//boost_unit_test_framework + [ run test_exp_sinh_quadrature.cpp : : : release TEST10 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : exp_sinh_quadrature_test_10 ] - [ run gauss_quadrature_test.cpp : : : TEST1 $(float128_type) + [ run test_double_exponential_eigen.cpp : : : + [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax ] + [ check-target-builds ../../multiprecision/config//has_eigen : : no ] ] + [ run test_gauss_kronrod_eigen.cpp : : : + [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax ] + [ check-target-builds ../../multiprecision/config//has_eigen : : no ] ] + [ run test_gauss_quadrature_eigen.cpp : : : + [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax ] + [ check-target-builds ../../multiprecision/config//has_eigen : : no ] ] + [ run test_gauss_quadrature.cpp : : : TEST1 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release : gauss_quadrature_test_1 ] - [ run gauss_quadrature_test.cpp : : : TEST2 $(float128_type) + [ run test_gauss_quadrature.cpp : : : TEST2 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : gauss_quadrature_test_2 ] - [ run gauss_quadrature_test.cpp : : : TEST3 $(float128_type) + [ run test_gauss_quadrature.cpp : : : TEST3 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : gauss_quadrature_test_3 ] - [ run gauss_kronrod_quadrature_test.cpp : : : TEST1 $(float128_type) + [ run test_gauss_kronrod_quadrature.cpp : : : TEST1 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release : gauss_kronrod_quadrature_test_1 ] - [ run gauss_kronrod_quadrature_test.cpp : : : TEST1A $(float128_type) + [ run test_gauss_kronrod_quadrature.cpp : : : TEST1A $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : gauss_kronrod_quadrature_test_1a ] - [ run gauss_kronrod_quadrature_test.cpp : : : TEST2 $(float128_type) + [ run test_gauss_kronrod_quadrature.cpp : : : TEST2 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : gauss_kronrod_quadrature_test_2 ] - [ run gauss_kronrod_quadrature_test.cpp : : : TEST3 $(float128_type) + [ run test_gauss_kronrod_quadrature.cpp : : : TEST3 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : gauss_kronrod_quadrature_test_3 ] - [ run adaptive_gauss_kronrod_quadrature_test.cpp : : : TEST1 $(float128_type) + [ run test_adaptive_gauss_kronrod_quadrature.cpp : : : TEST1 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release : adaptive_gauss_quadrature_test_1 ] - [ run adaptive_gauss_kronrod_quadrature_test.cpp : : : TEST1A $(float128_type) + [ run test_adaptive_gauss_kronrod_quadrature.cpp : : : TEST1A $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : adaptive_gauss_quadrature_test_1a ] - [ run adaptive_gauss_kronrod_quadrature_test.cpp : : : TEST2 $(float128_type) + [ run test_adaptive_gauss_kronrod_quadrature.cpp : : : TEST2 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : adaptive_gauss_quadrature_test_2 ] - [ run adaptive_gauss_kronrod_quadrature_test.cpp : : : TEST3 $(float128_type) + [ run test_adaptive_gauss_kronrod_quadrature.cpp : : : TEST3 $(float128_type) [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] off msvc:/bigobj release [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : adaptive_gauss_quadrature_test_3 ] + [ run test_gauss_hermite_quadrature.cpp : : : $(float128_type) [ requires cxx17_if_constexpr ] off msvc:/bigobj release ] + [ run test_gauss_hermite_quadrature_eigen.cpp : : : [ requires cxx17_if_constexpr ] + [ check-target-builds ../../multiprecision/config//has_eigen : : no ] ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=1 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_1 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=2 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_2 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=3 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_3 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=4 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_4 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=5 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_5 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=6 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_6 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=7 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_7 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=8 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_8 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=9 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_9 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=10 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_10 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=11 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_11 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=12 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_12 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=13 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_13 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=14 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_14 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=15 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_15 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=16 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_16 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=17 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_17 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=18 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_18 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=19 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_19 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=20 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_20 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=21 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_21 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=22 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_22 ] - [ run naive_monte_carlo_test.cpp : : : + [ run test_naive_monte_carlo.cpp : : : msvc:/bigobj TEST=23 [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" : naive_monte_carlo_test_23 ] - [ compile compile_test/quad_naive_monte_carlo_incl_test.cpp : + [ compile compile_test/test_quad_naive_monte_carlo_incl.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] linux:"-pthread" [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/gauss_concept_test.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/gauss_kronrod_concept_test.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_gauss_concept.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_gauss_kronrod_concept.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run test_van_den_bos_unit_square.cpp : : : + 17 + [ requires cxx17_if_constexpr cxx11_auto_declarations cxx11_lambdas cxx11_hdr_array cxx11_hdr_thread ] + linux:"-pthread" ] + [ compile-fail test_van_den_bos_unit_square_integral_return_fail.cpp : + 17 + [ requires cxx17_if_constexpr cxx11_auto_declarations cxx11_lambdas cxx11_hdr_array ] ] [ run git_issue_898.cpp ] [ run git_issue_1075.cpp : : : $(float128_type) ] - [ run test_trapezoidal.cpp /boost/test//boost_unit_test_framework : : : + [ run test_trapezoidal.cpp : : : release [ requires cxx11_lambdas cxx11_auto_declarations cxx11_decltype cxx11_unified_initialization_syntax cxx11_variadic_templates ] $(float128_type) ] + [ run test_symplectic.cpp ] ; test-suite autodiff : - [ run test_numerical_differentiation.cpp /boost/test//boost_unit_test_framework : : : msvc:/bigobj [ requires cxx11_auto_declarations cxx11_constexpr ] ] - [ run compile_test/diff_numerical_differentiation_incl_test.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_constexpr ] ] - [ compile compile_test/diff_numerical_differentiation_concept_test.cpp : [ requires cxx11_auto_declarations cxx11_constexpr ] ] - [ run test_autodiff_1.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ run test_autodiff_2.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ run test_autodiff_3.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ run test_autodiff_4.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ run test_autodiff_5.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ run test_autodiff_6.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ run test_autodiff_7.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ run test_autodiff_8.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ check-target-builds ../config//is_ci_standalone_run "Standalone CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ compile compile_test/diff_autodiff_incl_test.cpp : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ compile compile_test/diff_finite_difference_incl_test.cpp : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] - [ compile compile_test/diff_lanczos_smoothing_incl_test.cpp : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ run test_numerical_differentiation.cpp : : : msvc:/bigobj [ requires cxx11_auto_declarations cxx11_constexpr ] ] + [ run compile_test/test_diff_numerical_differentiation_incl.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_constexpr ] ] + [ compile compile_test/test_diff_numerical_differentiation_concept.cpp : [ requires cxx11_auto_declarations cxx11_constexpr ] ] + [ run test_autodiff_1.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ run test_autodiff_2.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ run test_autodiff_3.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ run test_autodiff_4.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ run test_autodiff_5.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ run test_autodiff_6.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ run test_autodiff_7.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ run test_autodiff_8.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ check-target-builds ../config//is_ci_standalone_run "Standalone CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ compile compile_test/test_diff_autodiff_incl.cpp : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ compile compile_test/test_diff_finite_difference_incl.cpp : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] + [ compile compile_test/test_diff_lanczos_smoothing_incl.cpp : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release [ requires cxx17_if_constexpr cxx17_std_apply ] $(float128_type) [ check-target-builds ../config//is_cygwin_run "Cygwin CI run" : no ] [ requires cxx11_inline_namespaces ] ] ; test-suite test_reverse_mode_autodiff : - [ run test_reverse_mode_autodiff_flat_linear_allocator.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] - [ run test_reverse_mode_autodiff_constructors.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] - [ run test_reverse_mode_autodiff_comparison_operators.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] - [ run test_reverse_mode_autodiff_stl_support.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] - [ run test_reverse_mode_autodiff_basic_math_ops.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] - [ run test_reverse_mode_autodiff_error_functions.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] + [ run test_reverse_mode_autodiff_flat_linear_allocator.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] + [ run test_reverse_mode_autodiff_constructors.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] + [ run test_reverse_mode_autodiff_comparison_operators.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] + [ run test_reverse_mode_autodiff_stl_support.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] + [ run test_reverse_mode_autodiff_basic_math_ops.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] + [ run test_reverse_mode_autodiff_error_functions.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] ; test-suite gradient_based_optimizers : - [ run test_gradient_descent_optimizer.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] - [ run test_nesterov_optimizer.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] - [ run test_lbfgs.cpp /boost/test//boost_unit_test_framework : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] + [ run test_gradient_descent_optimizer.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] + [ run test_nesterov_optimizer.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] + [ run test_lbfgs.cpp : : : gcc-mingw:-Wa,-mbig-obj off msvc:/bigobj release ] ; # BEGIN AUTODIFF LONG RUNNING TESTS test-suite autodiff-long-running-tests : [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma1pm1_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma1pm1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma1pm1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma1pm1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma1pm1_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_lgamma_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_lgamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_lgamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_lgamma_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_lgamma_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_digamma_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_digamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_digamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_digamma_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_digamma_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_trigamma_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_trigamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_trigamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_trigamma_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_trigamma_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_polygamma_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_polygamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_polygamma_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_polygamma_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_polygamma_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_ratio_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_ratio_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_ratio_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_ratio_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_ratio_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_delta_ratio_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_delta_ratio_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_delta_ratio_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_delta_ratio_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_delta_ratio_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_p_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_p_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_p_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_p_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_p_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_q_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_q_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_q_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_q_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_gamma_q_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_lower_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_lower_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_lower_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_lower_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gamma/test_reverse_mode_autodiff_tgamma_lower_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_rising_factorial_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_rising_factorial_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_rising_factorial_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_rising_factorial_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_rising_factorial_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_falling_factorial_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_falling_factorial_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_falling_factorial_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_falling_factorial_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/factorial/test_reverse_mode_autodiff_falling_factorial_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_beta_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_beta_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_beta_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_beta_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_beta_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_betac_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_betac_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_betac_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_betac_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_betac_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inv_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inv_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inv_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inv_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inv_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inv_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inv_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inv_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inv_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inv_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inva_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inva_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inva_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inva_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_inva_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inva_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inva_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inva_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inva_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_inva_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_invb_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_invb_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_invb_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_invb_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_invb_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_invb_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_invb_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_invb_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_invb_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibetac_invb_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_derivative_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_derivative_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_derivative_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_derivative_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/beta/test_reverse_mode_autodiff_ibeta_derivative_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_p_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_q_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_q_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_q_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_q_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/legendre/test_reverse_mode_autodiff_legendre_q_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/laguerre/test_reverse_mode_autodiff_laguerre_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/laguerre/test_reverse_mode_autodiff_laguerre_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/laguerre/test_reverse_mode_autodiff_laguerre_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/laguerre/test_reverse_mode_autodiff_laguerre_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/laguerre/test_reverse_mode_autodiff_laguerre_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/hermite/test_reverse_mode_autodiff_hermite_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/hermite/test_reverse_mode_autodiff_hermite_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/hermite/test_reverse_mode_autodiff_hermite_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hermite/test_reverse_mode_autodiff_hermite_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hermite/test_reverse_mode_autodiff_hermite_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_u_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_u_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_u_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_u_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_u_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/chebyshev/test_reverse_mode_autodiff_chebyshev_t_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_r_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_r_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_r_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_r_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_r_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_i_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_i_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_i_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_i_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/spherical_harmonics/test_reverse_mode_autodiff_spherical_harmonic_i_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_prime_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_derivative_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_derivative_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_derivative_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/gegenbauer/test_reverse_mode_autodiff_gegenbauer_derivative_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_derivative_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_derivative_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_derivative_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_derivative_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_derivative_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_double_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_double_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_double_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_double_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi/test_reverse_mode_autodiff_jacobi_double_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_bessel_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_bessel_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_bessel_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_bessel_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_bessel_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_neumann_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_neumann_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_neumann_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_neumann_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_neumann_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_j_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_neumann_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_i_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_cyl_bessel_k_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_bessel_prime_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_bessel_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_bessel_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_bessel_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_neumann_prime_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_neumann_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_neumann_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/bessel/test_reverse_mode_autodiff_sph_neumann_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_cyl_hankel_1_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_cyl_hankel_1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_cyl_hankel_1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_cyl_hankel_1_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_cyl_hankel_2_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_cyl_hankel_2_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_cyl_hankel_2_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_cyl_hankel_2_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_sph_hankel_1_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_sph_hankel_1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_sph_hankel_1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_sph_hankel_1_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_sph_hankel_2_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_sph_hankel_2_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_sph_hankel_2_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hankel/test_reverse_mode_autodiff_sph_hankel_2_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_ai_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_prime_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/airy/test_reverse_mode_autodiff_airy_bi_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rf_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rf_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rf_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rf_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rf_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rd_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rd_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rd_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rd_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rd_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rj_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rj_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rj_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rj_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rj_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rc_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rc_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rc_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rc_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rc_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rg_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rg_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rg_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rg_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_rg_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_1_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_1_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_2_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_2_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_2_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_2_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_2_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_3_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_3_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_3_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_3_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_3_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_d_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_d_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_d_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_d_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/elliptic_integrals/test_reverse_mode_autodiff_ellint_d_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_zeta/test_reverse_mode_autodiff_jacobi_zeta_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_zeta/test_reverse_mode_autodiff_jacobi_zeta_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_zeta/test_reverse_mode_autodiff_jacobi_zeta_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_zeta/test_reverse_mode_autodiff_jacobi_zeta_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_zeta/test_reverse_mode_autodiff_jacobi_zeta_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/heuman_lambda/test_reverse_mode_autodiff_heuman_lambda_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/heuman_lambda/test_reverse_mode_autodiff_heuman_lambda_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/heuman_lambda/test_reverse_mode_autodiff_heuman_lambda_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/heuman_lambda/test_reverse_mode_autodiff_heuman_lambda_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/heuman_lambda/test_reverse_mode_autodiff_heuman_lambda_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cd_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cd_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cd_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cd_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cd_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cn_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cn_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cn_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cn_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cn_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cs_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cs_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cs_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cs_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_cs_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dc_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dc_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dc_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dc_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dc_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dn_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dn_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dn_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dn_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_dn_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ds_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ds_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ds_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ds_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ds_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nc_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nc_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nc_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nc_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nc_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nd_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nd_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nd_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nd_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_nd_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ns_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ns_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ns_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ns_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_ns_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sc_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sc_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sc_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sc_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sc_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sd_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sd_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sd_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sd_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sd_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sn_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sn_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sn_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sn_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_elliptic/test_reverse_mode_autodiff_jacobi_sn_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta2_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta2_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta2_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta2_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta2_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_ON_bin_float_types.cpp ] - [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta1tau_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3tau_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3tau_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3tau_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1tau_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1tau_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta3m1tau_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4tau_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4tau_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4tau_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1tau_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1tau_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1tau_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/jacobi_theta/test_reverse_mode_autodiff_jacobi_theta4m1tau_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_w0_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_w0_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_w0_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_w0_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_wm1_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_wm1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_wm1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_wm1_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_w0_prime_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_w0_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_w0_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_w0_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_wm1_prime_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_wm1_prime_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_wm1_prime_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/lambert_w/test_reverse_mode_autodiff_lambert_wm1_prime_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/riemann_zeta/test_reverse_mode_autodiff_zeta_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/riemann_zeta/test_reverse_mode_autodiff_zeta_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/riemann_zeta/test_reverse_mode_autodiff_zeta_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/riemann_zeta/test_reverse_mode_autodiff_zeta_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/riemann_zeta/test_reverse_mode_autodiff_zeta_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/expint/test_reverse_mode_autodiff_expint_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/expint/test_reverse_mode_autodiff_expint_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/expint/test_reverse_mode_autodiff_expint_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/expint/test_reverse_mode_autodiff_expint_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/expint/test_reverse_mode_autodiff_expint_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F0_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F0_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F0_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F0_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F0_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_0F1_compile_test_ET_ON_bin_float_types.cpp ] + [ run test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F0_compile_test_ET_ON_multiprecision_float_types.cpp ] + [ run test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F0_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_0F1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_0F1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_0F1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_0F1_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_2F0_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_2F0_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_2F0_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_2F0_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_2F0_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F1_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/hypergeometric/test_reverse_mode_autodiff_hypergeometric_1F1_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sin_pi_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sin_pi_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sin_pi_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sin_pi_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sin_pi_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cos_pi_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cos_pi_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cos_pi_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cos_pi_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cos_pi_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_log1p_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_log1p_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_log1p_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_log1p_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_log1p_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_expm1_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_expm1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_expm1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_expm1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_expm1_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cbrt_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cbrt_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cbrt_compile_test_ET_OFF_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cbrt_compile_test_ET_ON_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cbrt_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_cbrt_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sqrt1pm1_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sqrt1pm1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sqrt1pm1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sqrt1pm1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_sqrt1pm1_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_powm1_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_powm1_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_powm1_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_powm1_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_powm1_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_hypot_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_hypot_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_hypot_compile_test_ET_OFF_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_hypot_compile_test_ET_ON_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_hypot_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_hypot_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_rsqrt_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_rsqrt_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_rsqrt_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_rsqrt_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_logaddexp_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_logaddexp_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_logaddexp_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_logaddexp_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_logsumexp_compile_test_ET_ON_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_logsumexp_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_logsumexp_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/basic_funcs/test_reverse_mode_autodiff_logsumexp_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/sinc_pi/test_reverse_mode_autodiff_sinc_pi_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/sinc_pi/test_reverse_mode_autodiff_sinc_pi_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/sinc_pi/test_reverse_mode_autodiff_sinc_pi_compile_test_ET_OFF_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/sinc_pi/test_reverse_mode_autodiff_sinc_pi_compile_test_ET_ON_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/sinc_pi/test_reverse_mode_autodiff_sinc_pi_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/sinc_pi/test_reverse_mode_autodiff_sinc_pi_compile_test_ET_OFF_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/sinhc_pi/test_reverse_mode_autodiff_sinhc_pi_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/sinhc_pi/test_reverse_mode_autodiff_sinhc_pi_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/sinhc_pi/test_reverse_mode_autodiff_sinhc_pi_compile_test_ET_OFF_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/sinhc_pi/test_reverse_mode_autodiff_sinhc_pi_compile_test_ET_ON_multiprecision_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/sinhc_pi/test_reverse_mode_autodiff_sinhc_pi_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/sinhc_pi/test_reverse_mode_autodiff_sinhc_pi_compile_test_ET_OFF_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/owens_t/test_reverse_mode_autodiff_owens_t_compile_test_ET_ON_bin_float_types.cpp ] [ run test_reverse_mode_autodiff_special_functions_compile/owens_t/test_reverse_mode_autodiff_owens_t_compile_test_ET_OFF_bin_float_types.cpp ] - [ run-fail test_reverse_mode_autodiff_special_functions_compile/owens_t/test_reverse_mode_autodiff_owens_t_compile_test_ET_OFF_bin_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/owens_t/test_reverse_mode_autodiff_owens_t_compile_test_ET_ON_multiprecision_float_types.cpp ] - [ compile-fail test_reverse_mode_autodiff_special_functions_compile/owens_t/test_reverse_mode_autodiff_owens_t_compile_test_ET_OFF_multiprecision_float_types.cpp ] ; # END AUTODIFF LONG RUNNING TESTS # @@ -2021,44 +1644,45 @@ test-suite float128_tests : [ get_float128_tests ] ; # Concept checks, and things we do not want to test when running code coverage: # test-suite concepts : - [ run compile_test/dist_bernoulli_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_beta_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_binomial_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_cauchy_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_chi_squared_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_complement_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_exponential_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_extreme_val_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_find_location_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_find_scale_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_fisher_f_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_gamma_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_inv_gamma_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_inv_chi_sq_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_hyperexponential_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_hypergeo_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_landau_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_mapairy_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_holtsmark_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_saspoint5_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_laplace_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_logistic_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_lognormal_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_neg_binom_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_nc_chi_squ_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_nc_beta_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_nc_f_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_nc_t_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_normal_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_poisson_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_students_t_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_triangular_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_uniform_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_weibull_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_bernoulli_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_beta_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_binomial_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_cauchy_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_chi_squared_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_complement_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_exponential_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_extreme_val_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_generalized_extreme_value_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_find_location_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_find_scale_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_fisher_f_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_gamma_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_inv_gamma_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_inv_chi_sq_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_hyperexponential_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_hypergeo_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_landau_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_mapairy_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_holtsmark_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_saspoint5_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_laplace_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_logistic_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_lognormal_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_neg_binom_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_nc_chi_squ_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_nc_beta_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_nc_f_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_nc_t_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_normal_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_poisson_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_students_t_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_triangular_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_uniform_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_weibull_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ run compile_test/distribution_concept_check.cpp : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_arcsine_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/dist_empirical_cumulative_dist_func_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_inv_gaussian_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_arcsine_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_dist_empirical_cumulative_dist_func_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_inv_gaussian_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ compile compile_test/test_promote_args.cpp : [ requires cpp_lib_type_trait_variable_templates ] ] [ compile multiprc_concept_check_1.cpp : off msvc:/bigobj release off:no [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] @@ -2075,85 +1699,87 @@ test-suite concepts : [ compile mpfr_concept_check.cpp : [ check-target-builds ../config//has_mpfr_class : : no ] off [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ compile mpreal_concept_check.cpp : [ check-target-builds ../config//has_mpreal : : no ] off [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/interpolators_cubic_hermite_incl_test.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/interpolators_makima_incl_test.cpp compile_test_main : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/interpolators_pchip_incl_test.cpp compile_test_main : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/interpolators_quintic_hermite_incl_test.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/interpolators_septic_hermite_incl_test.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/interpolators_vector_barycentric_rational_incl_test.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/interpolators_whittaker_shannon_incl_test.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/compl_abs_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/compl_acos_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/compl_acosh_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/compl_asin_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/compl_asinh_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/compl_atan_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/compl_atanh_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_cardinal_trig_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_cubic_hermite_incl.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_makima_incl.cpp compile_test_main : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_pchip_incl.cpp compile_test_main : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_quintic_hermite_incl.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_septic_hermite_incl.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_vector_barycentric_rational_incl.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_whittaker_shannon_incl.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_compl_abs_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_compl_acos_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_compl_acosh_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_compl_asin_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_compl_asinh_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_compl_atan_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_compl_atanh_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_1f0_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_0f1_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_2f0_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_1f1_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_pfq_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_acosh_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_asinh_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_atanh_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_beta_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_bernoulli_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_bessel_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_bessel_deriv_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_binomial_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_cbrt_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_cos_pi_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_digamma_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_polygamma_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ellint_1_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ellint_2_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ellint_3_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ellint_d_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_jacobi_theta_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_jacobi_zeta_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_heuman_lambda_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ellint_rc_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ellint_rd_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ellint_rf_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ellint_rj_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ellint_rg_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_erf_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_expint_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_expm1_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_factorials_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_fpclassify_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_gamma_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_hermite_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_hypot_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_laguerre_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/sf_lanczos_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_legendre_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_legendre_stieltjes_incl_test.cpp compile_test_main : : : [ requires cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_log1p_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/sf_math_fwd_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_modf_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_next_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_powm1_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_prime_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_relative_distance_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_round_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_sign_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_sin_pi_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_sinc_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_sinhc_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_sph_harm_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_sqrt1pm1_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_trunc_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_ulp_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_zeta_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/sf_chebyshev_incl_test.cpp ../config//fftw3 : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/sf_chebyshev_transform_incl_test.cpp ../config//fftw3 : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] [ check-target-builds ../config//has_fftw3 "libfftw3" : : no ] ] - [ run compile_test/sf_fibonacci_incl_test.cpp compile_test_main : : : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_gegenbauer_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_lambert_w_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/sf_nonfinite_num_facets_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_1f0_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_0f1_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_2f0_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_1f1_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_pfq_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_acosh_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_asinh_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_atanh_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_beta_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_bernoulli_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_bessel_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_bessel_deriv_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_binomial_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_cbrt_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_cos_pi_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_digamma_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_polygamma_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ellint_1_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ellint_2_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ellint_3_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ellint_d_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_jacobi_theta_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_jacobi_zeta_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_heuman_lambda_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ellint_rc_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ellint_rd_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ellint_rf_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ellint_rj_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ellint_rg_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_erf_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_expint_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_expm1_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_factorials_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_fpclassify_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_gamma_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_hermite_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_hypot_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_laguerre_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_sf_lanczos_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_legendre_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_legendre_stieltjes_incl.cpp compile_test_main : : : [ requires cxx11_auto_declarations ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_log1p_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_sf_math_fwd_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_modf_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_next_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_powm1_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_prime_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_prime_sieve_incl.cpp compile_test_main : : : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_relative_distance_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_round_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_sign_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_sin_pi_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_sinc_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_sinhc_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_sph_harm_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_sqrt1pm1_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_trunc_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_ulp_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_zeta_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_sf_chebyshev_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_sf_chebyshev_transform_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_fibonacci_incl.cpp compile_test_main : : : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_gegenbauer_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_lambert_w_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_sf_nonfinite_num_facets_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ run compile_test/std_real_concept_check.cpp : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ compile compile_test/std_real_concept_check.cpp : EMULATE32 [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : std_real_concept_check_32 ] [ compile compile_test/std_real_concept_check.cpp : EMULATE64 [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] : std_real_concept_check_64 ] @@ -2165,199 +1791,203 @@ test-suite concepts : [ run compile_test/cstdfloat_concept_check_2.cpp : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ run compile_test/cstdfloat_concept_check_3.cpp : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ run compile_test/cstdfloat_concept_check_4.cpp : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/cstdfloat_cmath_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/cstdfloat_complex_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/cstdfloat_iostream_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/cstdfloat_limits_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/cstdfloat_types_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_cstdfloat_cmath_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_cstdfloat_complex_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_cstdfloat_iostream_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_cstdfloat_limits_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_cstdfloat_types_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ run test_cstdfloat.cpp /boost/test//boost_unit_test_framework : : : $(float128_type) [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_airy_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_hankel_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_jacobi_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/sf_owens_t_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/dist_skew_norm_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/constants_incl_test.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/quad_trapezoidal_incl_test.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_decltype cxx11_unified_initialization_syntax cxx11_variadic_templates ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_airy_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_hankel_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_jacobi_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_sf_owens_t_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_dist_skew_norm_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_constants_incl.cpp compile_test_main : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_quad_trapezoidal_incl.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_decltype cxx11_unified_initialization_syntax cxx11_variadic_templates ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ compile compile_test/test_traits.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_config_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_fraction_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_minima_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_polynomial_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_precision_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_rational_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_real_cast_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_remez_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_roots_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_series_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_solve_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_stats_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_test_data_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_test_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_toms748_inc_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_agm_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_assert_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_atomic_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_big_constant_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_centered_continued_fraction_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_cohen_acceleration_incl_test.cpp : [ requires cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_complex_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_condition_numbers_incl_test.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_convert_from_string_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_cxx03_warn_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_engel_expansion_incl_test.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_header_deprecated_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_is_detected_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_luroth_expansion_incl_test.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_mp_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_norms_incl_test.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_polynomial_gcd_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_promotion_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_random_vector_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_simple_continued_fraction_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_test_value_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_throw_exception_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_traits_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_ulps_plot_incl_test.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/tools_workaround_incl_test.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/interpolators_cubic_spline_concept_test.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/interpolators_barycentric_rational_concept_test.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/sf_legendre_stieltjes_concept_test.cpp : [ requires cxx11_auto_declarations cxx11_defaulted_functions cxx11_lambdas ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/quad_trapezoidal_concept_test.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_decltype cxx11_unified_initialization_syntax cxx11_variadic_templates ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_config_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_fraction_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_minima_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_polynomial_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_precision_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_rational_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_real_cast_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_remez_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_roots_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_series_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_solve_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_stats_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_test_data_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_test_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_toms748_inc.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_agm_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_assert_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_atomic_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_big_constant_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_centered_continued_fraction_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_cohen_acceleration_incl.cpp : [ requires cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_complex_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_condition_numbers_incl.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_convert_from_string_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_cxx03_warn_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_engel_expansion_incl.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_header_deprecated_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_is_detected_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_luroth_expansion_incl.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_mp_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_norms_incl.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_polynomial_gcd_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_promotion_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_random_vector_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_simple_continued_fraction_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_test_value_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_throw_exception_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_traits_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_ulps_plot_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_ulps_heatmap_incl.cpp : [ requires cxx17_if_constexpr cxx17_std_apply ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_tools_workaround_incl.cpp : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_cubic_spline_concept.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_interpolators_barycentric_rational_concept.cpp : [ requires cxx11_smart_ptr cxx11_defaulted_functions cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_sf_legendre_stieltjes_concept.cpp : [ requires cxx11_auto_declarations cxx11_defaulted_functions cxx11_lambdas ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_quad_trapezoidal_concept.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_decltype cxx11_unified_initialization_syntax cxx11_variadic_templates ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] [ compile test_no_long_double_policy.cpp ] [ compile bernoulli_no_atomic_d.cpp ] [ compile bernoulli_no_atomic_mp.cpp ] [ compile-fail bernoulli_no_atomic_fail.cpp ] - [ run compile_test/quad_exp_sinh_incl_test.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/quad_sinh_sinh_incl_test.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ run compile_test/quad_tanh_sinh_incl_test.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/quad_gauss_incl_test.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/quad_gauss_kronrod_incl_test.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/quad_ooura_fourier_integrals_incl_test.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/quad_wavelet_transforms_incl_test.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/quad_exp_sinh_concept_test.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/quad_sinh_sinh_concept_test.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] - [ compile compile_test/quad_tanh_sinh_concept_test.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_quad_exp_sinh_incl.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_quad_sinh_sinh_incl.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ run compile_test/test_quad_tanh_sinh_incl.cpp compile_test_main : : : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_quad_gauss_incl.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_quad_gauss_kronrod_incl.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_quad_gauss_hermite_incl.cpp : [ requires cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_quad_ooura_fourier_integrals_incl.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_quad_wavelet_transforms_incl.cpp : [ requires cxx17_std_apply cxx17_if_constexpr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_quad_exp_sinh_concept.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_quad_sinh_sinh_concept.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] + [ compile compile_test/test_quad_tanh_sinh_concept.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_smart_ptr cxx11_unified_initialization_syntax sfinae_expr ] [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : no ] ] ; # # Things that we can test with exceptions and RTTI turned off: # alias no_eh_tests : - compl_abs_incl_test - compl_acos_incl_test - compl_acosh_incl_test - compl_asin_incl_test - compl_asinh_incl_test - compl_atan_incl_test - compl_atanh_incl_test - sf_acosh_incl_test - sf_asinh_incl_test - sf_atanh_incl_test - sf_beta_incl_test - sf_bernoulli_incl_test - sf_bessel_incl_test - sf_bessel_deriv_incl_test - sf_binomial_incl_test - sf_cbrt_incl_test - sf_cos_pi_incl_test - sf_digamma_incl_test - sf_polygamma_incl_test - sf_ellint_1_incl_test - sf_ellint_2_incl_test - sf_ellint_3_incl_test - sf_ellint_d_incl_test - sf_jacobi_theta_incl_test - sf_jacobi_zeta_incl_test - sf_heuman_lambda_incl_test - sf_ellint_rc_incl_test - sf_ellint_rd_incl_test - sf_ellint_rf_incl_test - sf_ellint_rj_incl_test - sf_ellint_rg_incl_test - sf_erf_incl_test - sf_expint_incl_test - sf_expm1_incl_test - sf_factorials_incl_test - sf_fpclassify_incl_test - sf_gamma_incl_test - sf_hermite_incl_test - sf_hypot_incl_test - sf_laguerre_incl_test - sf_lanczos_incl_test - sf_legendre_incl_test - #sf_legendre_stieltjes_incl_test - sf_log1p_incl_test - sf_math_fwd_incl_test - sf_modf_incl_test - sf_next_incl_test - sf_powm1_incl_test - sf_prime_incl_test - sf_relative_distance_incl_test - sf_round_incl_test - sf_sign_incl_test - sf_sin_pi_incl_test - sf_sinc_incl_test - sf_sinhc_incl_test - sf_sph_harm_incl_test - sf_sqrt1pm1_incl_test - sf_trunc_incl_test - sf_ulp_incl_test - sf_zeta_incl_test - sf_chebyshev_incl_test - #sf_chebyshev_transform_incl_test - sf_fibonacci_incl_test - #sf_gegenbauer_incl_test - sf_lambert_w_incl_test - sf_nonfinite_num_facets_incl_test - sf_airy_incl_test - sf_hankel_incl_test - sf_jacobi_incl_test - sf_owens_t_incl_test - dist_skew_norm_incl_test - constants_incl_test - quad_trapezoidal_incl_test + test_compl_abs_incl + test_compl_acos_incl + test_compl_acosh_incl + test_compl_asin_incl + test_compl_asinh_incl + test_compl_atan_incl + test_compl_atanh_incl + test_sf_acosh_incl + test_sf_asinh_incl + test_sf_atanh_incl + test_sf_beta_incl + test_sf_bernoulli_incl + test_sf_bessel_incl + test_sf_bessel_deriv_incl + test_sf_binomial_incl + test_sf_cbrt_incl + test_sf_cos_pi_incl + test_sf_digamma_incl + test_sf_polygamma_incl + test_sf_ellint_1_incl + test_sf_ellint_2_incl + test_sf_ellint_3_incl + test_sf_ellint_d_incl + test_sf_jacobi_theta_incl + test_sf_jacobi_zeta_incl + test_sf_heuman_lambda_incl + test_sf_ellint_rc_incl + test_sf_ellint_rd_incl + test_sf_ellint_rf_incl + test_sf_ellint_rj_incl + test_sf_ellint_rg_incl + test_sf_erf_incl + test_sf_expint_incl + test_sf_expm1_incl + test_sf_factorials_incl + test_sf_fpclassify_incl + test_sf_gamma_incl + test_sf_hermite_incl + test_sf_hypot_incl + test_sf_laguerre_incl + test_sf_lanczos_incl + test_sf_legendre_incl + #test_sf_legendre_stieltjes_incl + test_sf_log1p_incl + test_sf_math_fwd_incl + test_sf_modf_incl + test_sf_next_incl + test_sf_powm1_incl + test_sf_prime_incl + test_sf_prime_sieve_incl + test_sf_relative_distance_incl + test_sf_round_incl + test_sf_sign_incl + test_sf_sin_pi_incl + test_sf_sinc_incl + test_sf_sinhc_incl + test_sf_sph_harm_incl + test_sf_sqrt1pm1_incl + test_sf_trunc_incl + test_sf_ulp_incl + test_sf_zeta_incl + test_sf_chebyshev_incl + #test_sf_chebyshev_transform_incl + test_sf_fibonacci_incl + #test_sf_gegenbauer_incl + test_sf_lambert_w_incl + test_sf_nonfinite_num_facets_incl + test_sf_airy_incl + test_sf_hankel_incl + test_sf_jacobi_incl + test_sf_owens_t_incl + test_dist_skew_norm_incl + test_constants_incl + test_quad_trapezoidal_incl test_traits - tools_config_inc_test - tools_fraction_inc_test - tools_minima_inc_test - tools_polynomial_inc_test - tools_precision_inc_test - tools_rational_inc_test - tools_real_cast_inc_test - tools_remez_inc_test - tools_roots_inc_test - tools_series_inc_test - tools_solve_inc_test - tools_stats_inc_test - tools_test_data_inc_test - #tools_test_inc_test - tools_toms748_inc_test - tools_agm_incl_test - tools_assert_incl_test - tools_atomic_incl_test - tools_big_constant_incl_test - #tools_centered_continued_fraction_incl_test - tools_cohen_acceleration_incl_test - tools_complex_incl_test - tools_condition_numbers_incl_test - tools_convert_from_string_incl_test - tools_cxx03_warn_incl_test - #tools_engel_expansion_incl_test - tools_header_deprecated_incl_test - tools_is_detected_incl_test - #tools_luroth_expansion_incl_test - tools_mp_incl_test - tools_norms_incl_test - tools_polynomial_gcd_incl_test - tools_promotion_incl_test - tools_random_vector_incl_test - #tools_simple_continued_fraction_incl_test - tools_test_value_incl_test - tools_throw_exception_incl_test - tools_traits_incl_test - #tools_ulps_plot_incl_test - tools_workaround_incl_test + test_tools_config_inc + test_tools_fraction_inc + test_tools_minima_inc + test_tools_polynomial_inc + test_tools_precision_inc + test_tools_rational_inc + test_tools_real_cast_inc + test_tools_remez_inc + test_tools_roots_inc + test_tools_series_inc + test_tools_solve_inc + test_tools_stats_inc + test_tools_test_data_inc + #test_tools_test_inc + test_tools_toms748_inc + test_tools_agm_incl + test_tools_assert_incl + test_tools_atomic_incl + test_tools_big_constant_incl + #test_tools_centered_continued_fraction_incl + test_tools_cohen_acceleration_incl + test_tools_complex_incl + test_tools_condition_numbers_incl + test_tools_convert_from_string_incl + test_tools_cxx03_warn_incl + #test_tools_engel_expansion_incl + test_tools_header_deprecated_incl + test_tools_is_detected_incl + #test_tools_luroth_expansion_incl + test_tools_mp_incl + test_tools_norms_incl + test_tools_polynomial_gcd_incl + test_tools_promotion_incl + test_tools_random_vector_incl + #test_tools_simple_continued_fraction_incl + test_tools_test_value_incl + test_tools_throw_exception_incl + test_tools_traits_incl + #test_tools_ulps_plot_incl + #test_tools_ulps_heatmap_incl + test_tools_workaround_incl ; explicit no_eh_tests ; diff --git a/test/adaptive_gauss_kronrod_quadrature_test.cpp b/test/adaptive_gauss_kronrod_quadrature_test.cpp deleted file mode 100644 index f2c703e92a..0000000000 --- a/test/adaptive_gauss_kronrod_quadrature_test.cpp +++ /dev/null @@ -1,337 +0,0 @@ -// Copyright Nick Thompson, 2017 -// 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) - -#define BOOST_TEST_MODULE adaptive_gauss_kronrod_quadrature_test - -#include -#include - -#if __has_include() -# include -#endif - -#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && !defined(BOOST_NO_SFINAE_EXPR) - -#include -#include -#include -#include -#include -#include -#include - -#if !defined(TEST1) && !defined(TEST1A) && !defined(TEST2) && !defined(TEST3) -# define TEST1 -# define TEST1A -# define TEST2 -# define TEST3 -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4127) // Conditional expression is constant -#endif - -using std::expm1; -using std::atan; -using std::tan; -using std::log; -using std::log1p; -using std::asinh; -using std::atanh; -using std::sqrt; -using std::isnormal; -using std::abs; -using std::sinh; -using std::tanh; -using std::cosh; -using std::pow; -using std::exp; -using std::sin; -using std::cos; -using std::string; -using boost::math::quadrature::gauss_kronrod; -using boost::math::constants::pi; -using boost::math::constants::half_pi; -using boost::math::constants::two_div_pi; -using boost::math::constants::two_pi; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::catalan; -using boost::math::constants::ln_two; -using boost::math::constants::root_two; -using boost::math::constants::root_two_pi; -using boost::math::constants::root_pi; -using boost::multiprecision::cpp_bin_float_quad; - -template -Real get_termination_condition() -{ - return boost::math::tools::epsilon() * 1000; -} - - -template -void test_linear() -{ - std::cout << "Testing linear functions are integrated properly by gauss_kronrod on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - Real error; - auto f = [](const Real& x) - { - return 5*x + 7; - }; - Real L1; - Real Q = gauss_kronrod::integrate(f, (Real) 0, (Real) 1, 15, get_termination_condition(), &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, 9.5, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, 9.5, tol); - BOOST_CHECK_LE(fabs(error / Q), get_termination_condition()); - BOOST_CHECK_GE(fabs(error), fabs(Q - 9.5)); -} - -template -void test_quadratic() -{ - std::cout << "Testing quadratic functions are integrated properly by gauss-kronrod on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - Real error; - - auto f = [](const Real& x) { return 5*x*x + 7*x + 12; }; - Real L1; - Real Q = gauss_kronrod::integrate(f, 0, 1, 15, get_termination_condition(), &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, (Real) 17 + half()*third(), tol); - BOOST_CHECK_CLOSE_FRACTION(L1, (Real) 17 + half()*third(), tol); - BOOST_CHECK_LE(fabs(error / Q), get_termination_condition()); - BOOST_CHECK_GE(fabs(error), fabs(Q - ((Real)17 + half()*third()))); -} - -// Examples taken from -//http://crd-legacy.lbl.gov/~dhbailey/dhbpapers/quadrature.pdf -template -void test_ca() -{ - std::cout << "Testing integration of C(a) on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - Real L1; - Real error; - - auto f1 = [](const Real& x) { return atan(x)/(x*(x*x + 1)) ; }; - Real Q = gauss_kronrod::integrate(f1, 0, 1, 15, get_termination_condition(), &error, &L1); - Real Q_expected = pi()*ln_two()/8 + catalan()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - BOOST_CHECK_LE(fabs(error / Q), get_termination_condition()); - BOOST_CHECK_GE(fabs(error), fabs(Q - Q_expected)); - - auto f2 = [](Real x)->Real { Real t0 = x*x + 1; Real t1 = sqrt(t0); return atan(t1)/(t0*t1); }; - Q = gauss_kronrod::integrate(f2, 0 , 1, 15, get_termination_condition(), &error, &L1); - Q_expected = pi()/4 - pi()/root_two() + 3*atan(root_two())/root_two(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - BOOST_CHECK_LE(fabs(error / Q), get_termination_condition()); - BOOST_CHECK_GE(fabs(error), fabs(Q - Q_expected)); - - auto f5 = [](Real t)->Real { return t*t*log(t)/((t*t - 1)*(t*t*t*t + 1)); }; - Q = gauss_kronrod::integrate(f5, 0, 1, 25); - Q_expected = pi()*pi()*(2 - root_two())/32; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 100 * tol); -} - -template -void test_three_quadrature_schemes_examples() -{ - std::cout << "Testing integral in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - Real Q; - Real Q_expected; - - // Example 1: - auto f1 = [](const Real& t) { return t*boost::math::log1p(t); }; - Q = gauss_kronrod::integrate(f1, 0 , 1); - Q_expected = half()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - - // Example 2: - auto f2 = [](const Real& t) { return t*t*atan(t); }; - Q = gauss_kronrod::integrate(f2, 0, 1); - Q_expected = (pi() -2 + 2*ln_two())/12; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 2 * tol); - - // Example 3: - auto f3 = [](const Real& t) { return exp(t)*cos(t); }; - Q = gauss_kronrod::integrate(f3, 0, half_pi()); - Q_expected = boost::math::expm1(half_pi())*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Example 4: - auto f4 = [](Real x)->Real { Real t0 = sqrt(x*x + 2); return atan(t0)/(t0*(x*x+1)); }; - Q = gauss_kronrod::integrate(f4, 0, 1); - Q_expected = 5*pi()*pi()/96; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); -} - - -template -void test_integration_over_real_line() -{ - std::cout << "Testing integrals over entire real line in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - Real Q; - Real Q_expected; - Real L1; - Real error; - - auto f1 = [](const Real& t) { return 1/(1+t*t);}; - Q = gauss_kronrod::integrate(f1, -boost::math::tools::max_value(), boost::math::tools::max_value(), 15, get_termination_condition(), &error, &L1); - Q_expected = pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - BOOST_CHECK_LE(fabs(error / Q), get_termination_condition()); - - auto f4 = [](const Real& t) { return 1/cosh(t);}; - Q = gauss_kronrod::integrate(f4, -boost::math::tools::max_value(), boost::math::tools::max_value(), 15, get_termination_condition(), &error, &L1); - Q_expected = pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - BOOST_CHECK_LE(fabs(error / Q), get_termination_condition()); - -} - -template -void test_right_limit_infinite() -{ - std::cout << "Testing right limit infinite for Gauss-Kronrod in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - Real Q; - Real Q_expected; - Real L1; - Real error; - - // Example 11: - auto f1 = [](const Real& t) { return 1/(1+t*t);}; - Q = gauss_kronrod::integrate(f1, 0, boost::math::tools::max_value(), 15, get_termination_condition(), &error, &L1); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); - BOOST_CHECK_LE(fabs(error / Q), get_termination_condition()); - - auto f4 = [](const Real& t) { return 1/(1+t*t); }; - Q = gauss_kronrod::integrate(f4, 1, boost::math::tools::max_value(), 15, get_termination_condition(), &error, &L1); - Q_expected = pi()/4; - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); - BOOST_CHECK_LE(fabs(error / Q), get_termination_condition()); -} - -template -void test_left_limit_infinite() -{ - std::cout << "Testing left limit infinite for Gauss-Kronrod in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - Real Q; - Real Q_expected; - - // Example 11: - auto f1 = [](const Real& t) { return 1/(1+t*t);}; - Q = gauss_kronrod::integrate(f1, -boost::math::tools::max_value(), 0); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE(Q, Q_expected, 300*tol); -} - -BOOST_AUTO_TEST_CASE(gauss_quadrature_test) -{ -#ifdef TEST1 - std::cout << "Testing with 15 point Gauss-Kronrod rule:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - // test one case where we do not have pre-computed constants: - std::cout << "Testing with 17 point Gauss-Kronrod rule:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - #ifdef __STDCPP_FLOAT64_T__ - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - #endif - -#endif -#ifdef TEST1A -#if LDBL_MANT_DIG < 100 // If we have too many digits in a long double, we get build errors due to a constexpr issue. - std::cout << "Testing with 21 point Gauss-Kronrod rule:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - std::cout << "Testing with 31 point Gauss-Kronrod rule:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#endif -#endif -#ifdef TEST2 -#if LDBL_MANT_DIG < 100 // If we have too many digits in a long double, we get build errors due to a constexpr issue. - std::cout << "Testing with 41 point Gauss-Kronrod rule:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - std::cout << "Testing with 51 point Gauss-Kronrod rule:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#endif -#endif -#ifdef TEST3 -#if LDBL_MANT_DIG < 100 // If we have too many digits in a long double, we get build errors due to a constexpr issue. - std::cout << "Testing with 61 point Gauss-Kronrod rule:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#endif -#endif -} - -#else - -int main() { return 0; } - -#endif diff --git a/test/bessel_iterator_test.cpp b/test/bessel_iterator_test.cpp deleted file mode 100644 index 80fc87de7f..0000000000 --- a/test/bessel_iterator_test.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// (C) Copyright John Maddock, 2024 -// 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) - -#define BOOST_TEST_MAIN -#include -#include - - -BOOST_AUTO_TEST_CASE(test_main) -{ - using boost::math::bessel_j_backwards_iterator; - using boost::math::bessel_i_backwards_iterator; - using boost::math::bessel_i_forwards_iterator; - - BOOST_CHECK_THROW(bessel_j_backwards_iterator(-2.3, 5.0), std::domain_error); - BOOST_CHECK_THROW(bessel_j_backwards_iterator(-2.3, 5.0, 2.0), std::domain_error); - BOOST_CHECK_THROW(bessel_j_backwards_iterator(-2.3, 5.0, 2.0, 2.0), std::domain_error); - - double tolerance = std::numeric_limits::epsilon() * 5; - - { - bessel_j_backwards_iterator i(12, 2.0); - for (unsigned j = 0; j < 4; ++j) - ++i; - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_j(8, 2.0), tolerance); - double v = *i++; - BOOST_CHECK_CLOSE_FRACTION(v, boost::math::cyl_bessel_j(8, 2.0), tolerance); - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_j(7, 2.0), tolerance); - } - { - bessel_j_backwards_iterator i(12, 2.0, boost::math::cyl_bessel_j(12, 2.0)); - for (unsigned j = 0; j < 4; ++j) - ++i; - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_j(8, 2.0), tolerance); - } - { - bessel_j_backwards_iterator i(12, 2.0, boost::math::cyl_bessel_j(13, 2.0), boost::math::cyl_bessel_j(12, 2.0)); - for (unsigned j = 0; j < 4; ++j) - ++i; - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_j(8, 2.0), tolerance); - } - - { - bessel_i_backwards_iterator i(12, 2.0); - for (unsigned j = 0; j < 4; ++j) - ++i; - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(8, 2.0), tolerance); - double v = *i++; - BOOST_CHECK_CLOSE_FRACTION(v, boost::math::cyl_bessel_i(8, 2.0), tolerance); - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(7, 2.0), tolerance); - - BOOST_CHECK_THROW(bessel_i_backwards_iterator(-1.1, 2.0), std::domain_error); - BOOST_CHECK_THROW(bessel_i_backwards_iterator(-1.1, 2.0, 1.0), std::domain_error); - BOOST_CHECK_THROW(bessel_i_backwards_iterator(-1.1, 2.0, 1.0, 1.0), std::domain_error); - } - { - bessel_i_backwards_iterator i(12, 2.0, boost::math::cyl_bessel_i(12, 2.0)); - for (unsigned j = 0; j < 4; ++j) - ++i; - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(8, 2.0), tolerance); - } - { - bessel_i_backwards_iterator i(12, 2.0, boost::math::cyl_bessel_i(13, 2.0), boost::math::cyl_bessel_i(12, 2.0)); - for (unsigned j = 0; j < 4; ++j) - ++i; - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(8, 2.0), tolerance); - } - - { - bessel_i_forwards_iterator i(-12, 2.0); - for (unsigned j = 0; j < 4; ++j) - ++i; - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(-8, 2.0), tolerance); - double v = *i++; - BOOST_CHECK_CLOSE_FRACTION(v, boost::math::cyl_bessel_i(-8, 2.0), tolerance); - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(-7, 2.0), tolerance); - - BOOST_CHECK_THROW(bessel_i_forwards_iterator(1.1, 2.0), std::domain_error); - BOOST_CHECK_THROW(bessel_i_forwards_iterator(1.1, 2.0, 1.0), std::domain_error); - BOOST_CHECK_THROW(bessel_i_forwards_iterator(1.1, 2.0, 1.0, 1.0), std::domain_error); - } - { - bessel_i_forwards_iterator i(-12, 2.0, boost::math::cyl_bessel_i(-12, 2.0)); - for (unsigned j = 0; j < 4; ++j) - ++i; - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(-8, 2.0), tolerance); - } - { - bessel_i_forwards_iterator i(-12, 2.0, boost::math::cyl_bessel_i(-13, 2.0), boost::math::cyl_bessel_i(-12, 2.0)); - for (unsigned j = 0; j < 4; ++j) - ++i; - BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(-8, 2.0), tolerance); - } -} diff --git a/test/bezier_polynomial_test.cpp b/test/bezier_polynomial_test.cpp deleted file mode 100644 index 4aadd3edc8..0000000000 --- a/test/bezier_polynomial_test.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright Nick Thompson, 2021 - * 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) - */ - -#include -#ifndef BOOST_MATH_NO_THREAD_LOCAL_WITH_NON_TRIVIAL_TYPES -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - -#if __has_include() -# include -#endif - -using boost::math::interpolators::bezier_polynomial; - -template -void test_linear() -{ - std::vector> control_points(2); - control_points[0] = {Real(0), Real(0)}; - control_points[1] = {Real(1), Real(1)}; - auto control_points_copy = control_points; - auto bp = bezier_polynomial(std::move(control_points_copy)); - - // P(0) = P_0: - CHECK_ULP_CLOSE(control_points[0][0], bp(0)[0], 3); - CHECK_ULP_CLOSE(control_points[0][1], bp(0)[1], 3); - - // P(1) = P_n: - CHECK_ULP_CLOSE(control_points[1][0], bp(1)[0], 3); - CHECK_ULP_CLOSE(control_points[1][1], bp(1)[1], 3); - - for (Real t = Real(1)/32; t < 1; t += Real(1)/32) { - Real expected0 = (1-t)*control_points[0][0] + t*control_points[1][0]; - CHECK_ULP_CLOSE(expected0, bp(t)[0], 3); - } - - // P(1) = P_n: - std::array endpoint{1,2}; - bp.edit_control_point(endpoint, 1); - CHECK_ULP_CLOSE(endpoint[0], bp(1)[0], 3); - CHECK_ULP_CLOSE(endpoint[1], bp(1)[1], 3); - -} - -template -void test_quadratic() -{ - std::vector> control_points(3); - control_points[0] = {Real(0), Real(0)}; - control_points[1] = {Real(1), Real(1)}; - control_points[2] = {Real(2), Real(2)}; - auto control_points_copy = control_points; - auto bp = bezier_polynomial(std::move(control_points_copy)); - - // P(0) = P_0: - auto computed_point = bp(0); - CHECK_ULP_CLOSE(control_points[0][0], computed_point[0], 3); - CHECK_ULP_CLOSE(control_points[0][1], computed_point[1], 3); - auto computed_dp = bp.prime(0); - CHECK_ULP_CLOSE(2*(control_points[1][0] - control_points[0][0]), computed_dp[0], 3); - CHECK_ULP_CLOSE(2*(control_points[1][1] - control_points[0][1]), computed_dp[1], 3); - - // P(1) = P_n: - computed_point = bp(1); - CHECK_ULP_CLOSE(control_points[2][0], computed_point[0], 3); - CHECK_ULP_CLOSE(control_points[2][1], computed_point[1], 3); -} - -// All points on a Bezier polynomial fall into the convex hull of the control polygon. -template -void test_convex_hull() -{ - std::vector> control_points(4); - control_points[0] = {Real(0), Real(0)}; - control_points[1] = {Real(0), Real(1)}; - control_points[2] = {Real(1), Real(1)}; - control_points[3] = {Real(1), Real(0)}; - auto bp = bezier_polynomial(std::move(control_points)); - - for (Real t = 0; t <= 1; t += Real(1)/32) { - auto p = bp(t); - CHECK_LE(p[0], Real(1)); - CHECK_LE(Real(0), p[0]); - CHECK_LE(p[1], Real(1)); - CHECK_LE(Real(0), p[1]); - } -} - -// Reversal Symmetry: If q(t) is the Bezier polynomial which consumes the control points in reversed order from p(t), -// then p(t) = q(1-t). -template -void test_reversal_symmetry() -{ - std::vector> control_points(10); - std::uniform_real_distribution dis(-1,1); - std::mt19937_64 gen; - for (size_t i = 0; i < control_points.size(); ++i) { - for (size_t j = 0; j < 3; ++j) { - control_points[i][j] = dis(gen); - } - } - - auto control_points_copy = control_points; - auto bp0 = bezier_polynomial(std::move(control_points_copy)); - - control_points_copy = control_points; - std::reverse(control_points_copy.begin(), control_points_copy.end()); - auto bp1 = bezier_polynomial(std::move(control_points_copy)); - auto P0 = bp0(Real(0)); - CHECK_ULP_CLOSE(control_points[0][0], P0[0], 3); - CHECK_ULP_CLOSE(control_points[0][1], P0[1], 3); - CHECK_ULP_CLOSE(control_points[0][2], P0[2], 3); - auto P1 = bp0(Real(1)); - CHECK_ULP_CLOSE(control_points.back()[0], P1[0], 3); - CHECK_ULP_CLOSE(control_points.back()[1], P1[1], 3); - CHECK_ULP_CLOSE(control_points.back()[2], P1[2], 3); - - P0 = bp1(Real(1)); - CHECK_ULP_CLOSE(control_points[0][0], P0[0], 3); - CHECK_ULP_CLOSE(control_points[0][1], P0[1], 3); - CHECK_ULP_CLOSE(control_points[0][2], P0[2], 3); - - P1 = bp1(Real(0)); - CHECK_ULP_CLOSE(control_points.back()[0], P1[0], 3); - CHECK_ULP_CLOSE(control_points.back()[1], P1[1], 3); - CHECK_ULP_CLOSE(control_points.back()[2], P1[2], 3); - - for (Real t = 0; t <= 1; t += Real(1.0)) { - auto P0 = bp0(t); - auto P1 = bp1(Real(1.0)-t); - if (!CHECK_ULP_CLOSE(P0[0], P1[0], 3)) { - std::cerr << " Error at t = " << t << "\n"; - } - CHECK_ULP_CLOSE(P0[1], P1[1], 3); - CHECK_ULP_CLOSE(P0[2], P1[2], 3); - } -} - -// Linear precision: If all control points lie *equidistantly* on a line, then the Bezier curve falls on a line. -// See Bezier and B-spline techniques, Section 2.8, Remark 8. -template -void test_linear_precision() -{ - std::vector> control_points(10); - std::array P0 = {1,1,1}; - std::array Pf = {2,2,2}; - control_points[0] = P0; - control_points[9] = Pf; - for (size_t i = 1; i < 9; ++i) { - Real t = Real(i)/(control_points.size()-1); - control_points[i][0] = (1-t)*P0[0] + t*Pf[0]; - control_points[i][1] = (1-t)*P0[1] + t*Pf[1]; - control_points[i][2] = (1-t)*P0[2] + t*Pf[2]; - } - - auto bp = bezier_polynomial(std::move(control_points)); - for (Real t = 0; t < 1; t += Real(1)/32) { - std::array P; - P[0] = (1-t)*P0[0] + t*Pf[0]; - P[1] = (1-t)*P0[1] + t*Pf[1]; - P[2] = (1-t)*P0[2] + t*Pf[2]; - - auto computed = bp(t); - CHECK_ULP_CLOSE(P[0], computed[0], 4); - CHECK_ULP_CLOSE(P[1], computed[1], 4); - CHECK_ULP_CLOSE(P[2], computed[2], 4); - - std::array dP; - dP[0] = Pf[0] - P0[0]; - dP[1] = Pf[1] - P0[1]; - dP[2] = Pf[2] - P0[2]; - auto dpComputed = bp.prime(t); - CHECK_ULP_CLOSE(dP[0], dpComputed[0], 5); - } -} - -int main() -{ - #ifdef __STDCPP_FLOAT32_T__ - test_linear(); - test_quadratic(); - test_convex_hull(); - test_linear_precision(); - test_reversal_symmetry(); - #else - test_linear(); - test_quadratic(); - test_convex_hull(); - test_linear_precision(); - test_reversal_symmetry(); - #endif - - #ifdef __STDCPP_FLOAT64_T__ - test_linear(); - test_quadratic(); - test_convex_hull(); - test_linear_precision(); - test_reversal_symmetry(); - #else - test_linear(); - test_quadratic(); - test_convex_hull(); - test_linear_precision(); - test_reversal_symmetry(); - #endif - - #ifdef BOOST_HAS_FLOAT128 - test_linear(); - test_quadratic(); - test_convex_hull(); - #endif - - return boost::math::test::report_errors(); -} - -#else -int main() { - return 0; -} -#endif diff --git a/test/bivariate_statistics_test.cpp b/test/bivariate_statistics_test.cpp deleted file mode 100644 index 0f78f08024..0000000000 --- a/test/bivariate_statistics_test.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/* - * (C) Copyright Nick Thompson 2018. - * (C) Copyright Matt Borland 2021. - * 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) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#include - -using boost::multiprecision::cpp_bin_float_50; -using boost::multiprecision::cpp_complex_50; - -/* - * Test checklist: - * 1) Does it work with multiprecision? - * 2) Does it work with .cbegin()/.cend() if the data is not altered? - * 3) Does it work with ublas and std::array? (Checking Eigen and Armadillo will make the CI system really unhappy.) - * 4) Does it work with std::forward_list if a forward iterator is all that is required? - * 5) Does it work with complex data if complex data is sensible? - */ - -using boost::math::statistics::means_and_covariance; -using boost::math::statistics::covariance; - -#ifndef BOOST_NO_CXX17_HDR_EXECUTION -#include - -template -void test_covariance(ExecutionPolicy&& exec) -{ - std::cout << std::setprecision(std::numeric_limits::digits10+1); - Real tol = std::numeric_limits::epsilon(); - using std::abs; - - // Covariance of a single thing is zero: - std::array u1{8}; - std::array v1{17}; - std::tuple temp = means_and_covariance(exec, u1, v1); - Real mu_u1 = std::get<0>(temp); - Real mu_v1 = std::get<1>(temp); - Real cov1 = std::get<2>(temp); - - CHECK_LE(abs(cov1), tol); - CHECK_LE(abs(mu_u1 - 8), tol); - CHECK_LE(abs(mu_v1 - 17), tol); - - - std::array u2{8, 4}; - std::array v2{3, 7}; - temp = means_and_covariance(exec, u2, v2); - Real mu_u2 = std::get<0>(temp); - Real mu_v2 = std::get<1>(temp); - Real cov2 = std::get<2>(temp); - - CHECK_LE(abs(cov2+4), tol); - CHECK_LE(abs(mu_u2 - 6), tol); - CHECK_LE(abs(mu_v2 - 5), tol); - - std::vector u3{1,2,3}; - std::vector v3{1,1,1}; - - temp = means_and_covariance(exec, u3, v3); - Real mu_u3 = std::get<0>(temp); - Real mu_v3 = std::get<1>(temp); - Real cov3 = std::get<2>(temp); - - // Since v is constant, covariance(u,v) = 0 against everything any u: - CHECK_LE(abs(cov3), tol); - CHECK_LE(abs(mu_u3 - 2), tol); - CHECK_LE(abs(mu_v3 - 1), tol); - // Make sure we pull the correct symbol out of means_and_covariance: - cov3 = covariance(exec, u3, v3); - CHECK_LE(abs(cov3), tol); - - cov3 = covariance(exec, v3, u3); - // Covariance is symmetric: cov(u,v) = cov(v,u) - CHECK_LE(abs(cov3), tol); - - // cov(u,u) = sigma(u)^2: - cov3 = covariance(exec, u3, u3); - Real expected = Real(2)/Real(3); - - CHECK_LE(abs(cov3 - expected), tol); - - std::mt19937 gen(15); - // Can't template standard library on multiprecision, so use double and cast back: - std::uniform_real_distribution dis(-1.0, 1.0); - std::vector u(500); - std::vector v(500); - for(size_t i = 0; i < u.size(); ++i) - { - u[i] = (Real) dis(gen); - v[i] = (Real) dis(gen); - } - - Real mu_u = boost::math::statistics::mean(u); - Real mu_v = boost::math::statistics::mean(v); - Real sigma_u_sq = boost::math::statistics::variance(u); - Real sigma_v_sq = boost::math::statistics::variance(v); - - temp = means_and_covariance(exec, u, v); - Real mu_u_ = std::get<0>(temp); - Real mu_v_ = std::get<1>(temp); - Real cov_uv = std::get<2>(temp); - - CHECK_LE(abs(mu_u - mu_u_), tol); - CHECK_LE(abs(mu_v - mu_v_), tol); - - // Cauchy-Schwartz inequality: - CHECK_LE(cov_uv*cov_uv, sigma_u_sq*sigma_v_sq); - // cov(X, X) = sigma(X)^2: - Real cov_uu = covariance(exec, u, u); - CHECK_LE(abs(cov_uu - sigma_u_sq), tol); - Real cov_vv = covariance(exec, v, v); - CHECK_LE(abs(cov_vv - sigma_v_sq), tol); -} - -template -void test_integer_covariance(ExecutionPolicy&& exec) -{ - std::cout << std::setprecision(std::numeric_limits::digits10+1); - double tol = std::numeric_limits::epsilon(); - using std::abs; - - // Covariance of a single thing is zero: - std::array u1{8}; - std::array v1{17}; - std::tuple temp = means_and_covariance(exec, u1, v1); - double mu_u1 = std::get<0>(temp); - double mu_v1 = std::get<1>(temp); - double cov1 = std::get<2>(temp); - - CHECK_LE(abs(cov1), tol); - CHECK_LE(abs(mu_u1 - 8), tol); - CHECK_LE(abs(mu_v1 - 17), tol); - - - std::array u2{8, 4}; - std::array v2{3, 7}; - temp = means_and_covariance(exec, u2, v2); - double mu_u2 = std::get<0>(temp); - double mu_v2 = std::get<1>(temp); - double cov2 = std::get<2>(temp); - - CHECK_LE(abs(cov2+4), tol); - CHECK_LE(abs(mu_u2 - 6), tol); - CHECK_LE(abs(mu_v2 - 5), tol); - - std::vector u3{1,2,3}; - std::vector v3{1,1,1}; - - temp = means_and_covariance(exec, u3, v3); - double mu_u3 = std::get<0>(temp); - double mu_v3 = std::get<1>(temp); - double cov3 = std::get<2>(temp); - - // Since v is constant, covariance(u,v) = 0 against everything any u: - CHECK_LE(abs(cov3), tol); - CHECK_LE(abs(mu_u3 - 2), tol); - CHECK_LE(abs(mu_v3 - 1), tol); - // Make sure we pull the correct symbol out of means_and_covariance: - cov3 = covariance(exec, u3, v3); - CHECK_LE(abs(cov3), tol); - - cov3 = covariance(exec, v3, u3); - // Covariance is symmetric: cov(u,v) = cov(v,u) - CHECK_LE(abs(cov3), tol); - - // cov(u,u) = sigma(u)^2: - cov3 = covariance(exec, u3, u3); - double expected = double(2)/double(3); - - CHECK_LE(abs(cov3 - expected), tol); - - std::mt19937 gen(15); - // Can't template standard library on multiprecision, so use double and cast back: - std::uniform_real_distribution dis(-1.0, 1.0); - std::vector u(500); - std::vector v(500); - for(size_t i = 0; i < u.size(); ++i) - { - u[i] = (Z) dis(gen); - v[i] = (Z) dis(gen); - } - - double mu_u = boost::math::statistics::mean(u); - double mu_v = boost::math::statistics::mean(v); - double sigma_u_sq = boost::math::statistics::variance(u); - double sigma_v_sq = boost::math::statistics::variance(v); - - temp = means_and_covariance(exec, u, v); - double mu_u_ = std::get<0>(temp); - double mu_v_ = std::get<1>(temp); - double cov_uv = std::get<2>(temp); - - CHECK_LE(abs(mu_u - mu_u_), tol); - CHECK_LE(abs(mu_v - mu_v_), tol); - - // Cauchy-Schwartz inequality: - CHECK_LE(cov_uv*cov_uv, sigma_u_sq*sigma_v_sq); - // cov(X, X) = sigma(X)^2: - double cov_uu = covariance(exec, u, u); - CHECK_LE(abs(cov_uu - sigma_u_sq), tol); - double cov_vv = covariance(exec, v, v); - CHECK_LE(abs(cov_vv - sigma_v_sq), tol); -} - -template -void test_correlation_coefficient(ExecutionPolicy&& exec) -{ - using boost::math::statistics::correlation_coefficient; - using std::abs; - using std::sqrt; - - Real tol = std::numeric_limits::epsilon(); - std::vector u{1}; - std::vector v{1}; - Real rho_uv = correlation_coefficient(exec, u, v); - CHECK_NAN(rho_uv); - - u = {1,1}; - v = {1,1}; - rho_uv = correlation_coefficient(exec, u, v); - CHECK_NAN(rho_uv); - - u = {1, 2, 3}; - v = {1, 2, 3}; - rho_uv = correlation_coefficient(exec, u, v); - CHECK_LE(abs(rho_uv - 1), tol); - - u = {1, 2, 3}; - v = {-1, -2, -3}; - rho_uv = correlation_coefficient(exec, u, v); - CHECK_LE(abs(rho_uv + 1), tol); - - rho_uv = correlation_coefficient(exec, v, u); - CHECK_LE(abs(rho_uv + 1), tol); - - u = {1, 2, 3}; - v = {0, 0, 0}; - rho_uv = correlation_coefficient(exec, v, u); - CHECK_NAN(rho_uv); - - u = {1, 2, 3}; - v = {0, 0, 3}; - rho_uv = correlation_coefficient(exec, v, u); - // mu_u = 2, sigma_u^2 = 2/3, mu_v = 1, sigma_v^2 = 2, cov(u,v) = 1. - CHECK_LE(abs(rho_uv - sqrt(Real(3))/Real(2)), tol); -} - -template -void test_integer_correlation_coefficient(ExecutionPolicy&& exec) -{ - using boost::math::statistics::correlation_coefficient; - using std::abs; - using std::sqrt; - - double tol = std::numeric_limits::epsilon(); - std::vector u{1}; - std::vector v{1}; - double rho_uv = correlation_coefficient(exec, u, v); - CHECK_NAN(rho_uv); - - u = {1,1}; - v = {1,1}; - rho_uv = correlation_coefficient(exec, u, v); - CHECK_NAN(rho_uv); - - u = {1, 2, 3}; - v = {1, 2, 3}; - rho_uv = correlation_coefficient(exec, u, v); - CHECK_LE(abs(rho_uv - 1.0), tol); - - rho_uv = correlation_coefficient(exec, v, u); - CHECK_LE(abs(rho_uv - 1.0), tol); - - u = {1, 2, 3}; - v = {0, 0, 0}; - rho_uv = correlation_coefficient(exec, v, u); - CHECK_NAN(rho_uv); - - u = {1, 2, 3}; - v = {0, 0, 3}; - rho_uv = correlation_coefficient(exec, v, u); - // mu_u = 2, sigma_u^2 = 2/3, mu_v = 1, sigma_v^2 = 2, cov(u,v) = 1. - CHECK_LE(abs(rho_uv - sqrt(double(3))/double(2)), tol); -} - -int main() -{ - test_covariance(std::execution::seq); - test_covariance(std::execution::par); - test_covariance(std::execution::seq); - test_covariance(std::execution::par); - test_covariance(std::execution::seq); - test_covariance(std::execution::par); - test_covariance(std::execution::seq); - test_covariance(std::execution::par); - - test_integer_covariance(std::execution::seq); - test_integer_covariance(std::execution::par); - test_integer_covariance(std::execution::seq); - test_integer_covariance(std::execution::par); - test_integer_covariance(std::execution::seq); - test_integer_covariance(std::execution::par); - test_integer_covariance(std::execution::seq); - test_integer_covariance(std::execution::par); - - test_correlation_coefficient(std::execution::seq); - test_correlation_coefficient(std::execution::par); - test_correlation_coefficient(std::execution::seq); - test_correlation_coefficient(std::execution::par); - test_correlation_coefficient(std::execution::seq); - test_correlation_coefficient(std::execution::par); - test_correlation_coefficient(std::execution::seq); - test_correlation_coefficient(std::execution::par); - - test_integer_correlation_coefficient(std::execution::seq); - test_integer_correlation_coefficient(std::execution::par); - test_integer_correlation_coefficient(std::execution::seq); - test_integer_correlation_coefficient(std::execution::par); - test_integer_correlation_coefficient(std::execution::seq); - test_integer_correlation_coefficient(std::execution::par); - test_integer_correlation_coefficient(std::execution::seq); - test_integer_correlation_coefficient(std::execution::par); - - return boost::math::test::report_errors(); -} - -#else - -template -void test_covariance() -{ - std::cout << std::setprecision(std::numeric_limits::digits10+1); - Real tol = std::numeric_limits::epsilon(); - using std::abs; - - // Covariance of a single thing is zero: - std::array u1{8}; - std::array v1{17}; - std::tuple temp = means_and_covariance(u1, v1); - Real mu_u1 = std::get<0>(temp); - Real mu_v1 = std::get<1>(temp); - Real cov1 = std::get<2>(temp); - - CHECK_LE(abs(cov1), tol); - CHECK_LE(abs(mu_u1 - 8), tol); - CHECK_LE(abs(mu_v1 - 17), tol); - - - std::array u2{8, 4}; - std::array v2{3, 7}; - temp = means_and_covariance(u2, v2); - Real mu_u2 = std::get<0>(temp); - Real mu_v2 = std::get<1>(temp); - Real cov2 = std::get<2>(temp); - - CHECK_LE(abs(cov2+4), tol); - CHECK_LE(abs(mu_u2 - 6), tol); - CHECK_LE(abs(mu_v2 - 5), tol); - - std::vector u3{1,2,3}; - std::vector v3{1,1,1}; - - temp = means_and_covariance(u3, v3); - Real mu_u3 = std::get<0>(temp); - Real mu_v3 = std::get<1>(temp); - Real cov3 = std::get<2>(temp); - - // Since v is constant, covariance(u,v) = 0 against everything any u: - CHECK_LE(abs(cov3), tol); - CHECK_LE(abs(mu_u3 - 2), tol); - CHECK_LE(abs(mu_v3 - 1), tol); - // Make sure we pull the correct symbol out of means_and_covariance: - cov3 = covariance(u3, v3); - CHECK_LE(abs(cov3), tol); - - cov3 = covariance(v3, u3); - // Covariance is symmetric: cov(u,v) = cov(v,u) - CHECK_LE(abs(cov3), tol); - - // cov(u,u) = sigma(u)^2: - cov3 = covariance(u3, u3); - Real expected = Real(2)/Real(3); - - CHECK_LE(abs(cov3 - expected), tol); - - std::mt19937 gen(15); - // Can't template standard library on multiprecision, so use double and cast back: - std::uniform_real_distribution dis(-1.0, 1.0); - std::vector u(500); - std::vector v(500); - for(size_t i = 0; i < u.size(); ++i) - { - u[i] = (Real) dis(gen); - v[i] = (Real) dis(gen); - } - - Real mu_u = boost::math::statistics::mean(u); - Real mu_v = boost::math::statistics::mean(v); - Real sigma_u_sq = boost::math::statistics::variance(u); - Real sigma_v_sq = boost::math::statistics::variance(v); - - temp = means_and_covariance(u, v); - Real mu_u_ = std::get<0>(temp); - Real mu_v_ = std::get<1>(temp); - Real cov_uv = std::get<2>(temp); - - CHECK_LE(abs(mu_u - mu_u_), tol); - CHECK_LE(abs(mu_v - mu_v_), tol); - - // Cauchy-Schwartz inequality: - CHECK_LE(cov_uv*cov_uv, sigma_u_sq*sigma_v_sq); - // cov(X, X) = sigma(X)^2: - Real cov_uu = covariance(u, u); - CHECK_LE(abs(cov_uu - sigma_u_sq), tol); - Real cov_vv = covariance(v, v); - CHECK_LE(abs(cov_vv - sigma_v_sq), tol); -} - -template -void test_integer_covariance() -{ - std::cout << std::setprecision(std::numeric_limits::digits10+1); - double tol = std::numeric_limits::epsilon(); - using std::abs; - - // Covariance of a single thing is zero: - std::array u1{8}; - std::array v1{17}; - std::tuple temp = means_and_covariance(u1, v1); - double mu_u1 = std::get<0>(temp); - double mu_v1 = std::get<1>(temp); - double cov1 = std::get<2>(temp); - - CHECK_LE(abs(cov1), tol); - CHECK_LE(abs(mu_u1 - 8), tol); - CHECK_LE(abs(mu_v1 - 17), tol); - - - std::array u2{8, 4}; - std::array v2{3, 7}; - temp = means_and_covariance(u2, v2); - double mu_u2 = std::get<0>(temp); - double mu_v2 = std::get<1>(temp); - double cov2 = std::get<2>(temp); - - CHECK_LE(abs(cov2+4), tol); - CHECK_LE(abs(mu_u2 - 6), tol); - CHECK_LE(abs(mu_v2 - 5), tol); - - std::vector u3{1,2,3}; - std::vector v3{1,1,1}; - - temp = means_and_covariance(u3, v3); - double mu_u3 = std::get<0>(temp); - double mu_v3 = std::get<1>(temp); - double cov3 = std::get<2>(temp); - - // Since v is constant, covariance(u,v) = 0 against everything any u: - CHECK_LE(abs(cov3), tol); - CHECK_LE(abs(mu_u3 - 2), tol); - CHECK_LE(abs(mu_v3 - 1), tol); - // Make sure we pull the correct symbol out of means_and_covariance: - cov3 = covariance(u3, v3); - CHECK_LE(abs(cov3), tol); - - cov3 = covariance(v3, u3); - // Covariance is symmetric: cov(u,v) = cov(v,u) - CHECK_LE(abs(cov3), tol); - - // cov(u,u) = sigma(u)^2: - cov3 = covariance(u3, u3); - double expected = double(2)/double(3); - - CHECK_LE(abs(cov3 - expected), tol); - - std::mt19937 gen(15); - // Can't template standard library on multiprecision, so use double and cast back: - std::uniform_real_distribution dis(-1.0, 1.0); - std::vector u(500); - std::vector v(500); - for(size_t i = 0; i < u.size(); ++i) - { - u[i] = (Z) dis(gen); - v[i] = (Z) dis(gen); - } - - double mu_u = boost::math::statistics::mean(u); - double mu_v = boost::math::statistics::mean(v); - double sigma_u_sq = boost::math::statistics::variance(u); - double sigma_v_sq = boost::math::statistics::variance(v); - - temp = means_and_covariance(u, v); - double mu_u_ = std::get<0>(temp); - double mu_v_ = std::get<1>(temp); - double cov_uv = std::get<2>(temp); - - CHECK_LE(abs(mu_u - mu_u_), tol); - CHECK_LE(abs(mu_v - mu_v_), tol); - - // Cauchy-Schwartz inequality: - CHECK_LE(cov_uv*cov_uv, sigma_u_sq*sigma_v_sq); - // cov(X, X) = sigma(X)^2: - double cov_uu = covariance(u, u); - CHECK_LE(abs(cov_uu - sigma_u_sq), tol); - double cov_vv = covariance(v, v); - CHECK_LE(abs(cov_vv - sigma_v_sq), tol); -} - -template -void test_correlation_coefficient() -{ - using boost::math::statistics::correlation_coefficient; - using std::abs; - using std::sqrt; - - Real tol = std::numeric_limits::epsilon(); - std::vector u{1}; - std::vector v{1}; - Real rho_uv = correlation_coefficient(u, v); - CHECK_NAN(rho_uv); - - u = {1,1}; - v = {1,1}; - rho_uv = correlation_coefficient(u, v); - CHECK_NAN(rho_uv); - - u = {1, 2, 3}; - v = {1, 2, 3}; - rho_uv = correlation_coefficient(u, v); - CHECK_LE(abs(rho_uv - 1), tol); - - u = {1, 2, 3}; - v = {-1, -2, -3}; - rho_uv = correlation_coefficient(u, v); - CHECK_LE(abs(rho_uv + 1), tol); - - rho_uv = correlation_coefficient(v, u); - CHECK_LE(abs(rho_uv + 1), tol); - - u = {1, 2, 3}; - v = {0, 0, 0}; - rho_uv = correlation_coefficient(v, u); - CHECK_NAN(rho_uv); - - u = {1, 2, 3}; - v = {0, 0, 3}; - rho_uv = correlation_coefficient(v, u); - // mu_u = 2, sigma_u^2 = 2/3, mu_v = 1, sigma_v^2 = 2, cov(u,v) = 1. - CHECK_LE(abs(rho_uv - sqrt(Real(3))/Real(2)), tol); -} - -template -void test_integer_correlation_coefficient() -{ - using boost::math::statistics::correlation_coefficient; - using std::abs; - using std::sqrt; - - double tol = std::numeric_limits::epsilon(); - std::vector u{1}; - std::vector v{1}; - double rho_uv = correlation_coefficient(u, v); - CHECK_NAN(rho_uv); - - u = {1,1}; - v = {1,1}; - rho_uv = correlation_coefficient(u, v); - CHECK_NAN(rho_uv); - - u = {1, 2, 3}; - v = {1, 2, 3}; - rho_uv = correlation_coefficient(u, v); - CHECK_LE(abs(rho_uv - 1.0), tol); - - rho_uv = correlation_coefficient(v, u); - CHECK_LE(abs(rho_uv - 1.0), tol); - - u = {1, 2, 3}; - v = {0, 0, 0}; - rho_uv = correlation_coefficient(v, u); - CHECK_NAN(rho_uv); - - u = {1, 2, 3}; - v = {0, 0, 3}; - rho_uv = correlation_coefficient(v, u); - // mu_u = 2, sigma_u^2 = 2/3, mu_v = 1, sigma_v^2 = 2, cov(u,v) = 1. - CHECK_LE(abs(rho_uv - sqrt(double(3))/double(2)), tol); -} - -int main() -{ - test_covariance(); - test_covariance(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_covariance(); -#endif - test_covariance(); - - test_integer_covariance(); - test_integer_covariance(); - test_integer_covariance(); - test_integer_covariance(); - - test_correlation_coefficient(); - test_correlation_coefficient(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_correlation_coefficient(); -#endif - test_correlation_coefficient(); - - test_integer_correlation_coefficient(); - test_integer_correlation_coefficient(); - test_integer_correlation_coefficient(); - test_integer_correlation_coefficient(); - - return boost::math::test::report_errors(); -} - -#endif diff --git a/test/cardinal_cubic_b_spline_test.cpp b/test/cardinal_cubic_b_spline_test.cpp deleted file mode 100644 index 5eb0c1cb04..0000000000 --- a/test/cardinal_cubic_b_spline_test.cpp +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright Nick Thompson, 2017 -// 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) - -#define BOOST_TEST_MODULE test_cubic_b_spline -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -using std::sin; -using boost::multiprecision::cpp_bin_float_50; -using boost::math::constants::third; -using boost::math::constants::half; - -template -void test_b3_spline() -{ - std::cout << "Testing evaluation of spline basis functions on type " << boost::typeindex::type_id().pretty_name() << "\n"; - // Outside the support: - Real eps = std::numeric_limits::epsilon(); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline(Real(2.5)), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline(Real(-2.5)), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_prime(Real(2.5)), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_prime(Real(-2.5)), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_double_prime(Real(2.5)), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_double_prime(Real(-2.5)), (Real) 0); - - - // On the boundary of support: - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline(2), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline(-2), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_prime(2), (Real) 0); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_prime(-2), (Real) 0); - - // Special values: - BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline(-1), third()*half(), eps); - BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline( 1), third()*half(), eps); - BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline(0), 2*third(), eps); - - BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline_prime(-1), half(), eps); - BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline_prime( 1), -half(), eps); - BOOST_CHECK_SMALL(boost::math::interpolators::detail::b3_spline_prime(0), eps); - - // Properties: B3 is an even function, B3' is an odd function. - for (size_t i = 1; i < 200; ++i) - { - Real arg = i*Real(0.01); - BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline(arg), boost::math::interpolators::detail::b3_spline(arg), eps); - BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline_prime(-arg), -boost::math::interpolators::detail::b3_spline_prime(arg), eps); - BOOST_CHECK_CLOSE(boost::math::interpolators::detail::b3_spline_double_prime(-arg), boost::math::interpolators::detail::b3_spline_double_prime(arg), eps); - } - -} -/* - * This test ensures that the interpolant s(x_j) = f(x_j) at all grid points. - */ -template -void test_interpolation_condition() -{ - using std::sqrt; - std::cout << "Testing interpolation condition for cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; - std::random_device rd; - std::mt19937 gen(rd()); - boost::random::uniform_real_distribution dis(1, 10); - std::vector v(5000); - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = dis(gen); - } - - Real step = static_cast(0.01); - Real a = Real(5); - boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), a, step); - - for (size_t i = 0; i < v.size(); ++i) - { - Real y = spline(i*step + a); - // This seems like a very large tolerance, but I don't know of any other interpolators - // that will be able to do much better on random data. - BOOST_CHECK_CLOSE(y, v[i], 10000*sqrt(std::numeric_limits::epsilon())); - } - -} - - -template -void test_constant_function() -{ - std::cout << "Testing that constants are interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; - std::vector v(500); - const Real constant = Real(50.2); - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = constant; - } - - Real step = static_cast(0.02); - Real a = 5; - boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), a, step); - - for (size_t i = 0; i < v.size(); ++i) - { - // Do not test at interpolation point; we already know it works there: - Real y = spline(i*step + a + Real(0.001)); - BOOST_CHECK_CLOSE(y, constant, 10*std::numeric_limits::epsilon()); - Real y_prime = spline.prime(i*step + a + Real(0.002)); - BOOST_CHECK_SMALL(y_prime, 5000*std::numeric_limits::epsilon()); - Real y_double_prime = spline.double_prime(i*step + a + Real(0.002)); - BOOST_CHECK_SMALL(y_double_prime, 5000*std::numeric_limits::epsilon()); - - } - - // Test that correctly specified left and right-derivatives work properly: - spline = boost::math::interpolators::cardinal_cubic_b_spline(v.data(), v.size(), a, step, 0, 0); - - for (size_t i = 0; i < v.size(); ++i) - { - Real y = spline(i*step + a + Real(0.002)); - BOOST_CHECK_CLOSE(y, constant, std::numeric_limits::epsilon()); - Real y_prime = spline.prime(i*step + a + Real(0.002)); - BOOST_CHECK_SMALL(y_prime, std::numeric_limits::epsilon()); - } - - // - // Again with iterator constructor: - // - boost::math::interpolators::cardinal_cubic_b_spline spline2(v.begin(), v.end(), a, step); - - for (size_t i = 0; i < v.size(); ++i) - { - // Do not test at interpolation point; we already know it works there: - Real y = spline2(i*step + a + Real(0.001)); - BOOST_CHECK_CLOSE(y, constant, 10 * std::numeric_limits::epsilon()); - Real y_prime = spline2.prime(i*step + a + Real(0.002)); - BOOST_CHECK_SMALL(y_prime, 5000 * std::numeric_limits::epsilon()); - } - - // Test that correctly specified left and right-derivatives work properly: - spline2 = boost::math::interpolators::cardinal_cubic_b_spline(v.begin(), v.end(), a, step, 0, 0); - - for (size_t i = 0; i < v.size(); ++i) - { - Real y = spline2(i*step + a + Real(0.002)); - BOOST_CHECK_CLOSE(y, constant, std::numeric_limits::epsilon()); - Real y_prime = spline2.prime(i*step + a + Real(0.002)); - BOOST_CHECK_SMALL(y_prime, std::numeric_limits::epsilon()); - } -} - - -template -void test_affine_function() -{ - using std::sqrt; - std::cout << "Testing that affine functions are interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; - std::vector v(500); - Real a = 10; - Real b = 8; - Real step = static_cast(0.005); - - auto f = [a, b](Real x) { return a*x + b; }; - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = f(i*step); - } - - boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), 0, step); - - for (size_t i = 0; i < v.size() - 1; ++i) - { - Real arg = static_cast(i*step + Real(0.0001)); - Real y = spline(arg); - BOOST_CHECK_CLOSE(y, f(arg), sqrt(std::numeric_limits::epsilon())); - Real y_prime = spline.prime(arg); - BOOST_CHECK_CLOSE(y_prime, a, 100*sqrt(std::numeric_limits::epsilon())); - } - - // Test that correctly specified left and right-derivatives work properly: - spline = boost::math::interpolators::cardinal_cubic_b_spline(v.data(), v.size(), 0, step, a, a); - - for (size_t i = 0; i < v.size() - 1; ++i) - { - Real arg = static_cast(i*step + Real(0.0001)); - Real y = spline(arg); - BOOST_CHECK_CLOSE(y, f(arg), sqrt(std::numeric_limits::epsilon())); - Real y_prime = spline.prime(arg); - BOOST_CHECK_CLOSE(y_prime, a, 100*sqrt(std::numeric_limits::epsilon())); - } -} - - -template -void test_quadratic_function() -{ - using std::sqrt; - std::cout << "Testing that quadratic functions are interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; - std::vector v(500); - Real a = static_cast(1.2); - Real b = static_cast(-3.4); - Real c = static_cast(-8.6); - Real step = static_cast(0.01); - - auto f = [a, b, c](Real x) { return a*x*x + b*x + c; }; - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = f(i*step); - } - - boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), 0, step); - - for (size_t i = 0; i < v.size() -1; ++i) - { - Real arg = static_cast(i*step + Real(0.001)); - Real y = spline(arg); - BOOST_CHECK_CLOSE(y, f(arg), Real(0.1)); - Real y_prime = spline.prime(arg); - BOOST_CHECK_CLOSE(y_prime, 2*a*arg + b, Real(2.0)); - } -} - - -template -void test_circ_conic_function() -{ - using std::sqrt; - std::cout << "Testing that conic section of a circle is interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << '\n'; - std::vector v(500); - Real cv = Real(0.1); - Real w = Real(2.0); - Real step = Real(2 * w / (v.size() - 1)); - - auto f = [cv](Real x) { return cv * x * x / (1 + sqrt(1 - cv * cv * x * x)); }; - auto df = [cv](Real x) { return cv * x / sqrt(1 - cv * cv * x * x); }; - - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = f(-w + i * step); - } - - boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), -w, step); - - Real tol = 100 * sqrt(std::numeric_limits::epsilon()); - if ((std::numeric_limits::digits > 100) || !std::numeric_limits::digits) - tol *= 500000; - // First check derivatives exactly at end points - BOOST_CHECK_CLOSE(spline.prime(-w), df(-w), tol); - BOOST_CHECK_CLOSE(spline.prime(w), df(w), tol); - - for (size_t i = 0; i < v.size() - 1; ++i) - { - Real arg = -w + i * step + Real(0.001); - Real y = spline(arg); - BOOST_CHECK_CLOSE(y, f(arg), Real(2.0)); - Real y_prime = spline.prime(arg); - BOOST_CHECK_CLOSE(y_prime, df(arg), Real(1.0)); - } -} - - -template -void test_trig_function() -{ - std::cout << "Testing that sine functions are interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; - std::mt19937 gen; - std::vector v(500); - Real x0 = 1; - Real step = Real(0.125); - - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = sin(x0 + step * i); - } - - boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), x0, step); - - boost::random::uniform_real_distribution abscissa(x0, x0 + 499 * step); - - for (size_t i = 0; i < v.size(); ++i) - { - Real x = abscissa(gen); - Real y = spline(x); - BOOST_CHECK_CLOSE(y, Real(sin(x)), Real(1.0)); - auto y_prime = spline.prime(x); - BOOST_CHECK_CLOSE(y_prime, Real(cos(x)), Real(2.0)); - } -} - -template -void test_copy_move() -{ - std::cout << "Testing that copy/move operation succeed on cubic b spline\n"; - std::vector v(500); - Real x0 = 1; - Real step = static_cast(0.125); - constexpr Real tol = Real(0.01); - - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = sin(x0 + step * i); - } - - boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), x0, step); - - - // Default constructor should compile so that splines can be member variables: - boost::math::interpolators::cardinal_cubic_b_spline d; - d = boost::math::interpolators::cardinal_cubic_b_spline(v.data(), v.size(), x0, step); - BOOST_CHECK_CLOSE(d(x0), Real(sin(x0)), tol); - // Passing to lambda should compile: - auto f = [=](Real x) { return d(x); }; - // Make sure this variable is used. - BOOST_CHECK_CLOSE(f(x0), Real(sin(x0)), tol); - - // Move operations should compile. - auto s = std::move(spline); - - // Copy operations should compile: - boost::math::interpolators::cardinal_cubic_b_spline c = d; - BOOST_CHECK_CLOSE(c(x0), Real(sin(x0)), tol); - - // Test with std::bind: - auto h = std::bind(&boost::math::interpolators::cardinal_cubic_b_spline::operator(), &s, std::placeholders::_1); - BOOST_CHECK_CLOSE(h(x0), Real(sin(x0)), tol); -} - -template -void test_outside_interval() -{ - std::cout << "Testing that the spline can be evaluated outside the interpolation interval\n"; - std::vector v(400); - Real x0 = 1; - Real step = Real(0.125); - - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = sin(x0 + step * i); - } - - boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), x0, step); - - // There's no test here; it simply does it's best to be an extrapolator. - // - std::ostream cnull(0); - cnull << spline(0); - cnull << spline(2000); -} - -BOOST_AUTO_TEST_CASE(test_cubic_b_spline) -{ - #ifdef __STDCPP_FLOAT32_T__ - - test_b3_spline(); - test_interpolation_condition(); - test_constant_function(); - test_affine_function(); - test_quadratic_function(); - test_circ_conic_function(); - test_trig_function(); - - #else - - test_b3_spline(); - test_interpolation_condition(); - test_constant_function(); - test_affine_function(); - test_quadratic_function(); - test_circ_conic_function(); - test_trig_function(); - - #endif - - #ifdef __STDCPP_FLOAT64_T__ - - test_b3_spline(); - test_interpolation_condition(); - test_constant_function(); - test_affine_function(); - test_quadratic_function(); - test_circ_conic_function(); - test_trig_function(); - test_copy_move(); - test_outside_interval(); - - #else - - test_b3_spline(); - test_interpolation_condition(); - test_constant_function(); - test_affine_function(); - test_quadratic_function(); - test_circ_conic_function(); - test_trig_function(); - test_copy_move(); - test_outside_interval(); - - #endif - - #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - - test_b3_spline(); - test_interpolation_condition(); - test_constant_function(); - test_affine_function(); - test_quadratic_function(); - test_circ_conic_function(); - test_trig_function(); - - #endif - - test_b3_spline(); - test_interpolation_condition(); - test_constant_function(); - test_affine_function(); - test_quadratic_function(); - test_trig_function(); -} diff --git a/test/cardinal_quadratic_b_spline_test.cpp b/test/cardinal_quadratic_b_spline_test.cpp deleted file mode 100644 index 3955d4f572..0000000000 --- a/test/cardinal_quadratic_b_spline_test.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright Nick Thompson, 2019 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#include -using boost::math::interpolators::cardinal_quadratic_b_spline; - -#if __has_include() -# include -#endif - -template -void test_constant() -{ - Real c = Real(7.2); - Real t0 = 0; - Real h = Real(1)/Real(16); - size_t n = 512; - std::vector v(n, c); - auto qbs = cardinal_quadratic_b_spline(v.data(), v.size(), t0, h); - - size_t i = 0; - while (i < n) { - Real t = t0 + i*h; - CHECK_ULP_CLOSE(c, qbs(t), 2); - CHECK_MOLLIFIED_CLOSE(0, qbs.prime(t), (std::numeric_limits::digits > 100 ? 200 : 100) * std::numeric_limits::epsilon()); - ++i; - } - - i = 0; - while (i < n) { - Real t = t0 + i*h + h/2; - CHECK_ULP_CLOSE(c, qbs(t), 2); - CHECK_MOLLIFIED_CLOSE(0, qbs.prime(t), 300*std::numeric_limits::epsilon()); - t = t0 + i*h + h/4; - CHECK_ULP_CLOSE(c, qbs(t), 2); - CHECK_MOLLIFIED_CLOSE(0, qbs.prime(t), (std::numeric_limits::digits > 100 ? 300 : 150) * std::numeric_limits::epsilon()); - ++i; - } -} - -template -void test_linear() -{ - Real m = Real(8.3); - Real b = Real(7.2); - Real t0 = 0; - Real h = Real(1)/Real(16); - size_t n = 512; - std::vector y(n); - for (size_t i = 0; i < n; ++i) { - Real t = i*h; - y[i] = m*t + b; - } - auto qbs = cardinal_quadratic_b_spline(y.data(), y.size(), t0, h); - - size_t i = 0; - while (i < n) { - Real t = t0 + i*h; - CHECK_ULP_CLOSE(m*t+b, qbs(t), 2); - CHECK_ULP_CLOSE(m, qbs.prime(t), 820); - ++i; - } - - i = 0; - while (i < n) { - Real t = t0 + i*h + h/2; - CHECK_ULP_CLOSE(m*t+b, qbs(t), 2); - CHECK_MOLLIFIED_CLOSE(m, qbs.prime(t), 1500*std::numeric_limits::epsilon()); - t = t0 + i*h + h/4; - CHECK_ULP_CLOSE(m*t+b, qbs(t), 3); - CHECK_MOLLIFIED_CLOSE(m, qbs.prime(t), 1500*std::numeric_limits::epsilon()); - ++i; - } -} - -template -void test_quadratic() -{ - Real a = Real(8.2); - Real b = Real(7.2); - Real c = Real(-9.2); - Real t0 = 0; - Real h = Real(1)/Real(16); - size_t n = 513; - std::vector y(n); - for (size_t i = 0; i < n; ++i) { - Real t = i*h; - y[i] = a*t*t + b*t + c; - } - Real t_max = t0 + (n-1)*h; - auto qbs = cardinal_quadratic_b_spline(y, t0, h, b, 2*a*t_max + b); - - size_t i = 0; - while (i < n) { - Real t = t0 + i*h; - CHECK_ULP_CLOSE(a*t*t + b*t + c, qbs(t), 2); - ++i; - } - - i = 0; - while (i < n) { - Real t = t0 + i*h + h/2; - CHECK_ULP_CLOSE(a*t*t + b*t + c, qbs(t), 47); - - t = t0 + i*h + h/4; - if (!CHECK_ULP_CLOSE(a*t*t + b*t + c, qbs(t), 104)) { - std::cerr << " Problem abscissa t = " << t << "\n"; - } - ++i; - } -} - -int main() -{ - #ifdef __STDCPP_FLOAT32_T__ - test_constant(); - test_linear(); - #else - test_constant(); - test_linear(); - #endif - - #ifdef __STDCPP_FLOAT64_T__ - test_constant(); - test_linear(); - test_quadratic(); - #else - test_constant(); - test_linear(); - test_quadratic(); - #endif - -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_constant(); - test_linear(); - test_quadratic(); -#endif - - return boost::math::test::report_errors(); -} diff --git a/test/cardinal_trigonometric_test.cpp b/test/cardinal_trigonometric_test.cpp deleted file mode 100644 index 4207681145..0000000000 --- a/test/cardinal_trigonometric_test.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright Nick Thompson, 2019 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - - -using std::sin; -using boost::math::constants::two_pi; -using boost::math::interpolators::cardinal_trigonometric; - -template -void test_constant() -{ - Real t0 = 0; - Real h = 1; - for(size_t n = 1; n < 20; ++n) - { - Real c = 8; - std::vector v(n, c); - auto ct = cardinal_trigonometric(v, t0, h); - CHECK_ULP_CLOSE(c, ct(0.3), 3); - CHECK_ULP_CLOSE(c*h*n, ct.integrate(), 3); - CHECK_ULP_CLOSE(c*c*h*n, ct.squared_l2(), 3); - CHECK_MOLLIFIED_CLOSE(Real(0), ct.prime(0.8), 25*std::numeric_limits::epsilon()); - CHECK_MOLLIFIED_CLOSE(Real(0), ct.double_prime(0.8), 25*std::numeric_limits::epsilon()); - } -} - -template -void test_interpolation_condition() -{ - std::mt19937 gen(1234); - std::uniform_real_distribution dis(1, 10); - - for(size_t n = 1; n < 20; ++n) { - Real t0 = dis(gen); - Real h = dis(gen); - std::vector v(n); - for (size_t i = 0; i < n; ++i) { - v[i] = dis(gen); - } - auto ct = cardinal_trigonometric(v, t0, h); - for (size_t i = 0; i < n; ++i) { - Real arg = t0 + i*h; - Real expected = v[i]; - Real computed = ct(arg); - if(!CHECK_ULP_CLOSE(expected, computed, 5*n)) - { - std::cerr << " Samples: " << n << "\n"; - } - } - } - -} - - -#ifdef BOOST_HAS_FLOAT128 -void test_constant_q() -{ - __float128 t0 = 0; - __float128 h = 1; - for(size_t n = 1; n < 20; ++n) - { - __float128 c = 8; - std::vector<__float128> v(n, c); - auto ct = cardinal_trigonometric(v, t0, h); - CHECK_ULP_CLOSE(boost::multiprecision::float128(c), boost::multiprecision::float128(ct(0.3)), 3); - CHECK_ULP_CLOSE(boost::multiprecision::float128(c*h*n), boost::multiprecision::float128(ct.integrate()), 3); - } -} -#endif - - -template -void test_sampled_sine() -{ - using std::sin; - using std::cos; - for (unsigned n = 15; n < 50; ++n) - { - Real t0 = 0; - Real T = 1; - Real h = T/n; - std::vector v(n); - auto s = [&](Real t) { return sin(two_pi()*(t-t0)/T);}; - auto s_prime = [&](Real t) { return two_pi()*cos(two_pi()*(t-t0)/T)/T;}; - auto s_double_prime = [&](Real t) { return -two_pi()*two_pi()*sin(two_pi()*(t-t0)/T)/(T*T);}; - for(size_t j = 0; j < v.size(); ++j) - { - Real t = t0 + j*h; - v[j] = s(t); - } - auto ct = cardinal_trigonometric(v, t0, h); - CHECK_ULP_CLOSE(T, ct.period(), 3); - std::mt19937 gen(1234); - std::uniform_real_distribution dist(0, 500); - - unsigned j = 0; - while (j++ < 50) { - Real arg = dist(gen); - Real expected = s(arg); - Real computed = ct(arg); - CHECK_MOLLIFIED_CLOSE(expected, computed, std::numeric_limits::epsilon()*4000); - - expected = s_prime(arg); - computed = ct.prime(arg); - CHECK_MOLLIFIED_CLOSE(expected, computed, 18000*std::numeric_limits::epsilon()); - - expected = s_double_prime(arg); - computed = ct.double_prime(arg); - CHECK_MOLLIFIED_CLOSE(expected, computed, 100000*std::numeric_limits::epsilon()); - - } - CHECK_MOLLIFIED_CLOSE(Real(0), ct.integrate(), std::numeric_limits::epsilon()); - } -} - -template -void test_bump() -{ - using std::exp; - using std::abs; - using std::sqrt; - using std::pow; - auto bump = [](Real x)->Real { if (abs(x) >= 1) { return Real(0); } return exp(-Real(1)/(Real(1)-x*x)); }; - auto bump_prime = [](Real x)->Real { - if (abs(x) >= 1) { return Real(0); } - - return -2*x*exp(-Real(1)/(Real(1)-x*x))/pow(1-x*x,2); - }; - - auto bump_double_prime = [](Real x)->Real { - if (abs(x) >= 1) { return Real(0); } - - return (6*pow(x,4)-2)*exp(-Real(1)/(Real(1)-x*x))/pow(1-x*x,4); - }; - - - Real t0 = -1; - size_t n = 4096; - Real h = Real(2)/Real(n); - - std::vector v(n); - for(size_t i = 0; i < n; ++i) - { - Real t = t0 + i*h; - v[i] = bump(t); - } - - auto ct = cardinal_trigonometric(v, t0, h); - std::mt19937 gen(323723); - std::uniform_real_distribution dis(-0.9, 0.9); - - size_t i = 0; - while (i++ < 1000) - { - Real t = static_cast(dis(gen)); - Real expected = bump(t); - Real computed = ct(t); - if(!CHECK_MOLLIFIED_CLOSE(expected, computed, 2*std::numeric_limits::epsilon())) { - std::cerr << " Problem occurred at abscissa " << t << "\n"; - } - - expected = bump_prime(t); - computed = ct.prime(t); - if(!CHECK_MOLLIFIED_CLOSE(expected, computed, 4000*std::numeric_limits::epsilon())) { - std::cerr << " Problem occurred at abscissa " << t << "\n"; - } - - expected = bump_double_prime(t); - computed = ct.double_prime(t); - if(!CHECK_MOLLIFIED_CLOSE(expected, computed, 4000*4000*std::numeric_limits::epsilon())) { - std::cerr << " Problem occurred at abscissa " << t << "\n"; - } - - - } - - // Wolfram Alpha: - // NIntegrate[Exp[-1/(1-x*x)],{x,-1,1}] - CHECK_ULP_CLOSE(Real(0.443993816168079437823L), ct.integrate(), 3); - - // NIntegrate[Exp[-2/(1-x*x)],{x,-1,1}] - CHECK_ULP_CLOSE(Real(0.1330861208449942715569473279553285713625791551628130055345002588895389L), ct.squared_l2(), 1); - - -} - - -int main() -{ - -#ifdef TEST1 - test_constant(); - test_sampled_sine(); - test_bump(); - test_interpolation_condition(); -#endif - - -#ifdef TEST2 - test_constant(); - test_sampled_sine(); - test_bump(); - test_interpolation_condition(); -#endif - -#ifdef TEST3 - test_constant(); - test_sampled_sine(); - test_bump(); - test_interpolation_condition(); -#endif - -#ifdef TEST4 -#ifdef BOOST_HAS_FLOAT128 -test_constant_q(); -#endif -#endif - - return boost::math::test::report_errors(); -} diff --git a/test/catmull_rom_test.cpp b/test/catmull_rom_test.cpp deleted file mode 100644 index 71ea96dc43..0000000000 --- a/test/catmull_rom_test.cpp +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright Nick Thompson, 2017 - * 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) - */ -#define BOOST_TEST_MODULE catmull_rom_test - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -using std::abs; -using boost::multiprecision::cpp_bin_float_50; -using boost::math::catmull_rom; - -template -void test_alpha_distance() -{ - Real tol = std::numeric_limits::epsilon(); - std::array v1 = {0,0,0}; - std::array v2 = {1,0,0}; - Real alpha = 0.5; - Real d = boost::math::detail::alpha_distance>(v1, v2, alpha); - BOOST_CHECK_CLOSE_FRACTION(d, 1, tol); - - d = boost::math::detail::alpha_distance>(v1, v2, 0.0); - BOOST_CHECK_CLOSE_FRACTION(d, 1, tol); - - d = boost::math::detail::alpha_distance>(v1, v2, 1.0); - BOOST_CHECK_CLOSE_FRACTION(d, 1, tol); - - v2[0] = 2; - d = boost::math::detail::alpha_distance>(v1, v2, alpha); - BOOST_CHECK_CLOSE_FRACTION(d, pow(2, (Real)1/ (Real) 2), tol); - - d = boost::math::detail::alpha_distance>(v1, v2, 0.0); - BOOST_CHECK_CLOSE_FRACTION(d, 1, tol); - - d = boost::math::detail::alpha_distance>(v1, v2, 1.0); - BOOST_CHECK_CLOSE_FRACTION(d, 2, tol); -} - - -template -void test_linear() -{ - std::cout << "Testing that the Catmull-Rom spline interpolates linear functions correctly on type " - << boost::typeindex::type_id().pretty_name() << "\n"; - - Real tol = 10*std::numeric_limits::epsilon(); - std::vector> v(4); - v[0] = {0,0,0}; - v[1] = {1,0,0}; - v[2] = {2,0,0}; - v[3] = {3,0,0}; - catmull_rom> cr(std::move(v)); - - // Test that the interpolation condition is obeyed: - BOOST_CHECK_CLOSE_FRACTION(cr.max_parameter(), 3, tol); - auto p0 = cr(0.0); - BOOST_CHECK_SMALL(p0[0], tol); - BOOST_CHECK_SMALL(p0[1], tol); - BOOST_CHECK_SMALL(p0[2], tol); - auto p1 = cr(1.0); - BOOST_CHECK_CLOSE_FRACTION(p1[0], 1, tol); - BOOST_CHECK_SMALL(p1[1], tol); - BOOST_CHECK_SMALL(p1[2], tol); - - auto p2 = cr(2.0); - BOOST_CHECK_CLOSE_FRACTION(p2[0], 2, tol); - BOOST_CHECK_SMALL(p2[1], tol); - BOOST_CHECK_SMALL(p2[2], tol); - - - auto p3 = cr(3.0); - BOOST_CHECK_CLOSE_FRACTION(p3[0], 3, tol); - BOOST_CHECK_SMALL(p3[1], tol); - BOOST_CHECK_SMALL(p3[2], tol); - - Real s = cr.parameter_at_point(0); - BOOST_CHECK_SMALL(s, tol); - - s = cr.parameter_at_point(1); - BOOST_CHECK_CLOSE_FRACTION(s, 1, tol); - - s = cr.parameter_at_point(2); - BOOST_CHECK_CLOSE_FRACTION(s, 2, tol); - - s = cr.parameter_at_point(3); - BOOST_CHECK_CLOSE_FRACTION(s, 3, tol); - - // Test that the function is linear on the interval [1,2]: - for (double s = 1; s < 2; s += 0.01) - { - auto p = cr(s); - BOOST_CHECK_CLOSE_FRACTION(p[0], s, tol); - BOOST_CHECK_SMALL(p[1], tol); - BOOST_CHECK_SMALL(p[2], tol); - - auto tangent = cr.prime(s); - BOOST_CHECK_CLOSE_FRACTION(tangent[0], 1, tol); - BOOST_CHECK_SMALL(tangent[1], tol); - BOOST_CHECK_SMALL(tangent[2], tol); - } - -} - -template -void test_circle() -{ - using boost::math::constants::pi; - using std::cos; - using std::sin; - - std::cout << "Testing that the Catmull-Rom spline interpolates circles correctly on type " - << boost::typeindex::type_id().pretty_name() << "\n"; - - Real tol = 10*std::numeric_limits::epsilon(); - std::vector> v(20*sizeof(Real)); - std::vector> u(20*sizeof(Real)); - for (size_t i = 0; i < v.size(); ++i) - { - Real theta = ((Real) i/ (Real) v.size())*2*pi(); - v[i] = {cos(theta), sin(theta)}; - u[i] = v[i]; - } - catmull_rom> circle(std::move(v), true); - - // Interpolation condition: - for (size_t i = 0; i < v.size(); ++i) - { - Real s = circle.parameter_at_point(i); - auto p = circle(s); - Real x = p[0]; - Real y = p[1]; - if (abs(x) < std::numeric_limits::epsilon()) - { - BOOST_CHECK_SMALL(u[i][0], tol); - } - if (abs(y) < std::numeric_limits::epsilon()) - { - BOOST_CHECK_SMALL(u[i][1], tol); - } - else - { - BOOST_CHECK_CLOSE_FRACTION(x, u[i][0], tol); - BOOST_CHECK_CLOSE_FRACTION(y, u[i][1], tol); - } - } - - Real max_s = circle.max_parameter(); - for(Real s = 0; s < max_s; s += Real(0.01)) - { - auto p = circle(s); - Real x = p[0]; - Real y = p[1]; - BOOST_CHECK_CLOSE_FRACTION(x*x+y*y, 1, 0.001); - } -} - - -template -void test_affine_invariance() -{ - std::cout << "Testing that the Catmull-Rom spline is affine invariant in dimension " - << dimension << " on type " - << boost::typeindex::type_id().pretty_name() << "\n"; - - Real tol = 1000*std::numeric_limits::epsilon(); - std::vector> v(100); - std::vector> u(100); - std::mt19937_64 gen(438232); - Real inv_denom = (Real) 100/( (Real) (gen.max)() + (Real) 2); - for(size_t j = 0; j < dimension; ++j) - { - v[0][j] = gen()*inv_denom; - u[0][j] = v[0][j]; - } - - for (size_t i = 1; i < v.size(); ++i) - { - for(size_t j = 0; j < dimension; ++j) - { - v[i][j] = v[i-1][j] + gen()*inv_denom; - u[i][j] = v[i][j]; - } - } - std::array affine_shift; - for (size_t j = 0; j < dimension; ++j) - { - affine_shift[j] = gen()*inv_denom; - } - - catmull_rom> cr1(std::move(v)); - - for(size_t i = 0; i< u.size(); ++i) - { - for(size_t j = 0; j < dimension; ++j) - { - u[i][j] += affine_shift[j]; - } - } - - catmull_rom> cr2(std::move(u)); - - BOOST_CHECK_CLOSE_FRACTION(cr1.max_parameter(), cr2.max_parameter(), tol); - - Real ds = cr1.max_parameter()/1024; - for (Real s = 0; s < cr1.max_parameter(); s += ds) - { - auto p0 = cr1(s); - auto p1 = cr2(s); - auto tangent0 = cr1.prime(s); - auto tangent1 = cr2.prime(s); - for (size_t j = 0; j < dimension; ++j) - { - BOOST_CHECK_CLOSE_FRACTION(p0[j] + affine_shift[j], p1[j], tol); - if (abs(tangent0[j]) > 5000*tol) - { - BOOST_CHECK_CLOSE_FRACTION(tangent0[j], tangent1[j], 5000*tol); - } - } - } -} - -template -void test_helix() -{ - using boost::math::constants::pi; - std::cout << "Testing that the Catmull-Rom spline interpolates helices correctly on type " - << boost::typeindex::type_id().pretty_name() << "\n"; - - Real tol = 0.001; - std::vector> v(400*sizeof(Real)); - for (size_t i = 0; i < v.size(); ++i) - { - Real theta = ((Real) i/ (Real) v.size())*2*pi(); - v[i] = {cos(theta), sin(theta), theta}; - } - catmull_rom> helix(std::move(v)); - - // Interpolation condition: - for (size_t i = 0; i < v.size(); ++i) - { - Real s = helix.parameter_at_point(i); - auto p = helix(s); - Real t = p[2]; - - Real x = p[0]; - Real y = p[1]; - if (abs(x) < tol) - { - BOOST_CHECK_SMALL(Real(cos(t)), tol); - } - if (abs(y) < tol) - { - BOOST_CHECK_SMALL(Real(sin(t)), tol); - } - else - { - BOOST_CHECK_CLOSE_FRACTION(x, cos(t), tol); - BOOST_CHECK_CLOSE_FRACTION(y, sin(t), tol); - } - } - - Real max_s = helix.max_parameter(); - for(Real s = helix.parameter_at_point(1); s < max_s; s += 0.01) - { - auto p = helix(s); - Real x = p[0]; - Real y = p[1]; - Real t = p[2]; - BOOST_CHECK_CLOSE_FRACTION(x*x+y*y, (Real) 1, (Real) 0.01); - if (abs(x) < 0.01) - { - BOOST_CHECK_SMALL(Real(cos(t)), (Real) 0.05); - } - if (abs(y) < 0.01) - { - BOOST_CHECK_SMALL(Real(sin(t)), (Real) 0.05); - } - else - { - BOOST_CHECK_CLOSE_FRACTION(x, Real(cos(t)), (Real) 0.05); - BOOST_CHECK_CLOSE_FRACTION(y, Real(sin(t)), (Real) 0.05); - } - } -} - - -template -class mypoint3d -{ -public: - // Must define a value_type: - typedef Real value_type; - - // Regular constructor: - mypoint3d(Real x, Real y, Real z) - { - m_vec[0] = x; - m_vec[1] = y; - m_vec[2] = z; - } - - // Must define a default constructor: - mypoint3d() {} - - // Must define array access: - Real operator[](size_t i) const - { - return m_vec[i]; - } - - // Array element assignment: - Real& operator[](size_t i) - { - return m_vec[i]; - } - - -private: - std::array m_vec; -}; - - -// Must define the free function "size()": -template -constexpr std::size_t size(const mypoint3d&) -{ - return 3; -} - -template -void test_data_representations() -{ - std::cout << "Testing that the Catmull-Rom spline works with multiple data representations.\n"; - mypoint3d p0(Real(0.1), Real(0.2), Real(0.3)); - mypoint3d p1(Real(0.2), Real(0.3), Real(0.4)); - mypoint3d p2(Real(0.3), Real(0.4), Real(0.5)); - mypoint3d p3(Real(0.4), Real(0.5), Real(0.6)); - mypoint3d p4(Real(0.5), Real(0.6), Real(0.7)); - mypoint3d p5(Real(0.6), Real(0.7), Real(0.8)); - - - // Tests initializer_list: - catmull_rom> cat({p0, p1, p2, p3, p4, p5}); - - Real tol = Real(0.001); - auto p = cat(cat.parameter_at_point(0)); - BOOST_CHECK_CLOSE_FRACTION(p[0], p0[0], tol); - BOOST_CHECK_CLOSE_FRACTION(p[1], p0[1], tol); - BOOST_CHECK_CLOSE_FRACTION(p[2], p0[2], tol); - p = cat(cat.parameter_at_point(1)); - BOOST_CHECK_CLOSE_FRACTION(p[0], p1[0], tol); - BOOST_CHECK_CLOSE_FRACTION(p[1], p1[1], tol); - BOOST_CHECK_CLOSE_FRACTION(p[2], p1[2], tol); -} - -template -void test_random_access_container() -{ - std::cout << "Testing that the Catmull-Rom spline works with multiple data representations.\n"; - mypoint3d p0(0.1, 0.2, 0.3); - mypoint3d p1(0.2, 0.3, 0.4); - mypoint3d p2(0.3, 0.4, 0.5); - mypoint3d p3(0.4, 0.5, 0.6); - mypoint3d p4(0.5, 0.6, 0.7); - mypoint3d p5(0.6, 0.7, 0.8); - - boost::numeric::ublas::vector> u(6); - u[0] = p0; - u[1] = p1; - u[2] = p2; - u[3] = p3; - u[4] = p4; - u[5] = p5; - - // Tests initializer_list: - catmull_rom, decltype(u)> cat(std::move(u)); - - Real tol = Real(0.001); - auto p = cat(cat.parameter_at_point(0)); - BOOST_CHECK_CLOSE_FRACTION(p[0], p0[0], tol); - BOOST_CHECK_CLOSE_FRACTION(p[1], p0[1], tol); - BOOST_CHECK_CLOSE_FRACTION(p[2], p0[2], tol); - p = cat(cat.parameter_at_point(1)); - BOOST_CHECK_CLOSE_FRACTION(p[0], p1[0], tol); - BOOST_CHECK_CLOSE_FRACTION(p[1], p1[1], tol); - BOOST_CHECK_CLOSE_FRACTION(p[2], p1[2], tol); -} - -BOOST_AUTO_TEST_CASE(catmull_rom_test) -{ -#if !defined(TEST) || (TEST == 1) - - #ifdef __STDCPP_FLOAT32_T__ - test_circle(); - test_data_representations(); - #else - test_circle(); - test_data_representations(); - #endif - - #ifdef __STDCPP_FLOAT64_T__ - test_alpha_distance(); - test_linear(); - test_circle(); - #else - test_alpha_distance(); - test_linear(); - test_circle(); - #endif - - #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_linear(); - #endif - -#endif - -#if !defined(TEST) || (TEST == 2) - - #ifdef __STDCPP_FLOAT64_T__ - test_helix(); - test_affine_invariance(); - test_affine_invariance(); - test_affine_invariance(); - test_affine_invariance(); - test_random_access_container(); - #else - test_helix(); - test_affine_invariance(); - test_affine_invariance(); - test_affine_invariance(); - test_affine_invariance(); - test_random_access_container(); - #endif - -#endif - -#if !defined(TEST) || (TEST == 3) - test_affine_invariance(); -#endif -} diff --git a/test/ccmath_hypot_test.cpp b/test/ccmath_hypot_test.cpp deleted file mode 100644 index bc85b65962..0000000000 --- a/test/ccmath_hypot_test.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// (C) Copyright Matt Borland 2021. -// 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) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - -#if !defined(BOOST_MATH_NO_CONSTEXPR_DETECTION) && !defined(BOOST_MATH_USING_BUILTIN_CONSTANT_P) -template -constexpr void test() -{ - // Error Handling - if constexpr (std::numeric_limits::has_quiet_NaN) - { - static_assert(boost::math::ccmath::isnan(boost::math::ccmath::hypot(std::numeric_limits::quiet_NaN(), T(1))), "If x is NaN, NaN is returned"); - static_assert(boost::math::ccmath::isnan(boost::math::ccmath::hypot(T(1), std::numeric_limits::quiet_NaN())), "If y is NaN, NaN is returned"); - } - - static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(std::numeric_limits::infinity(), T(1)))); - static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(-std::numeric_limits::infinity(), T(1)))); - static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(T(1), std::numeric_limits::infinity()))); - static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(T(1), -std::numeric_limits::infinity()))); - - // Correct promoted types - if constexpr (!std::is_same_v) - { - constexpr auto test_type = boost::math::ccmath::hypot(T(1), 1.0f); - static_assert(std::is_same_v>); - } - else - { - constexpr auto test_type = boost::math::ccmath::hypot(1.0f, 1); - static_assert(std::is_same_v>); - } - - // Functionality - static_assert(boost::math::ccmath::hypot(T(1), T(1)) == boost::math::ccmath::sqrt(T(2))); - static_assert(boost::math::ccmath::hypot(T(-1), T(1)) == boost::math::ccmath::sqrt(T(2))); - static_assert(boost::math::ccmath::hypot(T(-1), T(-1)) == boost::math::ccmath::sqrt(T(2))); - static_assert(boost::math::ccmath::hypot(T(1), T(-1)) == boost::math::ccmath::sqrt(T(2))); - static_assert(boost::math::ccmath::hypot(T(1), T(2)) == boost::math::ccmath::sqrt(T(5))); - static_assert(boost::math::ccmath::hypot(T(2), T(2)) == boost::math::ccmath::sqrt(T(8))); -} - -int main() -{ - test(); - test(); - - #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test(); - #endif - - #ifdef BOOST_HAS_FLOAT128 - test(); - #endif - - return 0; -} -#else -int main() -{ - return 0; -} -#endif diff --git a/test/ccmath_isinf_test.cpp b/test/ccmath_isinf_test.cpp deleted file mode 100644 index 3ee5d1375a..0000000000 --- a/test/ccmath_isinf_test.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// (C) Copyright Matt Borland 2021. -// 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) - -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - -template -void test() -{ - using std::exp; - - // Integer types define infinity as 0 - // https://en.cppreference.com/w/cpp/types/numeric_limits/infinity - if constexpr(std::is_integral_v) - { - constexpr bool test_val = boost::math::ccmath::isinf(T(0)); - static_assert(test_val, "Not constexpr"); - } - else - { - constexpr bool test_val = boost::math::ccmath::isinf(T(0)); - static_assert(!test_val, "Not constexpr"); - } - - if constexpr (std::numeric_limits::has_quiet_NaN) - { - static_assert(!boost::math::ccmath::isinf(std::numeric_limits::quiet_NaN())); - } - static_assert(boost::math::ccmath::isinf(std::numeric_limits::infinity())); -} - -// Only test on platforms that provide BOOST_MATH_IS_CONSTANT_EVALUATED -#ifndef BOOST_MATH_NO_CONSTEXPR_DETECTION -int main() -{ - test(); - test(); - - #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test(); - #endif - - #if defined(BOOST_MATH_TEST_FLOAT128) && !defined(BOOST_MATH_USING_BUILTIN_CONSTANT_P) && defined(BOOST_MATH_TEST_FLOAT128) - test(); - #endif - - test(); - test(); - test(); - test(); - test(); - test(); - - return boost::report_errors(); -} -#else -int main() -{ - return 0; -} -#endif diff --git a/test/ccmath_isnan_test.cpp b/test/ccmath_isnan_test.cpp deleted file mode 100644 index 40d712a242..0000000000 --- a/test/ccmath_isnan_test.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// (C) Copyright Matt Borland 2021. -// 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) - -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - -template -void test() -{ - constexpr bool test_val = boost::math::ccmath::isnan(T(0)); - static_assert(!test_val, "Not constexpr"); - - if constexpr (std::numeric_limits::has_quiet_NaN) - { - static_assert(boost::math::ccmath::isnan(std::numeric_limits::quiet_NaN()), "Quiet NAN failed"); - } - if constexpr (std::numeric_limits::has_signaling_NaN) - { - static_assert(boost::math::ccmath::isnan(std::numeric_limits::signaling_NaN()), "Signaling NAN failed"); - } - static_assert(!boost::math::ccmath::isnan(std::numeric_limits::infinity()), "Infinity failed"); - static_assert(!boost::math::ccmath::isnan(T(0)), "Real 0 failed"); -} - -// Only test on platforms that provide BOOST_MATH_IS_CONSTANT_EVALUATED -#ifndef BOOST_MATH_NO_CONSTEXPR_DETECTION -int main() -{ - test(); - test(); - - #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test(); - #endif - - #if defined(BOOST_MATH_TEST_FLOAT128) && !defined(BOOST_MATH_USING_BUILTIN_CONSTANT_P) - test(); - #endif - - test(); - test(); - test(); - test(); - test(); - test(); - - return boost::report_errors(); -} -#else -int main() -{ - return 0; -} -#endif diff --git a/test/chebyshev_test.cpp b/test/chebyshev_test.cpp deleted file mode 100644 index 84117718c2..0000000000 --- a/test/chebyshev_test.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright Nick Thompson, 2017 - * 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) - */ - -#include -#include -#include -#include -#include -#include -#include -#include "math_unit_test.hpp" - -using boost::multiprecision::cpp_bin_float_quad; -using boost::math::chebyshev_t; -using boost::math::chebyshev_t_prime; -using boost::math::chebyshev_u; - -template -void test_polynomials() -{ - std::cout << "Testing explicit polynomial representations of the Chebyshev polynomials on type " << boost::typeindex::type_id().pretty_name() << "\n"; - - Real x = -2; - Real tol = 32*std::numeric_limits::epsilon(); - while (x < 2) - { - CHECK_MOLLIFIED_CLOSE(chebyshev_t(0, x), Real(1), tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_t(1, x), x, tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_t(2, x), 2*x*x - 1, tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_t(3, x), x*(4*x*x-3), tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_t(4, x), 8*x*x*(x*x - 1) + 1, tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_t(5, x), x*(16*x*x*x*x - 20*x*x + 5), tol); - x += 1/static_cast(1<<7); - } - - x = -2; - while (x < 2) - { - CHECK_MOLLIFIED_CLOSE(chebyshev_u(0, x), Real(1), tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_u(1, x), 2*x, tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_u(2, x), 4*x*x - 1, tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_u(3, x), 4*x*(2*x*x - 1), tol); - x += 1/static_cast(1<<7); - } -} - - -template -void test_derivatives() -{ - std::cout << "Testing explicit polynomial representations of the Chebyshev polynomial derivatives on type " << boost::typeindex::type_id().pretty_name() << "\n"; - - Real x = -2; - Real tol = 4*std::numeric_limits::epsilon(); - while (x < 2) - { - CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(0, x), Real(0), tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(1, x), Real(1), tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(2, x), 4*x, tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(3, x), 3*(4*x*x - 1), tol); - CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(4, x), 16*x*(2*x*x - 1), tol); - // This one makes the tolerance have to grow too large; the Chebyshev recurrence is more stable than naive polynomial evaluation anyway. - //BOOST_CHECK_CLOSE_FRACTION(chebyshev_t_prime(5, x), 5*(4*x*x*(4*x*x - 3) + 1), tol); - x += 1/static_cast(1<<7); - } -} - -template -void test_clenshaw_recurrence() -{ - using boost::math::chebyshev_clenshaw_recurrence; - std::array c0 = { {2, 0, 0, 0, 0} }; - // Check the size = 1 case: - std::array c01 = { {2} }; - // Check the size = 2 case: - std::array c02 = { {2, 0} }; - std::array c1 = { {0, 1, 0, 0} }; - std::array c2 = { {0, 0, 1, 0} }; - std::array c3 = { {0, 0, 0, 1, 0} }; - std::array c4 = { {0, 0, 0, 0, 1} }; - std::array c5 = { {0, 0, 0, 0, 0, 1} }; - std::array c6 = { {0, 0, 0, 0, 0, 0, 1} }; - - // - // Error handling checks: - // - CHECK_THROW(chebyshev_clenshaw_recurrence(c0.data(), c0.size(), Real(-1), Real(1), Real(-2)), std::domain_error); - CHECK_THROW(chebyshev_clenshaw_recurrence(c0.data(), c0.size(), Real(-1), Real(1), Real(2)), std::domain_error); - CHECK_EQUAL(chebyshev_clenshaw_recurrence(c0.data(), 0, Real(-1), Real(1), Real(0.5)), Real(0)); - - Real x = -1; - // It's not clear from this test which one is more accurate; higher precision cast testing is required, and is done elsewhere: - int ulps = 50; - while (x <= 1) - { - Real y = chebyshev_clenshaw_recurrence(c0.data(), c0.size(), x); - Real expected = chebyshev_t(0, x); - CHECK_ULP_CLOSE(expected, y, ulps); - y = chebyshev_clenshaw_recurrence(c0.data(), c0.size(), Real(-1), Real(1), x); - CHECK_ULP_CLOSE(expected, y, ulps); - - y = chebyshev_clenshaw_recurrence(c01.data(), c01.size(), x); - CHECK_ULP_CLOSE(expected, y, ulps); - y = chebyshev_clenshaw_recurrence(c01.data(), c01.size(), Real(-1), Real(1), x); - CHECK_ULP_CLOSE(expected, y, ulps); - - y = chebyshev_clenshaw_recurrence(c02.data(), c02.size(), x); - CHECK_ULP_CLOSE(expected, y, ulps); - y = chebyshev_clenshaw_recurrence(c02.data(), c02.size(), Real(-1), Real(1), x); - CHECK_ULP_CLOSE(expected, y, ulps); - - expected = chebyshev_t(1,x); - y = chebyshev_clenshaw_recurrence(c1.data(), c1.size(), x); - CHECK_ULP_CLOSE(expected, y, ulps); - y = chebyshev_clenshaw_recurrence(c1.data(), c1.size(), Real(-1), Real(1), x); - CHECK_ULP_CLOSE(expected, y, ulps); - - expected = chebyshev_t(2, x); - y = chebyshev_clenshaw_recurrence(c2.data(), c2.size(), x); - CHECK_ULP_CLOSE(expected, y, ulps); - y = chebyshev_clenshaw_recurrence(c2.data(), c2.size(), Real(-1), Real(1), x); - CHECK_ULP_CLOSE(expected, y, ulps); - - expected = chebyshev_t(3, x); - y = chebyshev_clenshaw_recurrence(c3.data(), c3.size(), x); - CHECK_ULP_CLOSE(expected, y, ulps); - y = chebyshev_clenshaw_recurrence(c3.data(), c3.size(), Real(-1), Real(1), x); - CHECK_ULP_CLOSE(expected, y, ulps); - - expected = chebyshev_t(4, x); - y = chebyshev_clenshaw_recurrence(c4.data(), c4.size(), x); - CHECK_ULP_CLOSE(expected, y, ulps); - y = chebyshev_clenshaw_recurrence(c4.data(), c4.size(), Real(-1), Real(1), x); - CHECK_ULP_CLOSE(expected, y, ulps); - - expected = chebyshev_t(5, x); - y = chebyshev_clenshaw_recurrence(c5.data(), c5.size(), x); - CHECK_ULP_CLOSE(expected, y, ulps); - y = chebyshev_clenshaw_recurrence(c5.data(), c5.size(), Real(-1), Real(1), x); - CHECK_ULP_CLOSE(expected, y, ulps); - - expected = chebyshev_t(6, x); - y = chebyshev_clenshaw_recurrence(c6.data(), c6.size(), x); - CHECK_ULP_CLOSE(expected, y, ulps); - y = chebyshev_clenshaw_recurrence(c6.data(), c6.size(), Real(-1), Real(1), x); - CHECK_ULP_CLOSE(expected, y, ulps); - - x += static_cast(1)/static_cast(1 << 7); - } -} - -template -void test_translated_clenshaw_recurrence() -{ - using boost::math::chebyshev_clenshaw_recurrence; - std::mt19937_64 mt(123242); - std::uniform_real_distribution dis(-1,1); - - std::vector c(32); - for (auto & d : c) { - d = dis(mt); - } - int samples = 0; - while (samples++ < 250) { - Real x = dis(mt); - Real expected = chebyshev_clenshaw_recurrence(c.data(), c.size(), x); - // The computed value, in this case, should actually be better, since it has more information to use. - // In any case, this test doesn't show Reinch's modification to the Clenshaw recurrence is better; - // it shows they are doing roughly the same thing. - Real computed = chebyshev_clenshaw_recurrence(c.data(), c.size(), Real(-1), Real(1), x); - if (!CHECK_ULP_CLOSE(expected, computed, 1000)) { - std::cerr << " Problem occurred at x = " << x << "\n"; - } - } -} - -int main() -{ - test_polynomials(); - test_polynomials(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_polynomials(); -#endif - test_polynomials(); - - test_derivatives(); - test_derivatives(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_derivatives(); -#endif - test_derivatives(); - - test_clenshaw_recurrence(); - test_clenshaw_recurrence(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_clenshaw_recurrence(); -#endif - - test_translated_clenshaw_recurrence(); - return boost::math::test::report_errors(); -} diff --git a/test/chebyshev_transform_test.cpp b/test/chebyshev_transform_test.cpp deleted file mode 100644 index a6eed51dfe..0000000000 --- a/test/chebyshev_transform_test.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright Nick Thompson, 2017 - * 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) - */ -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include - -#if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) && !defined(TEST4) -# define TEST1 -# define TEST2 -# define TEST3 -# define TEST4 -#endif - -using boost::math::chebyshev_t; -using boost::math::chebyshev_t_prime; -using boost::math::chebyshev_u; -using boost::math::chebyshev_transform; - - -template -void test_sin_chebyshev_transform() -{ - using boost::math::chebyshev_transform; - using boost::math::constants::half_pi; - using std::sin; - using std::cos; - using std::abs; - - Real tol = std::numeric_limits::epsilon(); - auto f = [](Real x)->Real { return sin(x); }; - Real a = 0; - Real b = 1; - chebyshev_transform cheb(f, a, b, tol); - - Real x = a; - while (x < b) - { - Real s = sin(x); - Real c = cos(x); - CHECK_ABSOLUTE_ERROR(s, cheb(x), tol); - CHECK_ABSOLUTE_ERROR(c, cheb.prime(x), 150*tol); - x += static_cast(1)/static_cast(1 << 7); - } - - Real Q = cheb.integrate(); - - CHECK_ABSOLUTE_ERROR(1 - cos(static_cast(1)), Q, 100*tol); -} - - -template -void test_sinc_chebyshev_transform() -{ - using std::cos; - using std::sin; - using std::abs; - using boost::math::sinc_pi; - using boost::math::chebyshev_transform; - using boost::math::constants::half_pi; - - Real tol = 100*std::numeric_limits::epsilon(); - auto f = [](Real x) { return boost::math::sinc_pi(x); }; - Real a = 0; - Real b = 1; - chebyshev_transform cheb(f, a, b, tol/50); - - Real x = a; - while (x < b) - { - Real s = sinc_pi(x); - Real ds = (cos(x)-sinc_pi(x))/x; - if (x == 0) { ds = 0; } - - CHECK_ABSOLUTE_ERROR(s, cheb(x), tol); - CHECK_ABSOLUTE_ERROR(ds, cheb.prime(x), 10*tol); - x += static_cast(1)/static_cast(1 << 7); - } - - Real Q = cheb.integrate(); - //NIntegrate[Sinc[x], {x, 0, 1}, WorkingPrecision -> 200, AccuracyGoal -> 150, PrecisionGoal -> 150, MaxRecursion -> 150] - Real Q_exp = BOOST_MATH_TEST_VALUE(Real, 0.94608307036718301494135331382317965781233795473811179047145477356668); - CHECK_ABSOLUTE_ERROR(Q_exp, Q, tol); -} - - - -//Examples taken from "Approximation Theory and Approximation Practice", by Trefethen -template -void test_atap_examples() -{ - using std::sin; - using std::exp; - using std::sqrt; - using boost::math::constants::half; - using boost::math::sinc_pi; - using boost::math::chebyshev_transform; - using boost::math::constants::half_pi; - - Real tol = 10*std::numeric_limits::epsilon(); - auto f1 = [](Real x) { return ((0 < x) - (x < 0)) - x/2; }; - auto f2 = [](Real x) { Real t = sin(6*x); Real s = sin(x + exp(2*x)); - Real u = (0 < s) - (s < 0); - return t + u; }; - - //auto f3 = [](Real x) { return sin(6*x) + sin(60*exp(x)); }; - //auto f4 = [](Real x) { return 1/(1+1000*(x+half())*(x+half())) + 1/sqrt(1+1000*(x-Real(1)/Real(2))*(x-Real(1)/Real(2)));}; - Real a = -1; - Real b = 1; - chebyshev_transform cheb1(f1, a, b, tol); - chebyshev_transform cheb2(f2, a, b, tol); - //chebyshev_transform cheb3(f3, a, b, tol); - - Real x = a; - while (x < b) - { - // f1 and f2 are not differentiable; standard convergence rate theorems don't apply. - // Basically, the max refinements are always hit; so the error is not related to the precision of the type. - Real acceptable_error = sqrt(tol); - Real acceptable_error_2 = 9e-4; - if (std::is_same::value) - { - acceptable_error = 1.6e-5; - } - if (std::is_same::value) - { - acceptable_error *= 500; - } - CHECK_ABSOLUTE_ERROR(f1(x), cheb1(x), acceptable_error); - - CHECK_ABSOLUTE_ERROR(f2(x), cheb2(x), acceptable_error_2); - x += static_cast(1)/static_cast(1 << 7); - } -} - - -//Validate that the Chebyshev polynomials are well approximated by the Chebyshev transform. -template -void test_chebyshev_chebyshev_transform() -{ - Real tol = 500*std::numeric_limits::epsilon(); - // T_0 = 1: - auto t0 = [](Real) { return 1; }; - chebyshev_transform cheb0(t0, -1, 1); - CHECK_ABSOLUTE_ERROR(2, cheb0.coefficients()[0], tol); - - Real x = -1; - while (x < 1) - { - CHECK_ABSOLUTE_ERROR(1, cheb0(x), tol); - CHECK_ABSOLUTE_ERROR(Real(0), cheb0.prime(x), tol); - x += static_cast(1)/static_cast(1 << 7); - } - - // T_1 = x: - auto t1 = [](Real x) { return x; }; - chebyshev_transform cheb1(t1, -1, 1); - CHECK_ABSOLUTE_ERROR(Real(1), cheb1.coefficients()[1], tol); - - x = -1; - while (x < 1) - { - CHECK_ABSOLUTE_ERROR(x, cheb1(x), tol); - CHECK_ABSOLUTE_ERROR(Real(1), cheb1.prime(x), tol); - x += static_cast(1)/static_cast(1 << 7); - } - - - auto t2 = [](Real x) { return 2*x*x-1; }; - chebyshev_transform cheb2(t2, -1, 1); - CHECK_ABSOLUTE_ERROR(Real(1), cheb2.coefficients()[2], tol); - - x = -1; - while (x < 1) - { - CHECK_ABSOLUTE_ERROR(t2(x), cheb2(x), tol); - CHECK_ABSOLUTE_ERROR(4*x, cheb2.prime(x), tol); - x += static_cast(1)/static_cast(1 << 7); - } -} - -int main() -{ -#ifdef TEST1 - test_chebyshev_chebyshev_transform(); - test_sin_chebyshev_transform(); - test_atap_examples(); - test_sinc_chebyshev_transform(); -#endif -#ifdef TEST2 - test_chebyshev_chebyshev_transform(); - test_sin_chebyshev_transform(); - test_atap_examples(); - test_sinc_chebyshev_transform(); -#endif -#ifdef TEST3 - test_chebyshev_chebyshev_transform(); - test_sin_chebyshev_transform(); - test_atap_examples(); - test_sinc_chebyshev_transform(); -#endif -#ifdef TEST4 -#ifdef BOOST_HAS_FLOAT128 - test_chebyshev_chebyshev_transform<__float128>(); - test_sin_chebyshev_transform<__float128>(); - test_atap_examples<__float128>(); - test_sinc_chebyshev_transform<__float128>(); -#endif -#endif - - return boost::math::test::report_errors(); -} - - diff --git a/test/check_cmake_version.cpp b/test/check_cmake_version.cpp index 2fd4648368..fb40e57832 100644 --- a/test/check_cmake_version.cpp +++ b/test/check_cmake_version.cpp @@ -18,7 +18,7 @@ int main( int ac, char const* av[] ) if( ac >= 2 ) { char version[ 64 ]; - std::sprintf( version, "%d.%d.%d", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100 ); + std::snprintf( version, sizeof( version ), "%d.%d.%d", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100 ); BOOST_TEST_CSTR_EQ( av[1], version ); } diff --git a/test/cmake_namespace_test/CMakeLists.txt b/test/cmake_namespace_test/CMakeLists.txt new file mode 100644 index 0000000000..105bc3a511 --- /dev/null +++ b/test/cmake_namespace_test/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright 2026 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +# +# Validates the configurable top level namespace (https://github.com/boostorg/math/issues/769) +# by relocating the whole library into ::my_lib::math. + +cmake_minimum_required(VERSION 3.8...3.20) + +project(cmake_namespace_test LANGUAGES CXX) + +option(BOOST_MATH_NAMESPACE_TEST_HEADERS "Compile every public header on its own with the relocated namespace" ON) + +# Math is header-only and standalone by default (no deps needed) +add_subdirectory(../.. boostorg/math) + +set(namespace_definition "BOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math") + +enable_testing() + +# Behavior through ::my_lib::math +add_executable(namespace_test namespace_test.cpp) +target_link_libraries(namespace_test Boost::math) +target_compile_definitions(namespace_test PRIVATE ${namespace_definition}) +add_test(NAME namespace_test COMMAND namespace_test) + +# BOOST_MATH_NAMESPACE::name and my_lib::math::name are the same entities +add_executable(qualified_name_test qualified_name_test.cpp) +target_link_libraries(qualified_name_test Boost::math) +target_compile_definitions(qualified_name_test PRIVATE ${namespace_definition}) +add_test(NAME qualified_name_test COMMAND qualified_name_test) + +# No symbol of the test binary may be mangled into ::boost +if(CMAKE_NM AND NOT MSVC) + add_test(NAME namespace_symbols COMMAND ${CMAKE_COMMAND} -DNM=${CMAKE_NM} -DFILE=$ -P ${CMAKE_CURRENT_SOURCE_DIR}/check_symbols.cmake) +endif() + +if(BOOST_MATH_NAMESPACE_TEST_HEADERS) + + set(include_root "${CMAKE_CURRENT_SOURCE_DIR}/../../include") + file(GLOB_RECURSE headers RELATIVE "${include_root}" "${include_root}/boost/math/*.hpp") + list(FILTER headers EXCLUDE REGEX "/detail/") + + # Headers that need third party libraries, need non-standalone Boost, or are fragments of another header + list(FILTER headers EXCLUDE REGEX "^boost/math/bindings/") + list(REMOVE_ITEM headers + boost/math/common_factor.hpp + boost/math/common_factor_ct.hpp + boost/math/common_factor_rt.hpp + boost/math/concepts/distributions.hpp + boost/math/constants/calculate_constants.hpp + boost/math/cstdfloat/cstdfloat_complex_std.hpp + boost/math/differentiation/autodiff_cpp11.hpp + boost/math/optimization/cma_es.hpp + boost/math/tools/signal_statistics.hpp + ) + + set(header_sources "") + foreach(header IN LISTS headers) + string(MAKE_C_IDENTIFIER "${header}" name) + set(source "${CMAKE_CURRENT_BINARY_DIR}/headers/${name}.cpp") + configure_file(header_test.cpp.in "${source}" @ONLY) + list(APPEND header_sources "${source}") + endforeach() + + add_library(namespace_header_tests OBJECT ${header_sources}) + target_link_libraries(namespace_header_tests PRIVATE Boost::math) + target_compile_definitions(namespace_header_tests PRIVATE ${namespace_definition}) + target_compile_features(namespace_header_tests PRIVATE cxx_std_17) + +endif() + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/test/cmake_namespace_test/check_symbols.cmake b/test/cmake_namespace_test/check_symbols.cmake new file mode 100644 index 0000000000..e68abc5f7e --- /dev/null +++ b/test/cmake_namespace_test/check_symbols.cmake @@ -0,0 +1,25 @@ +# Copyright 2026 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +# +# Usage: cmake -DNM= -DFILE= -P check_symbols.cmake +# Fails if any symbol is mangled into ::boost, or if nothing was emitted into ::my_lib::math. + +execute_process(COMMAND "${NM}" "${FILE}" OUTPUT_VARIABLE symbols RESULT_VARIABLE result) + +if(NOT result EQUAL 0) + message(FATAL_ERROR "${NM} failed on ${FILE}") +endif() + +string(REGEX MATCHALL "[^\n]*N5boost[^\n]*" leaked "${symbols}") +if(leaked) + list(LENGTH leaked count) + string(REPLACE ";" "\n" leaked "${leaked}") + message(FATAL_ERROR "${count} symbols are still in namespace boost:\n${leaked}") +endif() + +if(NOT symbols MATCHES "N6my_lib4math") + message(FATAL_ERROR "No symbols found in namespace my_lib::math, the check is not meaningful") +endif() + +message(STATUS "No symbols in namespace boost") diff --git a/test/cmake_namespace_test/header_test.cpp.in b/test/cmake_namespace_test/header_test.cpp.in new file mode 100644 index 0000000000..0c09e63296 --- /dev/null +++ b/test/cmake_namespace_test/header_test.cpp.in @@ -0,0 +1,13 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Generated by CMake: compiles one header with the library relocated into ::my_lib::math + +#include <@header@> + +// If anything still declares ::boost::math the lookup of math below is ambiguous +namespace boost {} +namespace boost_math_namespace_probe { namespace math { constexpr bool absent {true}; } } +namespace boost_math_namespace_check { using namespace ::boost_math_namespace_probe; using namespace ::boost; } +static_assert(boost_math_namespace_check::math::absent, "::boost::math is still declared"); diff --git a/test/cmake_namespace_test/namespace_test.cpp b/test/cmake_namespace_test/namespace_test.cpp new file mode 100644 index 0000000000..cee9edfa79 --- /dev/null +++ b/test/cmake_namespace_test/namespace_test.cpp @@ -0,0 +1,148 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Built with BOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math (https://github.com/boostorg/math/issues/769): +// the whole library must be usable through ::my_lib::math and nothing may be left in ::boost::math. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L +# include +# include +# include +# define BOOST_MATH_NAMESPACE_TEST_CXX17 +#endif + +static_assert(BOOST_MATH_NAMESPACE_LEVELS == 2, "my_lib,math has two components"); +static_assert(std::is_same<::BOOST_MATH_NAMESPACE::normal, ::my_lib::math::normal>::value, "BOOST_MATH_NAMESPACE names my_lib::math"); + +// If anything still declares ::boost::math (or ::boost::math_detail) the lookups below are ambiguous +namespace boost {} +namespace probe +{ + namespace math { constexpr bool absent {true}; } + namespace math_detail { constexpr bool absent {true}; } +} +namespace check { using namespace ::probe; using namespace ::boost; } +static_assert(check::math::absent, "::boost::math is still declared"); +static_assert(check::math_detail::absent, "::boost::math_detail is still declared"); + +// The forwarding macros must work from a user namespace +namespace user_functions +{ + using c_policy = ::my_lib::math::policies::policy< + ::my_lib::math::policies::domain_error<::my_lib::math::policies::errno_on_error>, + ::my_lib::math::policies::pole_error<::my_lib::math::policies::errno_on_error>>; + + BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(c_policy) +} + +namespace user_distributions +{ + using my_policy = ::my_lib::math::policies::policy<::my_lib::math::policies::promote_double>; + + BOOST_MATH_DECLARE_DISTRIBUTIONS(double, my_policy) +} + +namespace +{ + +int failures {0}; + +void check_close(double result, double expected, const char* what) +{ + const auto tolerance {1e-13 * (std::fabs(expected) > 1 ? std::fabs(expected) : 1.0)}; + if (!(std::fabs(result - expected) <= tolerance)) + { + std::cerr << "FAIL " << what << ": got " << result << ", expected " << expected << '\n'; + ++failures; + } +} + +void check_true(bool condition, const char* what) +{ + if (!condition) + { + std::cerr << "FAIL " << what << '\n'; + ++failures; + } +} + +} // namespace + +int main() +{ + // Special functions + check_close(::my_lib::math::tgamma(5.0), 24.0, "tgamma"); + check_close(::my_lib::math::lgamma(10.0), 12.801827480081469611, "lgamma"); + check_close(::my_lib::math::erf(0.5), 0.52049987781304653768, "erf"); + check_close(::my_lib::math::cyl_bessel_j(0, 1.0), 0.76519768655796655145, "cyl_bessel_j"); + check_close(::my_lib::math::beta(2.0, 3.0), 1.0 / 12, "beta"); + check_close(::my_lib::math::zeta(2.0), 1.6449340668482264365, "zeta"); + check_true(::my_lib::math::isnan(std::numeric_limits::quiet_NaN()), "isnan"); + check_true(::my_lib::math::isfinite(1.0), "isfinite"); + + // Distributions, with cdf and quantile found by ADL + const ::my_lib::math::normal standard_normal {}; + check_close(cdf(standard_normal, 0.0), 0.5, "normal cdf"); + check_close(quantile(::my_lib::math::students_t {5}, 0.975), 2.5705818356363146, "students_t quantile"); + + // Constants + check_close(::my_lib::math::constants::pi(), 3.141592653589793238, "pi"); + + // Tools + const auto root {::my_lib::math::tools::bisect([](double x) { return x * x - 2; }, 0.0, 2.0, + ::my_lib::math::tools::eps_tolerance {50})}; + check_close((root.first + root.second) / 2, 1.4142135623730950488, "bisect"); + const ::my_lib::math::tools::polynomial p {{1.0, 2.0, 3.0}}; + check_close(p(2.0), 17.0, "polynomial"); + + // Quadrature + const auto area {::my_lib::math::quadrature::gauss_kronrod::integrate([](double x) { return x * x; }, 0.0, 1.0)}; + check_close(area, 1.0 / 3, "gauss_kronrod"); + + // Default policy throws, from the relocated error handling + bool threw {false}; + try + { + static_cast(::my_lib::math::tgamma(0.0)); + } + catch (const std::domain_error&) + { + threw = true; + } + check_true(threw, "tgamma(0) throws std::domain_error"); + + // Policies through the forwarding macros + errno = 0; + check_true(std::isnan(user_functions::tgamma(-1.0)), "user policy tgamma(-1) is NaN"); + check_true(errno == EDOM, "user policy tgamma(-1) sets EDOM"); + check_close(user_functions::tgamma(5.0), 24.0, "user policy tgamma"); + check_close(cdf(user_distributions::normal {}, 0.0), 0.5, "user policy normal cdf"); + + #ifdef BOOST_MATH_NAMESPACE_TEST_CXX17 + check_close(::my_lib::math::ccmath::sqrt(4.0), 2.0, "ccmath sqrt"); + const std::vector v {1.0, 2.0, 3.0, 4.0}; + check_close(::my_lib::math::statistics::mean(v), 2.5, "statistics mean"); + #endif + + if (failures == 0) + { + std::cout << "All checks passed in namespace my_lib::math\n"; + } + return failures == 0 ? 0 : 1; +} diff --git a/test/cmake_namespace_test/qualified_name_test.cpp b/test/cmake_namespace_test/qualified_name_test.cpp new file mode 100644 index 0000000000..8417f567ec --- /dev/null +++ b/test/cmake_namespace_test/qualified_name_test.cpp @@ -0,0 +1,155 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Built with BOOST_MATH_NAMESPACE_COMPONENTS=my_lib,math (https://github.com/boostorg/math/issues/769): +// every entity must be reachable as both BOOST_MATH_NAMESPACE::name and my_lib::math::name, +// and the two spellings must name the same entity. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L +# include +# include +# include +# define BOOST_MATH_QUALIFIED_NAME_TEST_CXX17 +#endif + +// Types are identical through either spelling, with or without the leading :: +static_assert(std::is_same::value, "normal"); +static_assert(std::is_same<::BOOST_MATH_NAMESPACE::students_t_distribution, ::my_lib::math::students_t_distribution>::value, "students_t"); +static_assert(std::is_same, my_lib::math::policies::policy<>>::value, "policy"); +static_assert(std::is_same, my_lib::math::tools::eps_tolerance>::value, "eps_tolerance"); + +// A namespace alias works with the macro +namespace bm = BOOST_MATH_NAMESPACE; +static_assert(std::is_same::value, "alias"); + +// The unqualified macro still resolves from inside a nested user namespace +namespace user +{ +namespace nested +{ + +inline double gamma_via_macro(double x) +{ + return BOOST_MATH_NAMESPACE::tgamma(x); +} + +inline double gamma_via_namespace(double x) +{ + return my_lib::math::tgamma(x); +} + +} // namespace nested +} // namespace user + +namespace +{ + +int failures {0}; + +// Both spellings must give identical results that match the reference value +void check_same(double via_macro, double via_namespace, double expected, const char* what) +{ + const auto tolerance {1e-13 * (std::fabs(expected) > 1 ? std::fabs(expected) : 1.0)}; + if (!(via_macro == via_namespace) || !(std::fabs(via_macro - expected) <= tolerance)) + { + std::cerr << "FAIL " << what << ": BOOST_MATH_NAMESPACE gave " << via_macro + << ", my_lib::math gave " << via_namespace << ", expected " << expected << '\n'; + ++failures; + } +} + +void check_true(bool condition, const char* what) +{ + if (!condition) + { + std::cerr << "FAIL " << what << '\n'; + ++failures; + } +} + +using unary_function = double (*)(double); + +// The same function, not two functions that happen to agree +constexpr unary_function tgamma_via_macro {&BOOST_MATH_NAMESPACE::tgamma}; +constexpr unary_function tgamma_via_namespace {&my_lib::math::tgamma}; +static_assert(tgamma_via_macro == tgamma_via_namespace, "tgamma is one function"); + +constexpr unary_function erf_via_macro {&::BOOST_MATH_NAMESPACE::erf}; +constexpr unary_function erf_via_namespace {&::my_lib::math::erf}; +static_assert(erf_via_macro == erf_via_namespace, "erf is one function"); + +} // namespace + +int main() +{ + // Special functions + check_same(BOOST_MATH_NAMESPACE::tgamma(5.0), my_lib::math::tgamma(5.0), 24.0, "tgamma"); + check_same(::BOOST_MATH_NAMESPACE::lgamma(10.0), ::my_lib::math::lgamma(10.0), 12.801827480081469611, "lgamma"); + check_same(BOOST_MATH_NAMESPACE::erf(0.5), my_lib::math::erf(0.5), 0.52049987781304653768, "erf"); + check_same(BOOST_MATH_NAMESPACE::cyl_bessel_j(0, 1.0), my_lib::math::cyl_bessel_j(0, 1.0), 0.76519768655796655145, "cyl_bessel_j"); + check_same(BOOST_MATH_NAMESPACE::beta(2.0, 3.0), my_lib::math::beta(2.0, 3.0), 1.0 / 12, "beta"); + check_same(BOOST_MATH_NAMESPACE::zeta(2.0), my_lib::math::zeta(2.0), 1.6449340668482264365, "zeta"); + check_same(bm::tgamma(5.0), my_lib::math::tgamma(5.0), 24.0, "tgamma through alias"); + check_same(user::nested::gamma_via_macro(5.0), user::nested::gamma_via_namespace(5.0), 24.0, "tgamma from nested namespace"); + + const auto nan {std::numeric_limits::quiet_NaN()}; + check_true(BOOST_MATH_NAMESPACE::isnan(nan) && my_lib::math::isnan(nan), "isnan"); + + // Distributions, with the non-member functions called by qualified name + check_same(BOOST_MATH_NAMESPACE::cdf(BOOST_MATH_NAMESPACE::normal {}, 0.0), my_lib::math::cdf(my_lib::math::normal {}, 0.0), 0.5, "normal cdf"); + check_same(BOOST_MATH_NAMESPACE::quantile(BOOST_MATH_NAMESPACE::students_t {5}, 0.975), + my_lib::math::quantile(my_lib::math::students_t {5}, 0.975), 2.5705818356363146, "students_t quantile"); + + // An object made through one spelling works with functions named through the other + const BOOST_MATH_NAMESPACE::normal macro_normal {1.0, 2.0}; + check_same(my_lib::math::mean(macro_normal), BOOST_MATH_NAMESPACE::mean(macro_normal), 1.0, "mixed spelling mean"); + + // Constants + check_same(BOOST_MATH_NAMESPACE::constants::pi(), my_lib::math::constants::pi(), 3.141592653589793238, "pi"); + + // Policies spelled one way passed to functions spelled the other way + using macro_policy = BOOST_MATH_NAMESPACE::policies::policy< + BOOST_MATH_NAMESPACE::policies::domain_error, + BOOST_MATH_NAMESPACE::policies::pole_error>; + using namespace_policy = my_lib::math::policies::policy< + my_lib::math::policies::domain_error, + my_lib::math::policies::pole_error>; + static_assert(std::is_same::value, "policies"); + check_true(std::isnan(my_lib::math::tgamma(-1.0, macro_policy {})), "my_lib::math::tgamma with BOOST_MATH_NAMESPACE policy"); + check_true(std::isnan(BOOST_MATH_NAMESPACE::tgamma(-1.0, namespace_policy {})), "BOOST_MATH_NAMESPACE::tgamma with my_lib::math policy"); + + // Tools + const auto f {[](double x) { return x * x - 2; }}; + const auto macro_root {BOOST_MATH_NAMESPACE::tools::bisect(f, 0.0, 2.0, BOOST_MATH_NAMESPACE::tools::eps_tolerance {50})}; + const auto namespace_root {my_lib::math::tools::bisect(f, 0.0, 2.0, my_lib::math::tools::eps_tolerance {50})}; + check_same((macro_root.first + macro_root.second) / 2, (namespace_root.first + namespace_root.second) / 2, 1.4142135623730950488, "bisect"); + + // Quadrature + const auto g {[](double x) { return x * x; }}; + check_same(BOOST_MATH_NAMESPACE::quadrature::gauss_kronrod::integrate(g, 0.0, 1.0), + my_lib::math::quadrature::gauss_kronrod::integrate(g, 0.0, 1.0), 1.0 / 3, "gauss_kronrod"); + + #ifdef BOOST_MATH_QUALIFIED_NAME_TEST_CXX17 + check_same(BOOST_MATH_NAMESPACE::ccmath::sqrt(4.0), my_lib::math::ccmath::sqrt(4.0), 2.0, "ccmath sqrt"); + const std::vector v {1.0, 2.0, 3.0, 4.0}; + check_same(BOOST_MATH_NAMESPACE::statistics::mean(v), my_lib::math::statistics::mean(v), 2.5, "statistics mean"); + #endif + + if (failures == 0) + { + std::cout << "BOOST_MATH_NAMESPACE and my_lib::math name the same entities\n"; + } + return failures == 0 ? 0 : 1; +} diff --git a/test/compile_test/CMakeLists.txt b/test/compile_test/CMakeLists.txt index acfa292228..8989983683 100644 --- a/test/compile_test/CMakeLists.txt +++ b/test/compile_test/CMakeLists.txt @@ -4,4 +4,14 @@ include_directories(../../include_private) file(GLOB SRC_FILES CONFIGURE_DEPENDS "*.cpp") -boost_test(TYPE "compile" SOURCES ${SRC_FILES} COMPILE_DEFINITIONS BOOST_MATH_STANDALONE COMPILE_FEATURES cxx_std_17 LINK_LIBRARIES Boost::math Boost::multiprecision Boost::numeric_ublas Boost::unit_test_framework ) +# Users compile these headers with warnings as errors, so we do too. -Wno-deprecated-declarations +# because some of these tests exercise deprecated functions on purpose. +# gcc's plain -Wshadow also flags header locals that shadow the single-letter globals of +# test_compile_result.hpp, so gcc gets -Wshadow=local (locals and parameters only). +set(BOOST_MATH_COMPILE_TEST_WARNINGS "") +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(BOOST_MATH_COMPILE_TEST_WARNINGS -Wall -Wextra -Wshadow=local -Werror -Wno-deprecated-declarations) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(BOOST_MATH_COMPILE_TEST_WARNINGS -Wall -Wextra -Wshadow -Werror -Wno-deprecated-declarations) +endif() +boost_test(TYPE "compile" SOURCES ${SRC_FILES} COMPILE_DEFINITIONS BOOST_MATH_STANDALONE COMPILE_OPTIONS ${BOOST_MATH_COMPILE_TEST_WARNINGS} COMPILE_FEATURES cxx_std_17 LINK_LIBRARIES Boost::math Boost::multiprecision Boost::numeric_ublas Boost::unit_test_framework ) diff --git a/test/compile_test/ccmath_frexp_incl_test.cpp b/test/compile_test/ccmath_frexp_incl_test.cpp deleted file mode 100644 index a273d919f2..0000000000 --- a/test/compile_test/ccmath_frexp_incl_test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// (C) Copyright Matt Borland 2021. -// 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) - -#include -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - int i; - check_result(boost::math::ccmath::frexp(1.0f, &i)); - check_result(boost::math::ccmath::frexp(1.0, &i)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::ccmath::frexp(1.0l, &i)); -#endif -} diff --git a/test/compile_test/diff_numerical_differentiation_concept_test.cpp b/test/compile_test/diff_numerical_differentiation_concept_test.cpp deleted file mode 100644 index 1c0d5d1ece..0000000000 --- a/test/compile_test/diff_numerical_differentiation_concept_test.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright Nick Thompson 2017. -// 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) -// - -#ifndef BOOST_MATH_STANDALONE - -#include -#include - -void compile_and_link_test() -{ - boost::math::concepts::std_real_concept x = 0; - auto f = [](boost::math::concepts::std_real_concept x) { return x; }; - boost::math::differentiation::finite_difference_derivative(f, x); -} - -#endif diff --git a/test/compile_test/diff_numerical_differentiation_incl_test.cpp b/test/compile_test/diff_numerical_differentiation_incl_test.cpp deleted file mode 100644 index 7286949a11..0000000000 --- a/test/compile_test/diff_numerical_differentiation_incl_test.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright Nick Thompson 2017. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - double x = 0; - check_result(boost::math::differentiation::finite_difference_derivative(f, x)); - - auto g = [](std::complex x){ return x;}; - check_result(boost::math::differentiation::complex_step_derivative(g, x)); -} diff --git a/test/compile_test/differential_evolution_incl_test.cpp b/test/compile_test/differential_evolution_incl_test.cpp deleted file mode 100644 index 9347f30749..0000000000 --- a/test/compile_test/differential_evolution_incl_test.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright Nick Thompson 2024. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](std::vector const & v) { return v[0]*v[0]; }; - boost::math::optimization::differential_evolution_parameters> params; - std::mt19937_64 gen(12345); - auto v = boost::math::optimization::differential_evolution(f, params, gen); -} diff --git a/test/compile_test/distribution_concept_check.cpp b/test/compile_test/distribution_concept_check.cpp index 3f5253cd71..0102eaa3fc 100644 --- a/test/compile_test/distribution_concept_check.cpp +++ b/test/compile_test/distribution_concept_check.cpp @@ -27,6 +27,7 @@ void instantiate(RealType) function_requires > >(); function_requires > >(); function_requires > >(); + function_requires > >(); function_requires > >(); function_requires > >(); function_requires > >(); diff --git a/test/compile_test/instantiate.hpp b/test/compile_test/instantiate.hpp index 96c8964866..89999e7947 100644 --- a/test/compile_test/instantiate.hpp +++ b/test/compile_test/instantiate.hpp @@ -120,6 +120,7 @@ void instantiate(RealType) function_requires > >(); function_requires > >(); function_requires > >(); + function_requires > >(); function_requires > >(); function_requires > >(); function_requires > >(); @@ -162,6 +163,7 @@ void instantiate(RealType) function_requires > >(); function_requires > >(); function_requires > >(); + function_requires > >(); function_requires > >(); function_requires > >(); function_requires > >(); @@ -199,6 +201,7 @@ void instantiate(RealType) function_requires >(); function_requires >(); function_requires >(); + function_requires >(); function_requires >(); function_requires >(); function_requires >(); @@ -265,6 +268,8 @@ void instantiate(RealType) boost::math::gamma_q(v1, v2); boost::math::lgamma_q(v1, v2); boost::math::lgamma_p(v1, v2); + boost::math::ligamma(v1, v2); + boost::math::ligamma_lower(v1, v2); boost::math::gamma_p_inv(v1, v2); boost::math::gamma_q_inv(v1, v2); boost::math::gamma_p_inva(v1, v2); @@ -275,9 +280,12 @@ void instantiate(RealType) boost::math::erfc_inv(v1); boost::math::beta(v1, v2); boost::math::beta(v1, v2, v3); + boost::math::lbeta(v1, v2); boost::math::betac(v1, v2, v3); boost::math::ibeta(v1, v2, v3); boost::math::ibetac(v1, v2, v3); + boost::math::libeta(v1, v2, v3); + boost::math::libetac(v1, v2, v3); boost::math::ibeta_inv(v1, v2, v3); boost::math::ibetac_inv(v1, v2, v3); boost::math::ibeta_inva(v1, v2, v3); @@ -546,6 +554,8 @@ void instantiate(RealType) boost::math::gamma_q(v1 * 1, v2 + 0); boost::math::lgamma_q(v1 * 1, v2 + 0); boost::math::lgamma_p(v1 * 1, v2 + 0); + boost::math::ligamma(v1 * 1, v2 + 0); + boost::math::ligamma_lower(v1 * 1, v2 + 0); boost::math::gamma_p_inv(v1 * 1, v2 + 0); boost::math::gamma_q_inv(v1 * 1, v2 + 0); boost::math::gamma_p_inva(v1 * 1, v2 + 0); @@ -556,9 +566,12 @@ void instantiate(RealType) boost::math::erfc_inv(v1 * 1); boost::math::beta(v1 * 1, v2 + 0); boost::math::beta(v1 * 1, v2 + 0, v3 / 1); + boost::math::lbeta(v1 * 1, v2 + 0); boost::math::betac(v1 * 1, v2 + 0, v3 / 1); boost::math::ibeta(v1 * 1, v2 + 0, v3 / 1); boost::math::ibetac(v1 * 1, v2 + 0, v3 / 1); + boost::math::libeta(v1 * 1, v2 + 0, v3 / 1); + boost::math::libetac(v1 * 1, v2 + 0, v3 / 1); boost::math::ibeta_inv(v1 * 1, v2 + 0, v3 / 1); boost::math::ibetac_inv(v1 * 1, v2 + 0, v3 / 1); boost::math::ibeta_inva(v1 * 1, v2 + 0, v3 / 1); @@ -799,6 +812,8 @@ void instantiate(RealType) boost::math::gamma_q(v1, v2, pol); boost::math::lgamma_q(v1, v2, pol); boost::math::lgamma_p(v1, v2, pol); + boost::math::ligamma(v1, v2, pol); + boost::math::ligamma_lower(v1, v2, pol); boost::math::gamma_p_inv(v1, v2, pol); boost::math::gamma_q_inv(v1, v2, pol); boost::math::gamma_p_inva(v1, v2, pol); @@ -809,9 +824,12 @@ void instantiate(RealType) boost::math::erfc_inv(v1, pol); boost::math::beta(v1, v2, pol); boost::math::beta(v1, v2, v3, pol); + boost::math::lbeta(v1, v2, pol); boost::math::betac(v1, v2, v3, pol); boost::math::ibeta(v1, v2, v3, pol); boost::math::ibetac(v1, v2, v3, pol); + boost::math::libeta(v1, v2, v3, pol); + boost::math::libetac(v1, v2, v3, pol); boost::math::ibeta_inv(v1, v2, v3, pol); boost::math::ibetac_inv(v1, v2, v3, pol); boost::math::ibeta_inva(v1, v2, v3, pol); @@ -1078,6 +1096,8 @@ void instantiate(RealType) test::gamma_q(v1, v2); test::lgamma_q(v1, v2); test::lgamma_p(v1, v2); + test::ligamma(v1, v2); + test::ligamma_lower(v1, v2); test::gamma_p_inv(v1, v2); test::gamma_q_inv(v1, v2); test::gamma_p_inva(v1, v2); @@ -1088,9 +1108,12 @@ void instantiate(RealType) test::erfc_inv(v1); test::beta(v1, v2); test::beta(v1, v2, v3); + test::lbeta(v1, v2); test::betac(v1, v2, v3); test::ibeta(v1, v2, v3); test::ibetac(v1, v2, v3); + test::libeta(v1, v2, v3); + test::libetac(v1, v2, v3); test::ibeta_inv(v1, v2, v3); test::ibetac_inv(v1, v2, v3); test::ibeta_inva(v1, v2, v3); @@ -1361,6 +1384,8 @@ void instantiate_mixed(RealType) boost::math::gamma_q(i, s); boost::math::lgamma_q(i, s); boost::math::lgamma_p(i, s); + boost::math::ligamma(i, s); + boost::math::ligamma_lower(i, s); boost::math::gamma_q(fr, lr); boost::math::gamma_p_inv(i, fr); boost::math::gamma_q_inv(s, fr); @@ -1375,6 +1400,7 @@ void instantiate_mixed(RealType) } boost::math::erfc_inv(i); boost::math::beta(i, s); + boost::math::lbeta(i, s); boost::math::beta(fr, lr); boost::math::beta(i, s, l); boost::math::beta(fr, dr, lr); @@ -1384,6 +1410,8 @@ void instantiate_mixed(RealType) boost::math::ibeta(fr, dr, lr); boost::math::ibetac(l, i, s); boost::math::ibetac(fr, dr, lr); + boost::math::libeta(fr, dr, lr); + boost::math::libetac(fr, dr, lr); boost::math::ibeta_inv(l, s, i); boost::math::ibeta_inv(fr, dr, lr); boost::math::ibetac_inv(l, i, s); @@ -1578,6 +1606,8 @@ void instantiate_mixed(RealType) boost::math::gamma_q(i, s, pol); boost::math::lgamma_q(i, s, pol); boost::math::lgamma_p(i, s, pol); + boost::math::ligamma(i, s, pol); + boost::math::ligamma_lower(i, s, pol); boost::math::gamma_q(fr, lr, pol); boost::math::gamma_p_inv(i, fr, pol); boost::math::gamma_q_inv(s, fr, pol); @@ -1592,6 +1622,7 @@ void instantiate_mixed(RealType) } boost::math::erfc_inv(i, pol); boost::math::beta(i, s, pol); + boost::math::lbeta(i, s, pol); boost::math::beta(fr, lr, pol); boost::math::beta(i, s, l, pol); boost::math::beta(fr, dr, lr, pol); @@ -1601,6 +1632,8 @@ void instantiate_mixed(RealType) boost::math::ibeta(fr, dr, lr, pol); boost::math::ibetac(l, i, s, pol); boost::math::ibetac(fr, dr, lr, pol); + boost::math::libeta(fr, dr, lr, pol); + boost::math::libetac(fr, dr, lr, pol); boost::math::ibeta_inv(l, s, i, pol); boost::math::ibeta_inv(fr, dr, lr, pol); boost::math::ibetac_inv(l, i, s, pol); @@ -1794,6 +1827,8 @@ void instantiate_mixed(RealType) test::gamma_q(fr, lr); test::lgamma_q(fr, lr); test::lgamma_p(fr, lr); + test::ligamma(fr, lr); + test::ligamma_lower(fr, lr); test::gamma_p_inv(i, fr); test::gamma_q_inv(s, fr); test::gamma_p_inva(i, lr); @@ -1808,6 +1843,8 @@ void instantiate_mixed(RealType) test::erfc_inv(i); test::beta(i, s); test::beta(fr, lr); + test::lbeta(i, s); + test::lbeta(fr, lr); test::beta(i, s, l); test::beta(fr, dr, lr); test::betac(l, i, s); @@ -1816,6 +1853,8 @@ void instantiate_mixed(RealType) test::ibeta(fr, dr, lr); test::ibetac(l, i, s); test::ibetac(fr, dr, lr); + test::libeta(fr, dr, lr); + test::libetac(fr, dr, lr); test::ibeta_inv(l, s, i); test::ibeta_inv(fr, dr, lr); test::ibetac_inv(l, i, s); diff --git a/test/compile_test/interpolators_cardinal_trig_incl_test.cpp b/test/compile_test/interpolators_cardinal_trig_incl_test.cpp deleted file mode 100644 index 937a19c7e3..0000000000 --- a/test/compile_test/interpolators_cardinal_trig_incl_test.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright Matt Borland 2021. -// 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) -// -// A sanity check that this file -// #includes all the files that it needs to. -// -#if __has_include() - -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" -// -// This test includes because many of the interpolators are not compatible with pointers/c-style arrays -// -#include - -void compile_and_link_test() -{ - std::vector data = { 1, 2, 3 }; - boost::math::interpolators::cardinal_trigonometric> s(data, 3, 2); - check_result(s(1.0)); -} -#else -void compile_and_link_test() {} -#endif // __has_include diff --git a/test/compile_test/jso_incl_test.cpp b/test/compile_test/jso_incl_test.cpp deleted file mode 100644 index 2e1d91113b..0000000000 --- a/test/compile_test/jso_incl_test.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright Nick Thompson 2024. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](std::vector const & v) { return v[0]*v[0]; }; - boost::math::optimization::jso_parameters> params; - std::mt19937_64 gen(12345); - auto v = boost::math::optimization::jso(f, params, gen); -} diff --git a/test/compile_test/quad_exp_sinh_incl_test.cpp b/test/compile_test/quad_exp_sinh_incl_test.cpp deleted file mode 100644 index 6513110557..0000000000 --- a/test/compile_test/quad_exp_sinh_incl_test.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright Nick Thompson 2017. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - boost::math::quadrature::exp_sinh integrator; - check_result(integrator.integrate(f)); -} diff --git a/test/compile_test/quad_gauss_incl_test.cpp b/test/compile_test/quad_gauss_incl_test.cpp deleted file mode 100644 index 93e12a9c62..0000000000 --- a/test/compile_test/quad_gauss_incl_test.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright Matt Borland 2021. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - boost::math::quadrature::gauss integrator; - check_result(integrator.integrate(f)); -} diff --git a/test/compile_test/quad_gauss_kronrod_incl_test.cpp b/test/compile_test/quad_gauss_kronrod_incl_test.cpp deleted file mode 100644 index 801ddc33d3..0000000000 --- a/test/compile_test/quad_gauss_kronrod_incl_test.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright Matt Borland 2021. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - boost::math::quadrature::gauss integrator; - check_result(integrator.integrate(f)); -} diff --git a/test/compile_test/quad_naive_monte_carlo_concept_test.cpp b/test/compile_test/quad_naive_monte_carlo_concept_test.cpp deleted file mode 100644 index 96365618ec..0000000000 --- a/test/compile_test/quad_naive_monte_carlo_concept_test.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Nick Thompson, 2017 - * 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) - */ - -#if !defined(BOOST_MATH_STANDALONE) && (!defined(_MSC_VER) || (_MSC_VER >= 1900)) - -#include -#include - -using boost::math::concepts::std_real_concept; -using boost::math::quadrature::naive_monte_carlo; - -void compile_and_link_test() -{ - auto g = [&](std::vector const &) - { - return 1.873; - }; - std::vector> bounds{{0, 1}, {0, 1}, {0, 1}}; - naive_monte_carlo mc(g, bounds, 1.0); - - auto task = mc.integrate(); - task.get(); -} - -#else -void compile_and_link_test() -{ -} -#endif diff --git a/test/compile_test/quad_ooura_fourier_integrals_incl_test.cpp b/test/compile_test/quad_ooura_fourier_integrals_incl_test.cpp deleted file mode 100644 index 17303d4bc9..0000000000 --- a/test/compile_test/quad_ooura_fourier_integrals_incl_test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright Matt Borland 2021. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -#ifndef _MSC_VER -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - boost::math::quadrature::ooura_fourier_sin sin_integrator; - boost::math::quadrature::ooura_fourier_cos cos_integrator; - check_result>(sin_integrator.integrate(f, 1.0)); - check_result>(cos_integrator.integrate(f, 1.0)); -} -#endif diff --git a/test/compile_test/quad_sinh_sinh_incl_test.cpp b/test/compile_test/quad_sinh_sinh_incl_test.cpp deleted file mode 100644 index 8b58c14fba..0000000000 --- a/test/compile_test/quad_sinh_sinh_incl_test.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright Nick Thompson 2017. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - boost::math::quadrature::sinh_sinh integrator; - check_result(integrator.integrate(f)); -} diff --git a/test/compile_test/quad_tanh_sinh_incl_test.cpp b/test/compile_test/quad_tanh_sinh_incl_test.cpp deleted file mode 100644 index bf794c75ba..0000000000 --- a/test/compile_test/quad_tanh_sinh_incl_test.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright Nick Thompson 2017. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - boost::math::quadrature::tanh_sinh integrator; - check_result(integrator.integrate(f)); -} diff --git a/test/compile_test/quad_wavelet_transforms_incl_test.cpp b/test/compile_test/quad_wavelet_transforms_incl_test.cpp deleted file mode 100644 index 71f9457b97..0000000000 --- a/test/compile_test/quad_wavelet_transforms_incl_test.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright Matt Borland 2021. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - auto psi = boost::math::daubechies_wavelet(); - auto Wf = boost::math::quadrature::daubechies_wavelet_transform(f, psi); - check_result(Wf(0.0, 0.0)); -} diff --git a/test/compile_test/random_search_incl_test.cpp b/test/compile_test/random_search_incl_test.cpp deleted file mode 100644 index ddffd733c2..0000000000 --- a/test/compile_test/random_search_incl_test.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright Nick Thompson 2024. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](std::vector const & v) { return v[0]*v[0]; }; - boost::math::optimization::random_search_parameters> params; - std::mt19937_64 gen(12345); - auto v = boost::math::optimization::random_search(f, params, gen); -} diff --git a/test/compile_test/sf_beta_incl_test.cpp b/test/compile_test/sf_beta_incl_test.cpp deleted file mode 100644 index e20431c67a..0000000000 --- a/test/compile_test/sf_beta_incl_test.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright John Maddock 2006. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - check_result(boost::math::beta(f, f)); - check_result(boost::math::beta(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::beta(l, l)); -#endif - - check_result(boost::math::ibeta(f, f, f)); - check_result(boost::math::ibeta(d, d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::ibeta(l, l, l)); -#endif - - check_result(boost::math::ibeta_inv(f, f, f)); - check_result(boost::math::ibeta_inv(d, d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::ibeta_inv(l, l, l)); -#endif - - check_result(boost::math::ibeta_inva(f, f, f)); - check_result(boost::math::ibeta_inva(d, d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::ibeta_inva(l, l, l)); -#endif -} - diff --git a/test/compile_test/sf_chebyshev_transform_incl_test.cpp b/test/compile_test/sf_chebyshev_transform_incl_test.cpp deleted file mode 100644 index 3416f5b1ab..0000000000 --- a/test/compile_test/sf_chebyshev_transform_incl_test.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright Matt Borland 2021 -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#if __has_include() - -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - boost::math::chebyshev_transform test(f, 0.0, 1.0); - check_result(test(1.0)); -} - -#else -void compile_and_link_test() {} -#endif // __has_include diff --git a/test/compile_test/sf_gamma_incl_test.cpp b/test/compile_test/sf_gamma_incl_test.cpp deleted file mode 100644 index 85045c857d..0000000000 --- a/test/compile_test/sf_gamma_incl_test.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright John Maddock 2006. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - check_result(boost::math::tgamma(f)); - check_result(boost::math::tgamma(d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::tgamma(l)); -#endif - - check_result(boost::math::lgamma(f)); - check_result(boost::math::lgamma(d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::lgamma(l)); -#endif - - check_result(boost::math::gamma_p(f, f)); - check_result(boost::math::gamma_p(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::gamma_p(l, l)); -#endif - - check_result(boost::math::gamma_q(f, f)); - check_result(boost::math::gamma_q(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::gamma_q(l, l)); -#endif - - check_result(boost::math::lgamma_q(f, f)); - check_result(boost::math::lgamma_q(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::lgamma_q(l, l)); -#endif - -check_result(boost::math::lgamma_p(f, f)); -check_result(boost::math::lgamma_p(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::lgamma_p(l, l)); -#endif - - check_result(boost::math::gamma_p_inv(f, f)); - check_result(boost::math::gamma_p_inv(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::gamma_p_inv(l, l)); -#endif - - check_result(boost::math::gamma_q_inv(f, f)); - check_result(boost::math::gamma_q_inv(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::gamma_q_inv(l, l)); -#endif - - check_result(boost::math::gamma_p_inva(f, f)); - check_result(boost::math::gamma_p_inva(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::gamma_p_inva(l, l)); -#endif - - check_result(boost::math::gamma_q_inva(f, f)); - check_result(boost::math::gamma_q_inva(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::gamma_q_inva(l, l)); -#endif - - check_result(boost::math::gamma_p_derivative(f, f)); - check_result(boost::math::gamma_p_derivative(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::gamma_p_derivative(l, l)); -#endif - - check_result(boost::math::tgamma_ratio(f, f)); - check_result(boost::math::tgamma_ratio(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::tgamma_ratio(l, l)); -#endif - - check_result(boost::math::tgamma_delta_ratio(f, f)); - check_result(boost::math::tgamma_delta_ratio(d, d)); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - check_result(boost::math::tgamma_delta_ratio(l, l)); -#endif -} diff --git a/test/compile_test/ccmath_abs_incl_test.cpp b/test/compile_test/test_ccmath_abs_incl.cpp similarity index 100% rename from test/compile_test/ccmath_abs_incl_test.cpp rename to test/compile_test/test_ccmath_abs_incl.cpp diff --git a/test/compile_test/ccmath_ceil_incl_test.cpp b/test/compile_test/test_ccmath_ceil_incl.cpp similarity index 100% rename from test/compile_test/ccmath_ceil_incl_test.cpp rename to test/compile_test/test_ccmath_ceil_incl.cpp diff --git a/test/compile_test/ccmath_copysign_incl_test.cpp b/test/compile_test/test_ccmath_copysign_incl.cpp similarity index 100% rename from test/compile_test/ccmath_copysign_incl_test.cpp rename to test/compile_test/test_ccmath_copysign_incl.cpp diff --git a/test/compile_test/ccmath_div_incl_test.cpp b/test/compile_test/test_ccmath_div_incl.cpp similarity index 100% rename from test/compile_test/ccmath_div_incl_test.cpp rename to test/compile_test/test_ccmath_div_incl.cpp diff --git a/test/compile_test/ccmath_fdim_incl_test.cpp b/test/compile_test/test_ccmath_fdim_incl.cpp similarity index 100% rename from test/compile_test/ccmath_fdim_incl_test.cpp rename to test/compile_test/test_ccmath_fdim_incl.cpp diff --git a/test/compile_test/ccmath_floor_incl_test.cpp b/test/compile_test/test_ccmath_floor_incl.cpp similarity index 100% rename from test/compile_test/ccmath_floor_incl_test.cpp rename to test/compile_test/test_ccmath_floor_incl.cpp diff --git a/test/compile_test/ccmath_fma_incl_test.cpp b/test/compile_test/test_ccmath_fma_incl.cpp similarity index 100% rename from test/compile_test/ccmath_fma_incl_test.cpp rename to test/compile_test/test_ccmath_fma_incl.cpp diff --git a/test/compile_test/ccmath_fmax_incl_test.cpp b/test/compile_test/test_ccmath_fmax_incl.cpp similarity index 100% rename from test/compile_test/ccmath_fmax_incl_test.cpp rename to test/compile_test/test_ccmath_fmax_incl.cpp diff --git a/test/compile_test/ccmath_fmin_incl_test.cpp b/test/compile_test/test_ccmath_fmin_incl.cpp similarity index 100% rename from test/compile_test/ccmath_fmin_incl_test.cpp rename to test/compile_test/test_ccmath_fmin_incl.cpp diff --git a/test/compile_test/ccmath_fmod_incl_test.cpp b/test/compile_test/test_ccmath_fmod_incl.cpp similarity index 100% rename from test/compile_test/ccmath_fmod_incl_test.cpp rename to test/compile_test/test_ccmath_fmod_incl.cpp diff --git a/test/compile_test/ccmath_fpclassify_incl_test.cpp b/test/compile_test/test_ccmath_fpclassify_incl.cpp similarity index 100% rename from test/compile_test/ccmath_fpclassify_incl_test.cpp rename to test/compile_test/test_ccmath_fpclassify_incl.cpp diff --git a/test/compile_test/test_ccmath_frexp_incl.cpp b/test/compile_test/test_ccmath_frexp_incl.cpp new file mode 100644 index 0000000000..242e34dbbc --- /dev/null +++ b/test/compile_test/test_ccmath_frexp_incl.cpp @@ -0,0 +1,17 @@ +// (C) Copyright Matt Borland 2021. +// 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) + +#include +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + int exponent; + check_result(boost::math::ccmath::frexp(1.0f, &exponent)); + check_result(boost::math::ccmath::frexp(1.0, &exponent)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::ccmath::frexp(1.0l, &exponent)); +#endif +} diff --git a/test/compile_test/ccmath_ilogb_incl_test.cpp b/test/compile_test/test_ccmath_ilogb_incl.cpp similarity index 100% rename from test/compile_test/ccmath_ilogb_incl_test.cpp rename to test/compile_test/test_ccmath_ilogb_incl.cpp diff --git a/test/compile_test/ccmath_isfinite_incl_test.cpp b/test/compile_test/test_ccmath_isfinite_incl.cpp similarity index 100% rename from test/compile_test/ccmath_isfinite_incl_test.cpp rename to test/compile_test/test_ccmath_isfinite_incl.cpp diff --git a/test/compile_test/ccmath_isgreater_incl_test.cpp b/test/compile_test/test_ccmath_isgreater_incl.cpp similarity index 100% rename from test/compile_test/ccmath_isgreater_incl_test.cpp rename to test/compile_test/test_ccmath_isgreater_incl.cpp diff --git a/test/compile_test/ccmath_isgreaterequal_incl_test.cpp b/test/compile_test/test_ccmath_isgreaterequal_incl.cpp similarity index 100% rename from test/compile_test/ccmath_isgreaterequal_incl_test.cpp rename to test/compile_test/test_ccmath_isgreaterequal_incl.cpp diff --git a/test/compile_test/ccmath_isinf_incl_test.cpp b/test/compile_test/test_ccmath_isinf_incl.cpp similarity index 100% rename from test/compile_test/ccmath_isinf_incl_test.cpp rename to test/compile_test/test_ccmath_isinf_incl.cpp diff --git a/test/compile_test/ccmath_isless_incl_test.cpp b/test/compile_test/test_ccmath_isless_incl.cpp similarity index 100% rename from test/compile_test/ccmath_isless_incl_test.cpp rename to test/compile_test/test_ccmath_isless_incl.cpp diff --git a/test/compile_test/ccmath_islessequal_incl_test.cpp b/test/compile_test/test_ccmath_islessequal_incl.cpp similarity index 100% rename from test/compile_test/ccmath_islessequal_incl_test.cpp rename to test/compile_test/test_ccmath_islessequal_incl.cpp diff --git a/test/compile_test/ccmath_isnan_incl_test.cpp b/test/compile_test/test_ccmath_isnan_incl.cpp similarity index 100% rename from test/compile_test/ccmath_isnan_incl_test.cpp rename to test/compile_test/test_ccmath_isnan_incl.cpp diff --git a/test/compile_test/ccmath_isnormal_incl_test.cpp b/test/compile_test/test_ccmath_isnormal_incl.cpp similarity index 100% rename from test/compile_test/ccmath_isnormal_incl_test.cpp rename to test/compile_test/test_ccmath_isnormal_incl.cpp diff --git a/test/compile_test/ccmath_isunordered_incl_test.cpp b/test/compile_test/test_ccmath_isunordered_incl.cpp similarity index 100% rename from test/compile_test/ccmath_isunordered_incl_test.cpp rename to test/compile_test/test_ccmath_isunordered_incl.cpp diff --git a/test/compile_test/ccmath_ldexp_incl_test.cpp b/test/compile_test/test_ccmath_ldexp_incl.cpp similarity index 100% rename from test/compile_test/ccmath_ldexp_incl_test.cpp rename to test/compile_test/test_ccmath_ldexp_incl.cpp diff --git a/test/compile_test/ccmath_logb_incl_test.cpp b/test/compile_test/test_ccmath_logb_incl.cpp similarity index 100% rename from test/compile_test/ccmath_logb_incl_test.cpp rename to test/compile_test/test_ccmath_logb_incl.cpp diff --git a/test/compile_test/ccmath_modf_incl_test.cpp b/test/compile_test/test_ccmath_modf_incl.cpp similarity index 100% rename from test/compile_test/ccmath_modf_incl_test.cpp rename to test/compile_test/test_ccmath_modf_incl.cpp diff --git a/test/compile_test/ccmath_next_incl_test.cpp b/test/compile_test/test_ccmath_next_incl.cpp similarity index 100% rename from test/compile_test/ccmath_next_incl_test.cpp rename to test/compile_test/test_ccmath_next_incl.cpp diff --git a/test/compile_test/ccmath_remainder_incl_test.cpp b/test/compile_test/test_ccmath_remainder_incl.cpp similarity index 100% rename from test/compile_test/ccmath_remainder_incl_test.cpp rename to test/compile_test/test_ccmath_remainder_incl.cpp diff --git a/test/compile_test/ccmath_round_incl_test.cpp b/test/compile_test/test_ccmath_round_incl.cpp similarity index 100% rename from test/compile_test/ccmath_round_incl_test.cpp rename to test/compile_test/test_ccmath_round_incl.cpp diff --git a/test/compile_test/ccmath_scalbln_incl_test.cpp b/test/compile_test/test_ccmath_scalbln_incl.cpp similarity index 100% rename from test/compile_test/ccmath_scalbln_incl_test.cpp rename to test/compile_test/test_ccmath_scalbln_incl.cpp diff --git a/test/compile_test/ccmath_scalbn_incl_test.cpp b/test/compile_test/test_ccmath_scalbn_incl.cpp similarity index 100% rename from test/compile_test/ccmath_scalbn_incl_test.cpp rename to test/compile_test/test_ccmath_scalbn_incl.cpp diff --git a/test/compile_test/ccmath_signbit_incl_test.cpp b/test/compile_test/test_ccmath_signbit_incl.cpp similarity index 100% rename from test/compile_test/ccmath_signbit_incl_test.cpp rename to test/compile_test/test_ccmath_signbit_incl.cpp diff --git a/test/compile_test/ccmath_sqrt_incl_test.cpp b/test/compile_test/test_ccmath_sqrt_incl.cpp similarity index 100% rename from test/compile_test/ccmath_sqrt_incl_test.cpp rename to test/compile_test/test_ccmath_sqrt_incl.cpp diff --git a/test/compile_test/ccmath_trunc_incl_test.cpp b/test/compile_test/test_ccmath_trunc_incl.cpp similarity index 100% rename from test/compile_test/ccmath_trunc_incl_test.cpp rename to test/compile_test/test_ccmath_trunc_incl.cpp diff --git a/test/compile_test/compl_abs_incl_test.cpp b/test/compile_test/test_compl_abs_incl.cpp similarity index 100% rename from test/compile_test/compl_abs_incl_test.cpp rename to test/compile_test/test_compl_abs_incl.cpp diff --git a/test/compile_test/compl_acos_incl_test.cpp b/test/compile_test/test_compl_acos_incl.cpp similarity index 100% rename from test/compile_test/compl_acos_incl_test.cpp rename to test/compile_test/test_compl_acos_incl.cpp diff --git a/test/compile_test/compl_acosh_incl_test.cpp b/test/compile_test/test_compl_acosh_incl.cpp similarity index 100% rename from test/compile_test/compl_acosh_incl_test.cpp rename to test/compile_test/test_compl_acosh_incl.cpp diff --git a/test/compile_test/compl_asin_incl_test.cpp b/test/compile_test/test_compl_asin_incl.cpp similarity index 100% rename from test/compile_test/compl_asin_incl_test.cpp rename to test/compile_test/test_compl_asin_incl.cpp diff --git a/test/compile_test/compl_asinh_incl_test.cpp b/test/compile_test/test_compl_asinh_incl.cpp similarity index 100% rename from test/compile_test/compl_asinh_incl_test.cpp rename to test/compile_test/test_compl_asinh_incl.cpp diff --git a/test/compile_test/compl_atan_incl_test.cpp b/test/compile_test/test_compl_atan_incl.cpp similarity index 100% rename from test/compile_test/compl_atan_incl_test.cpp rename to test/compile_test/test_compl_atan_incl.cpp diff --git a/test/compile_test/compl_atanh_incl_test.cpp b/test/compile_test/test_compl_atanh_incl.cpp similarity index 100% rename from test/compile_test/compl_atanh_incl_test.cpp rename to test/compile_test/test_compl_atanh_incl.cpp diff --git a/test/compile_test/constants_incl_test.cpp b/test/compile_test/test_constants_incl.cpp similarity index 100% rename from test/compile_test/constants_incl_test.cpp rename to test/compile_test/test_constants_incl.cpp diff --git a/test/compile_test/cstdfloat_cmath_incl_test.cpp b/test/compile_test/test_cstdfloat_cmath_incl.cpp similarity index 100% rename from test/compile_test/cstdfloat_cmath_incl_test.cpp rename to test/compile_test/test_cstdfloat_cmath_incl.cpp diff --git a/test/compile_test/cstdfloat_complex_incl_test.cpp b/test/compile_test/test_cstdfloat_complex_incl.cpp similarity index 100% rename from test/compile_test/cstdfloat_complex_incl_test.cpp rename to test/compile_test/test_cstdfloat_complex_incl.cpp diff --git a/test/compile_test/cstdfloat_iostream_incl_test.cpp b/test/compile_test/test_cstdfloat_iostream_incl.cpp similarity index 100% rename from test/compile_test/cstdfloat_iostream_incl_test.cpp rename to test/compile_test/test_cstdfloat_iostream_incl.cpp diff --git a/test/compile_test/cstdfloat_limits_incl_test.cpp b/test/compile_test/test_cstdfloat_limits_incl.cpp similarity index 100% rename from test/compile_test/cstdfloat_limits_incl_test.cpp rename to test/compile_test/test_cstdfloat_limits_incl.cpp diff --git a/test/compile_test/cstdfloat_types_incl_test.cpp b/test/compile_test/test_cstdfloat_types_incl.cpp similarity index 100% rename from test/compile_test/cstdfloat_types_incl_test.cpp rename to test/compile_test/test_cstdfloat_types_incl.cpp diff --git a/test/compile_test/diff_autodiff_incl_test.cpp b/test/compile_test/test_diff_autodiff_incl.cpp similarity index 100% rename from test/compile_test/diff_autodiff_incl_test.cpp rename to test/compile_test/test_diff_autodiff_incl.cpp diff --git a/test/compile_test/diff_finite_difference_incl_test.cpp b/test/compile_test/test_diff_finite_difference_incl.cpp similarity index 100% rename from test/compile_test/diff_finite_difference_incl_test.cpp rename to test/compile_test/test_diff_finite_difference_incl.cpp diff --git a/test/compile_test/diff_lanczos_smoothing_incl_test.cpp b/test/compile_test/test_diff_lanczos_smoothing_incl.cpp similarity index 100% rename from test/compile_test/diff_lanczos_smoothing_incl_test.cpp rename to test/compile_test/test_diff_lanczos_smoothing_incl.cpp diff --git a/test/compile_test/test_diff_numerical_differentiation_concept.cpp b/test/compile_test/test_diff_numerical_differentiation_concept.cpp new file mode 100644 index 0000000000..0c81393b22 --- /dev/null +++ b/test/compile_test/test_diff_numerical_differentiation_concept.cpp @@ -0,0 +1,19 @@ +// Copyright Nick Thompson 2017. +// 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) +// + +#ifndef BOOST_MATH_STANDALONE + +#include +#include + +void compile_and_link_test() +{ + boost::math::concepts::std_real_concept x = 0; + auto f = [](boost::math::concepts::std_real_concept y) { return y; }; + boost::math::differentiation::finite_difference_derivative(f, x); +} + +#endif diff --git a/test/compile_test/test_diff_numerical_differentiation_incl.cpp b/test/compile_test/test_diff_numerical_differentiation_incl.cpp new file mode 100644 index 0000000000..27a8dd52e0 --- /dev/null +++ b/test/compile_test/test_diff_numerical_differentiation_incl.cpp @@ -0,0 +1,24 @@ +// Copyright Nick Thompson 2017. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + double x = 0; + check_result(boost::math::differentiation::finite_difference_derivative(func, x)); + + auto g = [](std::complex z){ return z;}; + check_result(boost::math::differentiation::complex_step_derivative(g, x)); +} diff --git a/test/compile_test/test_differential_evolution_incl.cpp b/test/compile_test/test_differential_evolution_incl.cpp new file mode 100644 index 0000000000..93bc628568 --- /dev/null +++ b/test/compile_test/test_differential_evolution_incl.cpp @@ -0,0 +1,22 @@ +// Copyright Nick Thompson 2024. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](std::vector const & v) { return v[0]*v[0]; }; + boost::math::optimization::differential_evolution_parameters> params; + std::mt19937_64 gen(12345); + auto v = boost::math::optimization::differential_evolution(func, params, gen); +} diff --git a/test/compile_test/dist_arcsine_incl_test.cpp b/test/compile_test/test_dist_arcsine_incl.cpp similarity index 100% rename from test/compile_test/dist_arcsine_incl_test.cpp rename to test/compile_test/test_dist_arcsine_incl.cpp diff --git a/test/compile_test/dist_bernoulli_incl_test.cpp b/test/compile_test/test_dist_bernoulli_incl.cpp similarity index 100% rename from test/compile_test/dist_bernoulli_incl_test.cpp rename to test/compile_test/test_dist_bernoulli_incl.cpp diff --git a/test/compile_test/dist_beta_incl_test.cpp b/test/compile_test/test_dist_beta_incl.cpp similarity index 100% rename from test/compile_test/dist_beta_incl_test.cpp rename to test/compile_test/test_dist_beta_incl.cpp diff --git a/test/compile_test/dist_binomial_incl_test.cpp b/test/compile_test/test_dist_binomial_incl.cpp similarity index 100% rename from test/compile_test/dist_binomial_incl_test.cpp rename to test/compile_test/test_dist_binomial_incl.cpp diff --git a/test/compile_test/dist_cauchy_incl_test.cpp b/test/compile_test/test_dist_cauchy_incl.cpp similarity index 100% rename from test/compile_test/dist_cauchy_incl_test.cpp rename to test/compile_test/test_dist_cauchy_incl.cpp diff --git a/test/compile_test/dist_chi_squared_incl_test.cpp b/test/compile_test/test_dist_chi_squared_incl.cpp similarity index 100% rename from test/compile_test/dist_chi_squared_incl_test.cpp rename to test/compile_test/test_dist_chi_squared_incl.cpp diff --git a/test/compile_test/dist_complement_incl_test.cpp b/test/compile_test/test_dist_complement_incl.cpp similarity index 100% rename from test/compile_test/dist_complement_incl_test.cpp rename to test/compile_test/test_dist_complement_incl.cpp diff --git a/test/compile_test/dist_empirical_cumulative_dist_func_incl_test.cpp b/test/compile_test/test_dist_empirical_cumulative_dist_func_incl.cpp similarity index 100% rename from test/compile_test/dist_empirical_cumulative_dist_func_incl_test.cpp rename to test/compile_test/test_dist_empirical_cumulative_dist_func_incl.cpp diff --git a/test/compile_test/dist_exponential_incl_test.cpp b/test/compile_test/test_dist_exponential_incl.cpp similarity index 100% rename from test/compile_test/dist_exponential_incl_test.cpp rename to test/compile_test/test_dist_exponential_incl.cpp diff --git a/test/compile_test/dist_extreme_val_incl_test.cpp b/test/compile_test/test_dist_extreme_val_incl.cpp similarity index 100% rename from test/compile_test/dist_extreme_val_incl_test.cpp rename to test/compile_test/test_dist_extreme_val_incl.cpp diff --git a/test/compile_test/dist_find_location_incl_test.cpp b/test/compile_test/test_dist_find_location_incl.cpp similarity index 100% rename from test/compile_test/dist_find_location_incl_test.cpp rename to test/compile_test/test_dist_find_location_incl.cpp diff --git a/test/compile_test/dist_find_scale_incl_test.cpp b/test/compile_test/test_dist_find_scale_incl.cpp similarity index 100% rename from test/compile_test/dist_find_scale_incl_test.cpp rename to test/compile_test/test_dist_find_scale_incl.cpp diff --git a/test/compile_test/dist_fisher_f_incl_test.cpp b/test/compile_test/test_dist_fisher_f_incl.cpp similarity index 100% rename from test/compile_test/dist_fisher_f_incl_test.cpp rename to test/compile_test/test_dist_fisher_f_incl.cpp diff --git a/test/compile_test/dist_gamma_incl_test.cpp b/test/compile_test/test_dist_gamma_incl.cpp similarity index 100% rename from test/compile_test/dist_gamma_incl_test.cpp rename to test/compile_test/test_dist_gamma_incl.cpp diff --git a/test/compile_test/test_dist_generalized_extreme_value_incl.cpp b/test/compile_test/test_dist_generalized_extreme_value_incl.cpp new file mode 100644 index 0000000000..313f88611e --- /dev/null +++ b/test/compile_test/test_dist_generalized_extreme_value_incl.cpp @@ -0,0 +1,25 @@ +// Copyright Nick Thompson 2026. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + TEST_DIST_FUNC(generalized_extreme_value) +} + +template class boost::math::generalized_extreme_value_distribution >; +template class boost::math::generalized_extreme_value_distribution >; +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +template class boost::math::generalized_extreme_value_distribution >; +#endif diff --git a/test/compile_test/dist_geometric_incl_test.cpp b/test/compile_test/test_dist_geometric_incl.cpp similarity index 100% rename from test/compile_test/dist_geometric_incl_test.cpp rename to test/compile_test/test_dist_geometric_incl.cpp diff --git a/test/compile_test/dist_holtsmark_incl_test.cpp b/test/compile_test/test_dist_holtsmark_incl.cpp similarity index 100% rename from test/compile_test/dist_holtsmark_incl_test.cpp rename to test/compile_test/test_dist_holtsmark_incl.cpp diff --git a/test/compile_test/dist_hyperexponential_incl_test.cpp b/test/compile_test/test_dist_hyperexponential_incl.cpp similarity index 100% rename from test/compile_test/dist_hyperexponential_incl_test.cpp rename to test/compile_test/test_dist_hyperexponential_incl.cpp diff --git a/test/compile_test/dist_hypergeo_incl_test.cpp b/test/compile_test/test_dist_hypergeo_incl.cpp similarity index 100% rename from test/compile_test/dist_hypergeo_incl_test.cpp rename to test/compile_test/test_dist_hypergeo_incl.cpp diff --git a/test/compile_test/dist_inv_chi_sq_incl_test.cpp b/test/compile_test/test_dist_inv_chi_sq_incl.cpp similarity index 100% rename from test/compile_test/dist_inv_chi_sq_incl_test.cpp rename to test/compile_test/test_dist_inv_chi_sq_incl.cpp diff --git a/test/compile_test/dist_inv_gamma_incl_test.cpp b/test/compile_test/test_dist_inv_gamma_incl.cpp similarity index 100% rename from test/compile_test/dist_inv_gamma_incl_test.cpp rename to test/compile_test/test_dist_inv_gamma_incl.cpp diff --git a/test/compile_test/dist_inv_gaussian_incl_test.cpp b/test/compile_test/test_dist_inv_gaussian_incl.cpp similarity index 100% rename from test/compile_test/dist_inv_gaussian_incl_test.cpp rename to test/compile_test/test_dist_inv_gaussian_incl.cpp diff --git a/test/compile_test/dist_kolmogorov_smirnov_incl_test.cpp b/test/compile_test/test_dist_kolmogorov_smirnov_incl.cpp similarity index 100% rename from test/compile_test/dist_kolmogorov_smirnov_incl_test.cpp rename to test/compile_test/test_dist_kolmogorov_smirnov_incl.cpp diff --git a/test/compile_test/dist_landau_incl_test.cpp b/test/compile_test/test_dist_landau_incl.cpp similarity index 100% rename from test/compile_test/dist_landau_incl_test.cpp rename to test/compile_test/test_dist_landau_incl.cpp diff --git a/test/compile_test/dist_laplace_incl_test.cpp b/test/compile_test/test_dist_laplace_incl.cpp similarity index 100% rename from test/compile_test/dist_laplace_incl_test.cpp rename to test/compile_test/test_dist_laplace_incl.cpp diff --git a/test/compile_test/dist_logistic_incl_test.cpp b/test/compile_test/test_dist_logistic_incl.cpp similarity index 100% rename from test/compile_test/dist_logistic_incl_test.cpp rename to test/compile_test/test_dist_logistic_incl.cpp diff --git a/test/compile_test/dist_lognormal_incl_test.cpp b/test/compile_test/test_dist_lognormal_incl.cpp similarity index 100% rename from test/compile_test/dist_lognormal_incl_test.cpp rename to test/compile_test/test_dist_lognormal_incl.cpp diff --git a/test/compile_test/dist_mapairy_incl_test.cpp b/test/compile_test/test_dist_mapairy_incl.cpp similarity index 100% rename from test/compile_test/dist_mapairy_incl_test.cpp rename to test/compile_test/test_dist_mapairy_incl.cpp diff --git a/test/compile_test/dist_nc_beta_incl_test.cpp b/test/compile_test/test_dist_nc_beta_incl.cpp similarity index 100% rename from test/compile_test/dist_nc_beta_incl_test.cpp rename to test/compile_test/test_dist_nc_beta_incl.cpp diff --git a/test/compile_test/dist_nc_chi_squ_incl_test.cpp b/test/compile_test/test_dist_nc_chi_squ_incl.cpp similarity index 100% rename from test/compile_test/dist_nc_chi_squ_incl_test.cpp rename to test/compile_test/test_dist_nc_chi_squ_incl.cpp diff --git a/test/compile_test/dist_nc_f_incl_test.cpp b/test/compile_test/test_dist_nc_f_incl.cpp similarity index 100% rename from test/compile_test/dist_nc_f_incl_test.cpp rename to test/compile_test/test_dist_nc_f_incl.cpp diff --git a/test/compile_test/dist_nc_t_incl_test.cpp b/test/compile_test/test_dist_nc_t_incl.cpp similarity index 100% rename from test/compile_test/dist_nc_t_incl_test.cpp rename to test/compile_test/test_dist_nc_t_incl.cpp diff --git a/test/compile_test/dist_neg_binom_incl_test.cpp b/test/compile_test/test_dist_neg_binom_incl.cpp similarity index 100% rename from test/compile_test/dist_neg_binom_incl_test.cpp rename to test/compile_test/test_dist_neg_binom_incl.cpp diff --git a/test/compile_test/dist_normal_incl_test.cpp b/test/compile_test/test_dist_normal_incl.cpp similarity index 100% rename from test/compile_test/dist_normal_incl_test.cpp rename to test/compile_test/test_dist_normal_incl.cpp diff --git a/test/compile_test/dist_pareto_incl_test.cpp b/test/compile_test/test_dist_pareto_incl.cpp similarity index 100% rename from test/compile_test/dist_pareto_incl_test.cpp rename to test/compile_test/test_dist_pareto_incl.cpp diff --git a/test/compile_test/dist_poisson_incl_test.cpp b/test/compile_test/test_dist_poisson_incl.cpp similarity index 100% rename from test/compile_test/dist_poisson_incl_test.cpp rename to test/compile_test/test_dist_poisson_incl.cpp diff --git a/test/compile_test/dist_saspoint5_incl_test.cpp b/test/compile_test/test_dist_saspoint5_incl.cpp similarity index 100% rename from test/compile_test/dist_saspoint5_incl_test.cpp rename to test/compile_test/test_dist_saspoint5_incl.cpp diff --git a/test/compile_test/dist_skew_norm_incl_test.cpp b/test/compile_test/test_dist_skew_norm_incl.cpp similarity index 100% rename from test/compile_test/dist_skew_norm_incl_test.cpp rename to test/compile_test/test_dist_skew_norm_incl.cpp diff --git a/test/compile_test/dist_students_t_incl_test.cpp b/test/compile_test/test_dist_students_t_incl.cpp similarity index 100% rename from test/compile_test/dist_students_t_incl_test.cpp rename to test/compile_test/test_dist_students_t_incl.cpp diff --git a/test/compile_test/dist_triangular_incl_test.cpp b/test/compile_test/test_dist_triangular_incl.cpp similarity index 100% rename from test/compile_test/dist_triangular_incl_test.cpp rename to test/compile_test/test_dist_triangular_incl.cpp diff --git a/test/compile_test/dist_uniform_incl_test.cpp b/test/compile_test/test_dist_uniform_incl.cpp similarity index 100% rename from test/compile_test/dist_uniform_incl_test.cpp rename to test/compile_test/test_dist_uniform_incl.cpp diff --git a/test/compile_test/dist_weibull_incl_test.cpp b/test/compile_test/test_dist_weibull_incl.cpp similarity index 100% rename from test/compile_test/dist_weibull_incl_test.cpp rename to test/compile_test/test_dist_weibull_incl.cpp diff --git a/test/compile_test/filters_daubechies_incl_test.cpp b/test/compile_test/test_filters_daubechies_incl.cpp similarity index 100% rename from test/compile_test/filters_daubechies_incl_test.cpp rename to test/compile_test/test_filters_daubechies_incl.cpp diff --git a/test/compile_test/gauss_concept_test.cpp b/test/compile_test/test_gauss_concept.cpp similarity index 100% rename from test/compile_test/gauss_concept_test.cpp rename to test/compile_test/test_gauss_concept.cpp diff --git a/test/compile_test/gauss_kronrod_concept_test.cpp b/test/compile_test/test_gauss_kronrod_concept.cpp similarity index 100% rename from test/compile_test/gauss_kronrod_concept_test.cpp rename to test/compile_test/test_gauss_kronrod_concept.cpp diff --git a/test/compile_test/interpolators_barycentric_rational_concept_test.cpp b/test/compile_test/test_interpolators_barycentric_rational_concept.cpp similarity index 100% rename from test/compile_test/interpolators_barycentric_rational_concept_test.cpp rename to test/compile_test/test_interpolators_barycentric_rational_concept.cpp diff --git a/test/compile_test/interpolators_barycentric_rational_incl_test.cpp b/test/compile_test/test_interpolators_barycentric_rational_incl.cpp similarity index 100% rename from test/compile_test/interpolators_barycentric_rational_incl_test.cpp rename to test/compile_test/test_interpolators_barycentric_rational_incl.cpp diff --git a/test/compile_test/interpolators_bezier_polynomial_incl_test.cpp b/test/compile_test/test_interpolators_bezier_polynomial_incl.cpp similarity index 100% rename from test/compile_test/interpolators_bezier_polynomial_incl_test.cpp rename to test/compile_test/test_interpolators_bezier_polynomial_incl.cpp diff --git a/test/compile_test/test_interpolators_cardinal_trig_incl.cpp b/test/compile_test/test_interpolators_cardinal_trig_incl.cpp new file mode 100644 index 0000000000..2de703f17a --- /dev/null +++ b/test/compile_test/test_interpolators_cardinal_trig_incl.cpp @@ -0,0 +1,25 @@ +// Copyright Matt Borland 2021. +// 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) +// +// A sanity check that this file +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" +// +// This test includes because many of the interpolators are not compatible with pointers/c-style arrays +// +#include + +void compile_and_link_test() +{ + std::vector data = { 1, 2, 3 }; + boost::math::interpolators::cardinal_trigonometric> s(data, 3, 2); + check_result(s(1.0)); +} diff --git a/test/compile_test/interpolators_catmull_rom_concept_test.cpp b/test/compile_test/test_interpolators_catmull_rom_concept.cpp similarity index 100% rename from test/compile_test/interpolators_catmull_rom_concept_test.cpp rename to test/compile_test/test_interpolators_catmull_rom_concept.cpp diff --git a/test/compile_test/interpolators_catmull_rom_incl_test.cpp b/test/compile_test/test_interpolators_catmull_rom_incl.cpp similarity index 100% rename from test/compile_test/interpolators_catmull_rom_incl_test.cpp rename to test/compile_test/test_interpolators_catmull_rom_incl.cpp diff --git a/test/compile_test/interpolators_cubic_hermite_incl_test.cpp b/test/compile_test/test_interpolators_cubic_hermite_incl.cpp similarity index 100% rename from test/compile_test/interpolators_cubic_hermite_incl_test.cpp rename to test/compile_test/test_interpolators_cubic_hermite_incl.cpp diff --git a/test/compile_test/interpolators_cubic_spline_concept_test.cpp b/test/compile_test/test_interpolators_cubic_spline_concept.cpp similarity index 100% rename from test/compile_test/interpolators_cubic_spline_concept_test.cpp rename to test/compile_test/test_interpolators_cubic_spline_concept.cpp diff --git a/test/compile_test/interpolators_cubic_spline_incl_test.cpp b/test/compile_test/test_interpolators_cubic_spline_incl.cpp similarity index 100% rename from test/compile_test/interpolators_cubic_spline_incl_test.cpp rename to test/compile_test/test_interpolators_cubic_spline_incl.cpp diff --git a/test/compile_test/interpolators_makima_incl_test.cpp b/test/compile_test/test_interpolators_makima_incl.cpp similarity index 100% rename from test/compile_test/interpolators_makima_incl_test.cpp rename to test/compile_test/test_interpolators_makima_incl.cpp diff --git a/test/compile_test/interpolators_pchip_incl_test.cpp b/test/compile_test/test_interpolators_pchip_incl.cpp similarity index 100% rename from test/compile_test/interpolators_pchip_incl_test.cpp rename to test/compile_test/test_interpolators_pchip_incl.cpp diff --git a/test/compile_test/interpolators_quintic_hermite_incl_test.cpp b/test/compile_test/test_interpolators_quintic_hermite_incl.cpp similarity index 100% rename from test/compile_test/interpolators_quintic_hermite_incl_test.cpp rename to test/compile_test/test_interpolators_quintic_hermite_incl.cpp diff --git a/test/compile_test/interpolators_septic_hermite_incl_test.cpp b/test/compile_test/test_interpolators_septic_hermite_incl.cpp similarity index 100% rename from test/compile_test/interpolators_septic_hermite_incl_test.cpp rename to test/compile_test/test_interpolators_septic_hermite_incl.cpp diff --git a/test/compile_test/interpolators_vector_barycentric_rational_incl_test.cpp b/test/compile_test/test_interpolators_vector_barycentric_rational_incl.cpp similarity index 100% rename from test/compile_test/interpolators_vector_barycentric_rational_incl_test.cpp rename to test/compile_test/test_interpolators_vector_barycentric_rational_incl.cpp diff --git a/test/compile_test/interpolators_whittaker_shannon_incl_test.cpp b/test/compile_test/test_interpolators_whittaker_shannon_incl.cpp similarity index 100% rename from test/compile_test/interpolators_whittaker_shannon_incl_test.cpp rename to test/compile_test/test_interpolators_whittaker_shannon_incl.cpp diff --git a/test/compile_test/test_jso_incl.cpp b/test/compile_test/test_jso_incl.cpp new file mode 100644 index 0000000000..db3e8d7540 --- /dev/null +++ b/test/compile_test/test_jso_incl.cpp @@ -0,0 +1,22 @@ +// Copyright Nick Thompson 2024. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](std::vector const & v) { return v[0]*v[0]; }; + boost::math::optimization::jso_parameters> params; + std::mt19937_64 gen(12345); + auto v = boost::math::optimization::jso(func, params, gen); +} diff --git a/test/compile_test/quad_exp_sinh_concept_test.cpp b/test/compile_test/test_quad_exp_sinh_concept.cpp similarity index 100% rename from test/compile_test/quad_exp_sinh_concept_test.cpp rename to test/compile_test/test_quad_exp_sinh_concept.cpp diff --git a/test/compile_test/test_quad_exp_sinh_incl.cpp b/test/compile_test/test_quad_exp_sinh_incl.cpp new file mode 100644 index 0000000000..35ee100c61 --- /dev/null +++ b/test/compile_test/test_quad_exp_sinh_incl.cpp @@ -0,0 +1,21 @@ +// Copyright Nick Thompson 2017. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + boost::math::quadrature::exp_sinh integrator; + check_result(integrator.integrate(func)); +} diff --git a/test/compile_test/test_quad_gauss_hermite_incl.cpp b/test/compile_test/test_quad_gauss_hermite_incl.cpp new file mode 100644 index 0000000000..c3f80f4d76 --- /dev/null +++ b/test/compile_test/test_quad_gauss_hermite_incl.cpp @@ -0,0 +1,21 @@ +// Copyright Nick Thompson 2026. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto integrand = [](double x) { return x; }; + check_result(boost::math::quadrature::gauss_hermite::integrate(integrand)); + check_result(boost::math::quadrature::gauss_hermite::integrate(integrand)); +} diff --git a/test/compile_test/test_quad_gauss_incl.cpp b/test/compile_test/test_quad_gauss_incl.cpp new file mode 100644 index 0000000000..29de11cb59 --- /dev/null +++ b/test/compile_test/test_quad_gauss_incl.cpp @@ -0,0 +1,21 @@ +// Copyright Matt Borland 2021. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + boost::math::quadrature::gauss integrator; + check_result(integrator.integrate(func)); +} diff --git a/test/compile_test/test_quad_gauss_kronrod_incl.cpp b/test/compile_test/test_quad_gauss_kronrod_incl.cpp new file mode 100644 index 0000000000..2871ab0f55 --- /dev/null +++ b/test/compile_test/test_quad_gauss_kronrod_incl.cpp @@ -0,0 +1,21 @@ +// Copyright Matt Borland 2021. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + boost::math::quadrature::gauss integrator; + check_result(integrator.integrate(func)); +} diff --git a/test/compile_test/test_quad_naive_monte_carlo_concept.cpp b/test/compile_test/test_quad_naive_monte_carlo_concept.cpp new file mode 100644 index 0000000000..7b5d9fc8da --- /dev/null +++ b/test/compile_test/test_quad_naive_monte_carlo_concept.cpp @@ -0,0 +1,33 @@ +/* + * Copyright Nick Thompson, 2017 + * 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) + */ + +#if !defined(BOOST_MATH_STANDALONE) && (!defined(_MSC_VER) || (_MSC_VER >= 1900)) + +#include +#include + +using boost::math::concepts::std_real_concept; +using boost::math::quadrature::naive_monte_carlo; + +void compile_and_link_test() +{ + auto g = [&](std::vector const &) + { + return 1.873; + }; + std::vector> bounds{{0, 1}, {0, 1}, {0, 1}}; + naive_monte_carlo mc(g, bounds, 1.0); + + auto task = mc.integrate(); + static_cast(task.get()); +} + +#else +void compile_and_link_test() +{ +} +#endif diff --git a/test/compile_test/quad_naive_monte_carlo_incl_test.cpp b/test/compile_test/test_quad_naive_monte_carlo_incl.cpp similarity index 100% rename from test/compile_test/quad_naive_monte_carlo_incl_test.cpp rename to test/compile_test/test_quad_naive_monte_carlo_incl.cpp diff --git a/test/compile_test/test_quad_ooura_fourier_integrals_incl.cpp b/test/compile_test/test_quad_ooura_fourier_integrals_incl.cpp new file mode 100644 index 0000000000..4e7c56223f --- /dev/null +++ b/test/compile_test/test_quad_ooura_fourier_integrals_incl.cpp @@ -0,0 +1,25 @@ +// Copyright Matt Borland 2021. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +#ifndef _MSC_VER +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + boost::math::quadrature::ooura_fourier_sin sin_integrator; + boost::math::quadrature::ooura_fourier_cos cos_integrator; + check_result>(sin_integrator.integrate(func, 1.0)); + check_result>(cos_integrator.integrate(func, 1.0)); +} +#endif diff --git a/test/compile_test/quad_sinh_sinh_concept_test.cpp b/test/compile_test/test_quad_sinh_sinh_concept.cpp similarity index 100% rename from test/compile_test/quad_sinh_sinh_concept_test.cpp rename to test/compile_test/test_quad_sinh_sinh_concept.cpp diff --git a/test/compile_test/test_quad_sinh_sinh_incl.cpp b/test/compile_test/test_quad_sinh_sinh_incl.cpp new file mode 100644 index 0000000000..01336b46ab --- /dev/null +++ b/test/compile_test/test_quad_sinh_sinh_incl.cpp @@ -0,0 +1,21 @@ +// Copyright Nick Thompson 2017. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + boost::math::quadrature::sinh_sinh integrator; + check_result(integrator.integrate(func)); +} diff --git a/test/compile_test/quad_tanh_sinh_concept_test.cpp b/test/compile_test/test_quad_tanh_sinh_concept.cpp similarity index 100% rename from test/compile_test/quad_tanh_sinh_concept_test.cpp rename to test/compile_test/test_quad_tanh_sinh_concept.cpp diff --git a/test/compile_test/test_quad_tanh_sinh_incl.cpp b/test/compile_test/test_quad_tanh_sinh_incl.cpp new file mode 100644 index 0000000000..136256f56e --- /dev/null +++ b/test/compile_test/test_quad_tanh_sinh_incl.cpp @@ -0,0 +1,21 @@ +// Copyright Nick Thompson 2017. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + boost::math::quadrature::tanh_sinh integrator; + check_result(integrator.integrate(func)); +} diff --git a/test/compile_test/quad_trapezoidal_concept_test.cpp b/test/compile_test/test_quad_trapezoidal_concept.cpp similarity index 100% rename from test/compile_test/quad_trapezoidal_concept_test.cpp rename to test/compile_test/test_quad_trapezoidal_concept.cpp diff --git a/test/compile_test/quad_trapezoidal_incl_test.cpp b/test/compile_test/test_quad_trapezoidal_incl.cpp similarity index 100% rename from test/compile_test/quad_trapezoidal_incl_test.cpp rename to test/compile_test/test_quad_trapezoidal_incl.cpp diff --git a/test/compile_test/test_quad_wavelet_transforms_incl.cpp b/test/compile_test/test_quad_wavelet_transforms_incl.cpp new file mode 100644 index 0000000000..284b69fc94 --- /dev/null +++ b/test/compile_test/test_quad_wavelet_transforms_incl.cpp @@ -0,0 +1,22 @@ +// Copyright Matt Borland 2021. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + auto psi = boost::math::daubechies_wavelet(); + auto Wf = boost::math::quadrature::daubechies_wavelet_transform(func, psi); + check_result(Wf(0.0, 0.0)); +} diff --git a/test/compile_test/test_random_search_incl.cpp b/test/compile_test/test_random_search_incl.cpp new file mode 100644 index 0000000000..cafc5715a8 --- /dev/null +++ b/test/compile_test/test_random_search_incl.cpp @@ -0,0 +1,22 @@ +// Copyright Nick Thompson 2024. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](std::vector const & v) { return v[0]*v[0]; }; + boost::math::optimization::random_search_parameters> params; + std::mt19937_64 gen(12345); + auto v = boost::math::optimization::random_search(func, params, gen); +} diff --git a/test/compile_test/sf_0f1_incl_test.cpp b/test/compile_test/test_sf_0f1_incl.cpp similarity index 100% rename from test/compile_test/sf_0f1_incl_test.cpp rename to test/compile_test/test_sf_0f1_incl.cpp diff --git a/test/compile_test/sf_1f0_incl_test.cpp b/test/compile_test/test_sf_1f0_incl.cpp similarity index 100% rename from test/compile_test/sf_1f0_incl_test.cpp rename to test/compile_test/test_sf_1f0_incl.cpp diff --git a/test/compile_test/sf_1f1_incl_test.cpp b/test/compile_test/test_sf_1f1_incl.cpp similarity index 100% rename from test/compile_test/sf_1f1_incl_test.cpp rename to test/compile_test/test_sf_1f1_incl.cpp diff --git a/test/compile_test/sf_2f0_incl_test.cpp b/test/compile_test/test_sf_2f0_incl.cpp similarity index 100% rename from test/compile_test/sf_2f0_incl_test.cpp rename to test/compile_test/test_sf_2f0_incl.cpp diff --git a/test/compile_test/sf_acosh_incl_test.cpp b/test/compile_test/test_sf_acosh_incl.cpp similarity index 100% rename from test/compile_test/sf_acosh_incl_test.cpp rename to test/compile_test/test_sf_acosh_incl.cpp diff --git a/test/compile_test/sf_airy_incl_test.cpp b/test/compile_test/test_sf_airy_incl.cpp similarity index 100% rename from test/compile_test/sf_airy_incl_test.cpp rename to test/compile_test/test_sf_airy_incl.cpp diff --git a/test/compile_test/sf_asinh_incl_test.cpp b/test/compile_test/test_sf_asinh_incl.cpp similarity index 100% rename from test/compile_test/sf_asinh_incl_test.cpp rename to test/compile_test/test_sf_asinh_incl.cpp diff --git a/test/compile_test/sf_atanh_incl_test.cpp b/test/compile_test/test_sf_atanh_incl.cpp similarity index 100% rename from test/compile_test/sf_atanh_incl_test.cpp rename to test/compile_test/test_sf_atanh_incl.cpp diff --git a/test/compile_test/sf_bernoulli_incl_test.cpp b/test/compile_test/test_sf_bernoulli_incl.cpp similarity index 100% rename from test/compile_test/sf_bernoulli_incl_test.cpp rename to test/compile_test/test_sf_bernoulli_incl.cpp diff --git a/test/compile_test/sf_bessel_deriv_incl_test.cpp b/test/compile_test/test_sf_bessel_deriv_incl.cpp similarity index 100% rename from test/compile_test/sf_bessel_deriv_incl_test.cpp rename to test/compile_test/test_sf_bessel_deriv_incl.cpp diff --git a/test/compile_test/sf_bessel_incl_test.cpp b/test/compile_test/test_sf_bessel_incl.cpp similarity index 100% rename from test/compile_test/sf_bessel_incl_test.cpp rename to test/compile_test/test_sf_bessel_incl.cpp diff --git a/test/compile_test/test_sf_beta_incl.cpp b/test/compile_test/test_sf_beta_incl.cpp new file mode 100644 index 0000000000..980aa7293c --- /dev/null +++ b/test/compile_test/test_sf_beta_incl.cpp @@ -0,0 +1,60 @@ +// Copyright John Maddock 2006. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + check_result(boost::math::beta(f, f)); + check_result(boost::math::beta(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::beta(l, l)); +#endif + + check_result(boost::math::lbeta(f, f)); + check_result(boost::math::lbeta(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::lbeta(l, l)); +#endif + + check_result(boost::math::ibeta(f, f, f)); + check_result(boost::math::ibeta(d, d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::ibeta(l, l, l)); +#endif + + check_result(boost::math::libeta(f, f, f)); + check_result(boost::math::libeta(d, d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::libeta(l, l, l)); +#endif + + check_result(boost::math::libetac(f, f, f)); + check_result(boost::math::libetac(d, d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::libetac(l, l, l)); +#endif + + check_result(boost::math::ibeta_inv(f, f, f)); + check_result(boost::math::ibeta_inv(d, d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::ibeta_inv(l, l, l)); +#endif + + check_result(boost::math::ibeta_inva(f, f, f)); + check_result(boost::math::ibeta_inva(d, d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::ibeta_inva(l, l, l)); +#endif +} + diff --git a/test/compile_test/sf_binomial_incl_test.cpp b/test/compile_test/test_sf_binomial_incl.cpp similarity index 100% rename from test/compile_test/sf_binomial_incl_test.cpp rename to test/compile_test/test_sf_binomial_incl.cpp diff --git a/test/compile_test/sf_cbrt_incl_test.cpp b/test/compile_test/test_sf_cbrt_incl.cpp similarity index 100% rename from test/compile_test/sf_cbrt_incl_test.cpp rename to test/compile_test/test_sf_cbrt_incl.cpp diff --git a/test/compile_test/sf_chebyshev_incl_test.cpp b/test/compile_test/test_sf_chebyshev_incl.cpp similarity index 100% rename from test/compile_test/sf_chebyshev_incl_test.cpp rename to test/compile_test/test_sf_chebyshev_incl.cpp diff --git a/test/compile_test/test_sf_chebyshev_transform_incl.cpp b/test/compile_test/test_sf_chebyshev_transform_incl.cpp new file mode 100644 index 0000000000..34df9799a2 --- /dev/null +++ b/test/compile_test/test_sf_chebyshev_transform_incl.cpp @@ -0,0 +1,21 @@ +// Copyright Matt Borland 2021 +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + boost::math::chebyshev_transform test(func, 0.0, 1.0); + check_result(test(1.0)); +} diff --git a/test/compile_test/sf_cos_pi_incl_test.cpp b/test/compile_test/test_sf_cos_pi_incl.cpp similarity index 100% rename from test/compile_test/sf_cos_pi_incl_test.cpp rename to test/compile_test/test_sf_cos_pi_incl.cpp diff --git a/test/compile_test/sf_daubechies_scaling_incl_test.cpp b/test/compile_test/test_sf_daubechies_scaling_incl.cpp similarity index 100% rename from test/compile_test/sf_daubechies_scaling_incl_test.cpp rename to test/compile_test/test_sf_daubechies_scaling_incl.cpp diff --git a/test/compile_test/sf_digamma_incl_test.cpp b/test/compile_test/test_sf_digamma_incl.cpp similarity index 100% rename from test/compile_test/sf_digamma_incl_test.cpp rename to test/compile_test/test_sf_digamma_incl.cpp diff --git a/test/compile_test/sf_ellint_1_incl_test.cpp b/test/compile_test/test_sf_ellint_1_incl.cpp similarity index 100% rename from test/compile_test/sf_ellint_1_incl_test.cpp rename to test/compile_test/test_sf_ellint_1_incl.cpp diff --git a/test/compile_test/sf_ellint_2_incl_test.cpp b/test/compile_test/test_sf_ellint_2_incl.cpp similarity index 100% rename from test/compile_test/sf_ellint_2_incl_test.cpp rename to test/compile_test/test_sf_ellint_2_incl.cpp diff --git a/test/compile_test/sf_ellint_3_incl_test.cpp b/test/compile_test/test_sf_ellint_3_incl.cpp similarity index 100% rename from test/compile_test/sf_ellint_3_incl_test.cpp rename to test/compile_test/test_sf_ellint_3_incl.cpp diff --git a/test/compile_test/sf_ellint_d_incl_test.cpp b/test/compile_test/test_sf_ellint_d_incl.cpp similarity index 100% rename from test/compile_test/sf_ellint_d_incl_test.cpp rename to test/compile_test/test_sf_ellint_d_incl.cpp diff --git a/test/compile_test/sf_ellint_rc_incl_test.cpp b/test/compile_test/test_sf_ellint_rc_incl.cpp similarity index 100% rename from test/compile_test/sf_ellint_rc_incl_test.cpp rename to test/compile_test/test_sf_ellint_rc_incl.cpp diff --git a/test/compile_test/sf_ellint_rd_incl_test.cpp b/test/compile_test/test_sf_ellint_rd_incl.cpp similarity index 100% rename from test/compile_test/sf_ellint_rd_incl_test.cpp rename to test/compile_test/test_sf_ellint_rd_incl.cpp diff --git a/test/compile_test/sf_ellint_rf_incl_test.cpp b/test/compile_test/test_sf_ellint_rf_incl.cpp similarity index 100% rename from test/compile_test/sf_ellint_rf_incl_test.cpp rename to test/compile_test/test_sf_ellint_rf_incl.cpp diff --git a/test/compile_test/sf_ellint_rg_incl_test.cpp b/test/compile_test/test_sf_ellint_rg_incl.cpp similarity index 100% rename from test/compile_test/sf_ellint_rg_incl_test.cpp rename to test/compile_test/test_sf_ellint_rg_incl.cpp diff --git a/test/compile_test/sf_ellint_rj_incl_test.cpp b/test/compile_test/test_sf_ellint_rj_incl.cpp similarity index 100% rename from test/compile_test/sf_ellint_rj_incl_test.cpp rename to test/compile_test/test_sf_ellint_rj_incl.cpp diff --git a/test/compile_test/sf_erf_incl_test.cpp b/test/compile_test/test_sf_erf_incl.cpp similarity index 100% rename from test/compile_test/sf_erf_incl_test.cpp rename to test/compile_test/test_sf_erf_incl.cpp diff --git a/test/compile_test/sf_expint_incl_test.cpp b/test/compile_test/test_sf_expint_incl.cpp similarity index 100% rename from test/compile_test/sf_expint_incl_test.cpp rename to test/compile_test/test_sf_expint_incl.cpp diff --git a/test/compile_test/sf_expm1_incl_test.cpp b/test/compile_test/test_sf_expm1_incl.cpp similarity index 100% rename from test/compile_test/sf_expm1_incl_test.cpp rename to test/compile_test/test_sf_expm1_incl.cpp diff --git a/test/compile_test/sf_factorials_incl_test.cpp b/test/compile_test/test_sf_factorials_incl.cpp similarity index 100% rename from test/compile_test/sf_factorials_incl_test.cpp rename to test/compile_test/test_sf_factorials_incl.cpp diff --git a/test/compile_test/sf_fibonacci_incl_test.cpp b/test/compile_test/test_sf_fibonacci_incl.cpp similarity index 100% rename from test/compile_test/sf_fibonacci_incl_test.cpp rename to test/compile_test/test_sf_fibonacci_incl.cpp diff --git a/test/compile_test/sf_fpclassify_incl_test.cpp b/test/compile_test/test_sf_fpclassify_incl.cpp similarity index 100% rename from test/compile_test/sf_fpclassify_incl_test.cpp rename to test/compile_test/test_sf_fpclassify_incl.cpp diff --git a/test/compile_test/test_sf_gamma_incl.cpp b/test/compile_test/test_sf_gamma_incl.cpp new file mode 100644 index 0000000000..12245b5e58 --- /dev/null +++ b/test/compile_test/test_sf_gamma_incl.cpp @@ -0,0 +1,107 @@ +// Copyright John Maddock 2006. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + check_result(boost::math::tgamma(f)); + check_result(boost::math::tgamma(d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::tgamma(l)); +#endif + + check_result(boost::math::lgamma(f)); + check_result(boost::math::lgamma(d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::lgamma(l)); +#endif + + check_result(boost::math::gamma_p(f, f)); + check_result(boost::math::gamma_p(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::gamma_p(l, l)); +#endif + + check_result(boost::math::gamma_q(f, f)); + check_result(boost::math::gamma_q(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::gamma_q(l, l)); +#endif + + check_result(boost::math::lgamma_q(f, f)); + check_result(boost::math::lgamma_q(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::lgamma_q(l, l)); +#endif + +check_result(boost::math::lgamma_p(f, f)); +check_result(boost::math::lgamma_p(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::lgamma_p(l, l)); +#endif + + check_result(boost::math::ligamma(f, f)); + check_result(boost::math::ligamma(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::ligamma(l, l)); +#endif + + check_result(boost::math::ligamma_lower(f, f)); + check_result(boost::math::ligamma_lower(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::ligamma_lower(l, l)); +#endif + + check_result(boost::math::gamma_p_inv(f, f)); + check_result(boost::math::gamma_p_inv(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::gamma_p_inv(l, l)); +#endif + + check_result(boost::math::gamma_q_inv(f, f)); + check_result(boost::math::gamma_q_inv(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::gamma_q_inv(l, l)); +#endif + + check_result(boost::math::gamma_p_inva(f, f)); + check_result(boost::math::gamma_p_inva(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::gamma_p_inva(l, l)); +#endif + + check_result(boost::math::gamma_q_inva(f, f)); + check_result(boost::math::gamma_q_inva(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::gamma_q_inva(l, l)); +#endif + + check_result(boost::math::gamma_p_derivative(f, f)); + check_result(boost::math::gamma_p_derivative(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::gamma_p_derivative(l, l)); +#endif + + check_result(boost::math::tgamma_ratio(f, f)); + check_result(boost::math::tgamma_ratio(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::tgamma_ratio(l, l)); +#endif + + check_result(boost::math::tgamma_delta_ratio(f, f)); + check_result(boost::math::tgamma_delta_ratio(d, d)); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + check_result(boost::math::tgamma_delta_ratio(l, l)); +#endif +} diff --git a/test/compile_test/sf_gegenbauer_incl_test.cpp b/test/compile_test/test_sf_gegenbauer_incl.cpp similarity index 100% rename from test/compile_test/sf_gegenbauer_incl_test.cpp rename to test/compile_test/test_sf_gegenbauer_incl.cpp diff --git a/test/compile_test/sf_hankel_incl_test.cpp b/test/compile_test/test_sf_hankel_incl.cpp similarity index 100% rename from test/compile_test/sf_hankel_incl_test.cpp rename to test/compile_test/test_sf_hankel_incl.cpp diff --git a/test/compile_test/sf_hermite_incl_test.cpp b/test/compile_test/test_sf_hermite_incl.cpp similarity index 100% rename from test/compile_test/sf_hermite_incl_test.cpp rename to test/compile_test/test_sf_hermite_incl.cpp diff --git a/test/compile_test/sf_heuman_lambda_incl_test.cpp b/test/compile_test/test_sf_heuman_lambda_incl.cpp similarity index 100% rename from test/compile_test/sf_heuman_lambda_incl_test.cpp rename to test/compile_test/test_sf_heuman_lambda_incl.cpp diff --git a/test/compile_test/sf_hypot_incl_test.cpp b/test/compile_test/test_sf_hypot_incl.cpp similarity index 100% rename from test/compile_test/sf_hypot_incl_test.cpp rename to test/compile_test/test_sf_hypot_incl.cpp diff --git a/test/compile_test/sf_jacobi_incl_test.cpp b/test/compile_test/test_sf_jacobi_incl.cpp similarity index 100% rename from test/compile_test/sf_jacobi_incl_test.cpp rename to test/compile_test/test_sf_jacobi_incl.cpp diff --git a/test/compile_test/sf_jacobi_theta_incl_test.cpp b/test/compile_test/test_sf_jacobi_theta_incl.cpp similarity index 100% rename from test/compile_test/sf_jacobi_theta_incl_test.cpp rename to test/compile_test/test_sf_jacobi_theta_incl.cpp diff --git a/test/compile_test/sf_jacobi_zeta_incl_test.cpp b/test/compile_test/test_sf_jacobi_zeta_incl.cpp similarity index 100% rename from test/compile_test/sf_jacobi_zeta_incl_test.cpp rename to test/compile_test/test_sf_jacobi_zeta_incl.cpp diff --git a/test/compile_test/sf_laguerre_incl_test.cpp b/test/compile_test/test_sf_laguerre_incl.cpp similarity index 100% rename from test/compile_test/sf_laguerre_incl_test.cpp rename to test/compile_test/test_sf_laguerre_incl.cpp diff --git a/test/compile_test/sf_lambert_w_incl_test.cpp b/test/compile_test/test_sf_lambert_w_incl.cpp similarity index 100% rename from test/compile_test/sf_lambert_w_incl_test.cpp rename to test/compile_test/test_sf_lambert_w_incl.cpp diff --git a/test/compile_test/sf_lanczos_incl_test.cpp b/test/compile_test/test_sf_lanczos_incl.cpp similarity index 100% rename from test/compile_test/sf_lanczos_incl_test.cpp rename to test/compile_test/test_sf_lanczos_incl.cpp diff --git a/test/compile_test/sf_legendre_incl_test.cpp b/test/compile_test/test_sf_legendre_incl.cpp similarity index 100% rename from test/compile_test/sf_legendre_incl_test.cpp rename to test/compile_test/test_sf_legendre_incl.cpp diff --git a/test/compile_test/sf_legendre_stieltjes_concept_test.cpp b/test/compile_test/test_sf_legendre_stieltjes_concept.cpp similarity index 100% rename from test/compile_test/sf_legendre_stieltjes_concept_test.cpp rename to test/compile_test/test_sf_legendre_stieltjes_concept.cpp diff --git a/test/compile_test/sf_legendre_stieltjes_incl_test.cpp b/test/compile_test/test_sf_legendre_stieltjes_incl.cpp similarity index 100% rename from test/compile_test/sf_legendre_stieltjes_incl_test.cpp rename to test/compile_test/test_sf_legendre_stieltjes_incl.cpp diff --git a/test/compile_test/sf_log1p_incl_test.cpp b/test/compile_test/test_sf_log1p_incl.cpp similarity index 100% rename from test/compile_test/sf_log1p_incl_test.cpp rename to test/compile_test/test_sf_log1p_incl.cpp diff --git a/test/compile_test/sf_logaddexp_incl_test.cpp b/test/compile_test/test_sf_logaddexp_incl.cpp similarity index 100% rename from test/compile_test/sf_logaddexp_incl_test.cpp rename to test/compile_test/test_sf_logaddexp_incl.cpp diff --git a/test/compile_test/sf_logsumexp_incl_test.cpp b/test/compile_test/test_sf_logsumexp_incl.cpp similarity index 100% rename from test/compile_test/sf_logsumexp_incl_test.cpp rename to test/compile_test/test_sf_logsumexp_incl.cpp diff --git a/test/compile_test/sf_math_fwd_incl_test.cpp b/test/compile_test/test_sf_math_fwd_incl.cpp similarity index 100% rename from test/compile_test/sf_math_fwd_incl_test.cpp rename to test/compile_test/test_sf_math_fwd_incl.cpp diff --git a/test/compile_test/sf_modf_incl_test.cpp b/test/compile_test/test_sf_modf_incl.cpp similarity index 100% rename from test/compile_test/sf_modf_incl_test.cpp rename to test/compile_test/test_sf_modf_incl.cpp diff --git a/test/compile_test/sf_next_incl_test.cpp b/test/compile_test/test_sf_next_incl.cpp similarity index 100% rename from test/compile_test/sf_next_incl_test.cpp rename to test/compile_test/test_sf_next_incl.cpp diff --git a/test/compile_test/sf_nonfinite_num_facets_incl_test.cpp b/test/compile_test/test_sf_nonfinite_num_facets_incl.cpp similarity index 100% rename from test/compile_test/sf_nonfinite_num_facets_incl_test.cpp rename to test/compile_test/test_sf_nonfinite_num_facets_incl.cpp diff --git a/test/compile_test/sf_owens_t_incl_test.cpp b/test/compile_test/test_sf_owens_t_incl.cpp similarity index 100% rename from test/compile_test/sf_owens_t_incl_test.cpp rename to test/compile_test/test_sf_owens_t_incl.cpp diff --git a/test/compile_test/sf_pfq_incl_test.cpp b/test/compile_test/test_sf_pfq_incl.cpp similarity index 100% rename from test/compile_test/sf_pfq_incl_test.cpp rename to test/compile_test/test_sf_pfq_incl.cpp diff --git a/test/compile_test/sf_polygamma_incl_test.cpp b/test/compile_test/test_sf_polygamma_incl.cpp similarity index 100% rename from test/compile_test/sf_polygamma_incl_test.cpp rename to test/compile_test/test_sf_polygamma_incl.cpp diff --git a/test/compile_test/sf_powm1_incl_test.cpp b/test/compile_test/test_sf_powm1_incl.cpp similarity index 100% rename from test/compile_test/sf_powm1_incl_test.cpp rename to test/compile_test/test_sf_powm1_incl.cpp diff --git a/test/compile_test/sf_prime_incl_test.cpp b/test/compile_test/test_sf_prime_incl.cpp similarity index 100% rename from test/compile_test/sf_prime_incl_test.cpp rename to test/compile_test/test_sf_prime_incl.cpp diff --git a/test/compile_test/test_sf_prime_sieve_incl.cpp b/test/compile_test/test_sf_prime_sieve_incl.cpp new file mode 100644 index 0000000000..6bff78a191 --- /dev/null +++ b/test/compile_test/test_sf_prime_sieve_incl.cpp @@ -0,0 +1,20 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Basic sanity check that the header +// #includes all the files that it needs to. + +#include +#include + +void compile_and_link_test() +{ + std::vector v; + boost::math::prime_sieve(100u, v); + boost::math::prime_range(10u, 100u, v); + (void)boost::math::prime_count(100u); + (void)boost::math::prime_count(10u, 100u); + (void)boost::math::prime_count(boost::math::execution::cuda, 100u); +} diff --git a/test/compile_test/sf_relative_distance_incl_test.cpp b/test/compile_test/test_sf_relative_distance_incl.cpp similarity index 100% rename from test/compile_test/sf_relative_distance_incl_test.cpp rename to test/compile_test/test_sf_relative_distance_incl.cpp diff --git a/test/compile_test/sf_round_incl_test.cpp b/test/compile_test/test_sf_round_incl.cpp similarity index 100% rename from test/compile_test/sf_round_incl_test.cpp rename to test/compile_test/test_sf_round_incl.cpp diff --git a/test/compile_test/sf_rsqrt_incl_test.cpp b/test/compile_test/test_sf_rsqrt_incl.cpp similarity index 100% rename from test/compile_test/sf_rsqrt_incl_test.cpp rename to test/compile_test/test_sf_rsqrt_incl.cpp diff --git a/test/compile_test/sf_sign_incl_test.cpp b/test/compile_test/test_sf_sign_incl.cpp similarity index 100% rename from test/compile_test/sf_sign_incl_test.cpp rename to test/compile_test/test_sf_sign_incl.cpp diff --git a/test/compile_test/sf_sin_pi_incl_test.cpp b/test/compile_test/test_sf_sin_pi_incl.cpp similarity index 100% rename from test/compile_test/sf_sin_pi_incl_test.cpp rename to test/compile_test/test_sf_sin_pi_incl.cpp diff --git a/test/compile_test/sf_sinc_incl_test.cpp b/test/compile_test/test_sf_sinc_incl.cpp similarity index 100% rename from test/compile_test/sf_sinc_incl_test.cpp rename to test/compile_test/test_sf_sinc_incl.cpp diff --git a/test/compile_test/sf_sinhc_incl_test.cpp b/test/compile_test/test_sf_sinhc_incl.cpp similarity index 100% rename from test/compile_test/sf_sinhc_incl_test.cpp rename to test/compile_test/test_sf_sinhc_incl.cpp diff --git a/test/compile_test/sf_sph_harm_incl_test.cpp b/test/compile_test/test_sf_sph_harm_incl.cpp similarity index 100% rename from test/compile_test/sf_sph_harm_incl_test.cpp rename to test/compile_test/test_sf_sph_harm_incl.cpp diff --git a/test/compile_test/sf_sqrt1pm1_incl_test.cpp b/test/compile_test/test_sf_sqrt1pm1_incl.cpp similarity index 100% rename from test/compile_test/sf_sqrt1pm1_incl_test.cpp rename to test/compile_test/test_sf_sqrt1pm1_incl.cpp diff --git a/test/compile_test/sf_trigamma_incl_test.cpp b/test/compile_test/test_sf_trigamma_incl.cpp similarity index 100% rename from test/compile_test/sf_trigamma_incl_test.cpp rename to test/compile_test/test_sf_trigamma_incl.cpp diff --git a/test/compile_test/sf_trunc_incl_test.cpp b/test/compile_test/test_sf_trunc_incl.cpp similarity index 100% rename from test/compile_test/sf_trunc_incl_test.cpp rename to test/compile_test/test_sf_trunc_incl.cpp diff --git a/test/compile_test/sf_ulp_incl_test.cpp b/test/compile_test/test_sf_ulp_incl.cpp similarity index 100% rename from test/compile_test/sf_ulp_incl_test.cpp rename to test/compile_test/test_sf_ulp_incl.cpp diff --git a/test/compile_test/sf_zeta_incl_test.cpp b/test/compile_test/test_sf_zeta_incl.cpp similarity index 100% rename from test/compile_test/sf_zeta_incl_test.cpp rename to test/compile_test/test_sf_zeta_incl.cpp diff --git a/test/compile_test/stats_anderson_darling_inc_test.cpp b/test/compile_test/test_stats_anderson_darling_inc.cpp similarity index 100% rename from test/compile_test/stats_anderson_darling_inc_test.cpp rename to test/compile_test/test_stats_anderson_darling_inc.cpp diff --git a/test/compile_test/stats_bivariate_inc_test.cpp b/test/compile_test/test_stats_bivariate_inc.cpp similarity index 100% rename from test/compile_test/stats_bivariate_inc_test.cpp rename to test/compile_test/test_stats_bivariate_inc.cpp diff --git a/test/compile_test/stats_chaterjee_incl_test.cpp b/test/compile_test/test_stats_chaterjee_incl.cpp similarity index 100% rename from test/compile_test/stats_chaterjee_incl_test.cpp rename to test/compile_test/test_stats_chaterjee_incl.cpp diff --git a/test/compile_test/stats_linear_regression_inc_test.cpp b/test/compile_test/test_stats_linear_regression_inc.cpp similarity index 100% rename from test/compile_test/stats_linear_regression_inc_test.cpp rename to test/compile_test/test_stats_linear_regression_inc.cpp diff --git a/test/compile_test/stats_ljung_box_inc_test.cpp b/test/compile_test/test_stats_ljung_box_inc.cpp similarity index 100% rename from test/compile_test/stats_ljung_box_inc_test.cpp rename to test/compile_test/test_stats_ljung_box_inc.cpp diff --git a/test/compile_test/stats_runs_test_inc_test.cpp b/test/compile_test/test_stats_runs_test_inc.cpp similarity index 100% rename from test/compile_test/stats_runs_test_inc_test.cpp rename to test/compile_test/test_stats_runs_test_inc.cpp diff --git a/test/compile_test/stats_signal_statistics_inc_test.cpp b/test/compile_test/test_stats_signal_statistics_inc.cpp similarity index 100% rename from test/compile_test/stats_signal_statistics_inc_test.cpp rename to test/compile_test/test_stats_signal_statistics_inc.cpp diff --git a/test/compile_test/stats_t_test_inc_test.cpp b/test/compile_test/test_stats_t_test_inc.cpp similarity index 100% rename from test/compile_test/stats_t_test_inc_test.cpp rename to test/compile_test/test_stats_t_test_inc.cpp diff --git a/test/compile_test/stats_univariate_inc_test.cpp b/test/compile_test/test_stats_univariate_inc.cpp similarity index 100% rename from test/compile_test/stats_univariate_inc_test.cpp rename to test/compile_test/test_stats_univariate_inc.cpp diff --git a/test/compile_test/stats_z_test_inc_test.cpp b/test/compile_test/test_stats_z_test_inc.cpp similarity index 100% rename from test/compile_test/stats_z_test_inc_test.cpp rename to test/compile_test/test_stats_z_test_inc.cpp diff --git a/test/compile_test/tools_agm_incl_test.cpp b/test/compile_test/test_tools_agm_incl.cpp similarity index 100% rename from test/compile_test/tools_agm_incl_test.cpp rename to test/compile_test/test_tools_agm_incl.cpp diff --git a/test/compile_test/tools_assert_incl_test.cpp b/test/compile_test/test_tools_assert_incl.cpp similarity index 100% rename from test/compile_test/tools_assert_incl_test.cpp rename to test/compile_test/test_tools_assert_incl.cpp diff --git a/test/compile_test/tools_atomic_incl_test.cpp b/test/compile_test/test_tools_atomic_incl.cpp similarity index 100% rename from test/compile_test/tools_atomic_incl_test.cpp rename to test/compile_test/test_tools_atomic_incl.cpp diff --git a/test/compile_test/tools_big_constant_incl_test.cpp b/test/compile_test/test_tools_big_constant_incl.cpp similarity index 100% rename from test/compile_test/tools_big_constant_incl_test.cpp rename to test/compile_test/test_tools_big_constant_incl.cpp diff --git a/test/compile_test/tools_centered_continued_fraction_incl_test.cpp b/test/compile_test/test_tools_centered_continued_fraction_incl.cpp similarity index 100% rename from test/compile_test/tools_centered_continued_fraction_incl_test.cpp rename to test/compile_test/test_tools_centered_continued_fraction_incl.cpp diff --git a/test/compile_test/tools_cohen_acceleration_incl_test.cpp b/test/compile_test/test_tools_cohen_acceleration_incl.cpp similarity index 100% rename from test/compile_test/tools_cohen_acceleration_incl_test.cpp rename to test/compile_test/test_tools_cohen_acceleration_incl.cpp diff --git a/test/compile_test/tools_color_maps_incl_test.cpp b/test/compile_test/test_tools_color_maps_incl.cpp similarity index 100% rename from test/compile_test/tools_color_maps_incl_test.cpp rename to test/compile_test/test_tools_color_maps_incl.cpp diff --git a/test/compile_test/tools_complex_incl_test.cpp b/test/compile_test/test_tools_complex_incl.cpp similarity index 100% rename from test/compile_test/tools_complex_incl_test.cpp rename to test/compile_test/test_tools_complex_incl.cpp diff --git a/test/compile_test/tools_condition_numbers_incl_test.cpp b/test/compile_test/test_tools_condition_numbers_incl.cpp similarity index 100% rename from test/compile_test/tools_condition_numbers_incl_test.cpp rename to test/compile_test/test_tools_condition_numbers_incl.cpp diff --git a/test/compile_test/tools_config_inc_test.cpp b/test/compile_test/test_tools_config_inc.cpp similarity index 100% rename from test/compile_test/tools_config_inc_test.cpp rename to test/compile_test/test_tools_config_inc.cpp diff --git a/test/compile_test/tools_convert_from_string_incl_test.cpp b/test/compile_test/test_tools_convert_from_string_incl.cpp similarity index 100% rename from test/compile_test/tools_convert_from_string_incl_test.cpp rename to test/compile_test/test_tools_convert_from_string_incl.cpp diff --git a/test/compile_test/tools_cxx03_warn_incl_test.cpp b/test/compile_test/test_tools_cxx03_warn_incl.cpp similarity index 100% rename from test/compile_test/tools_cxx03_warn_incl_test.cpp rename to test/compile_test/test_tools_cxx03_warn_incl.cpp diff --git a/test/compile_test/tools_engel_expansion_incl_test.cpp b/test/compile_test/test_tools_engel_expansion_incl.cpp similarity index 100% rename from test/compile_test/tools_engel_expansion_incl_test.cpp rename to test/compile_test/test_tools_engel_expansion_incl.cpp diff --git a/test/compile_test/test_tools_fft_incl.cpp b/test/compile_test/test_tools_fft_incl.cpp new file mode 100644 index 0000000000..6389c0cd75 --- /dev/null +++ b/test/compile_test/test_tools_fft_incl.cpp @@ -0,0 +1,29 @@ +// Copyright Nick Thompson 2026. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + boost::math::tools::fft> fd(12); + std::vector> v(12); + fd.transform(v); + fd.inverse_transform(v); + check_result(v[0].real()); + + boost::math::tools::real_fft> rf(8); + std::vector x(8); + std::vector> X(5); + rf.transform(x, X); + check_result(X[0].real()); +} diff --git a/test/compile_test/tools_fraction_inc_test.cpp b/test/compile_test/test_tools_fraction_inc.cpp similarity index 100% rename from test/compile_test/tools_fraction_inc_test.cpp rename to test/compile_test/test_tools_fraction_inc.cpp diff --git a/test/compile_test/tools_header_deprecated_incl_test.cpp b/test/compile_test/test_tools_header_deprecated_incl.cpp similarity index 100% rename from test/compile_test/tools_header_deprecated_incl_test.cpp rename to test/compile_test/test_tools_header_deprecated_incl.cpp diff --git a/test/compile_test/tools_is_detected_incl_test.cpp b/test/compile_test/test_tools_is_detected_incl.cpp similarity index 100% rename from test/compile_test/tools_is_detected_incl_test.cpp rename to test/compile_test/test_tools_is_detected_incl.cpp diff --git a/test/compile_test/tools_luroth_expansion_incl_test.cpp b/test/compile_test/test_tools_luroth_expansion_incl.cpp similarity index 100% rename from test/compile_test/tools_luroth_expansion_incl_test.cpp rename to test/compile_test/test_tools_luroth_expansion_incl.cpp diff --git a/test/compile_test/tools_minima_inc_test.cpp b/test/compile_test/test_tools_minima_inc.cpp similarity index 100% rename from test/compile_test/tools_minima_inc_test.cpp rename to test/compile_test/test_tools_minima_inc.cpp diff --git a/test/compile_test/tools_mp_incl_test.cpp b/test/compile_test/test_tools_mp_incl.cpp similarity index 100% rename from test/compile_test/tools_mp_incl_test.cpp rename to test/compile_test/test_tools_mp_incl.cpp diff --git a/test/compile_test/tools_norms_incl_test.cpp b/test/compile_test/test_tools_norms_incl.cpp similarity index 100% rename from test/compile_test/tools_norms_incl_test.cpp rename to test/compile_test/test_tools_norms_incl.cpp diff --git a/test/compile_test/tools_polynomial_gcd_incl_test.cpp b/test/compile_test/test_tools_polynomial_gcd_incl.cpp similarity index 100% rename from test/compile_test/tools_polynomial_gcd_incl_test.cpp rename to test/compile_test/test_tools_polynomial_gcd_incl.cpp diff --git a/test/compile_test/tools_polynomial_inc_test.cpp b/test/compile_test/test_tools_polynomial_inc.cpp similarity index 100% rename from test/compile_test/tools_polynomial_inc_test.cpp rename to test/compile_test/test_tools_polynomial_inc.cpp diff --git a/test/compile_test/tools_precision_inc_test.cpp b/test/compile_test/test_tools_precision_inc.cpp similarity index 100% rename from test/compile_test/tools_precision_inc_test.cpp rename to test/compile_test/test_tools_precision_inc.cpp diff --git a/test/compile_test/tools_promotion_incl_test.cpp b/test/compile_test/test_tools_promotion_incl.cpp similarity index 100% rename from test/compile_test/tools_promotion_incl_test.cpp rename to test/compile_test/test_tools_promotion_incl.cpp diff --git a/test/compile_test/tools_random_vector_incl_test.cpp b/test/compile_test/test_tools_random_vector_incl.cpp similarity index 100% rename from test/compile_test/tools_random_vector_incl_test.cpp rename to test/compile_test/test_tools_random_vector_incl.cpp diff --git a/test/compile_test/tools_rational_inc_test.cpp b/test/compile_test/test_tools_rational_inc.cpp similarity index 100% rename from test/compile_test/tools_rational_inc_test.cpp rename to test/compile_test/test_tools_rational_inc.cpp diff --git a/test/compile_test/tools_real_cast_inc_test.cpp b/test/compile_test/test_tools_real_cast_inc.cpp similarity index 100% rename from test/compile_test/tools_real_cast_inc_test.cpp rename to test/compile_test/test_tools_real_cast_inc.cpp diff --git a/test/compile_test/tools_remez_inc_test.cpp b/test/compile_test/test_tools_remez_inc.cpp similarity index 100% rename from test/compile_test/tools_remez_inc_test.cpp rename to test/compile_test/test_tools_remez_inc.cpp diff --git a/test/compile_test/test_tools_roots_inc.cpp b/test/compile_test/test_tools_roots_inc.cpp new file mode 100644 index 0000000000..6475459fd8 --- /dev/null +++ b/test/compile_test/test_tools_roots_inc.cpp @@ -0,0 +1,40 @@ +// Copyright John Maddock 2006. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +#include +#include // for std::pair, our headers don't know what tuple type is to be used, we have to supply it. +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +inline void check_result_imp(std::pair, std::pair){} +inline void check_result_imp(std::pair, std::pair){} +inline void check_result_imp(std::pair, std::pair){} + +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + typedef double (*F)(double); + typedef std::pair (*F2)(double); + typedef boost::math::tuple (*F3)(double); + typedef boost::math::tools::eps_tolerance Tol; + Tol tol(u); + std::uintmax_t max_iter = 0; + F func = 0; + F2 f2 = 0; + F3 f3 = 0; + + check_result >(boost::math::tools::bisect(func, d, d, tol, max_iter)); + check_result >(boost::math::tools::bisect(func, d, d, tol)); + check_result(boost::math::tools::newton_raphson_iterate(f2, d, d, d, i, max_iter)); + check_result(boost::math::tools::halley_iterate(f3, d, d, d, i, max_iter)); + check_result(boost::math::tools::schroder_iterate(f3, d, d, d, i, max_iter)); +} + diff --git a/test/compile_test/tools_series_inc_test.cpp b/test/compile_test/test_tools_series_inc.cpp similarity index 100% rename from test/compile_test/tools_series_inc_test.cpp rename to test/compile_test/test_tools_series_inc.cpp diff --git a/test/compile_test/tools_simple_continued_fraction_incl_test.cpp b/test/compile_test/test_tools_simple_continued_fraction_incl.cpp similarity index 100% rename from test/compile_test/tools_simple_continued_fraction_incl_test.cpp rename to test/compile_test/test_tools_simple_continued_fraction_incl.cpp diff --git a/test/compile_test/tools_solve_inc_test.cpp b/test/compile_test/test_tools_solve_inc.cpp similarity index 100% rename from test/compile_test/tools_solve_inc_test.cpp rename to test/compile_test/test_tools_solve_inc.cpp diff --git a/test/compile_test/tools_stats_inc_test.cpp b/test/compile_test/test_tools_stats_inc.cpp similarity index 100% rename from test/compile_test/tools_stats_inc_test.cpp rename to test/compile_test/test_tools_stats_inc.cpp diff --git a/test/compile_test/tools_test_data_inc_test.cpp b/test/compile_test/test_tools_test_data_inc.cpp similarity index 100% rename from test/compile_test/tools_test_data_inc_test.cpp rename to test/compile_test/test_tools_test_data_inc.cpp diff --git a/test/compile_test/tools_test_inc_test.cpp b/test/compile_test/test_tools_test_inc.cpp similarity index 100% rename from test/compile_test/tools_test_inc_test.cpp rename to test/compile_test/test_tools_test_inc.cpp diff --git a/test/compile_test/tools_test_value_incl_test.cpp b/test/compile_test/test_tools_test_value_incl.cpp similarity index 100% rename from test/compile_test/tools_test_value_incl_test.cpp rename to test/compile_test/test_tools_test_value_incl.cpp diff --git a/test/compile_test/tools_throw_exception_incl_test.cpp b/test/compile_test/test_tools_throw_exception_incl.cpp similarity index 100% rename from test/compile_test/tools_throw_exception_incl_test.cpp rename to test/compile_test/test_tools_throw_exception_incl.cpp diff --git a/test/compile_test/tools_toms748_inc_test.cpp b/test/compile_test/test_tools_toms748_inc.cpp similarity index 100% rename from test/compile_test/tools_toms748_inc_test.cpp rename to test/compile_test/test_tools_toms748_inc.cpp diff --git a/test/compile_test/tools_traits_incl_test.cpp b/test/compile_test/test_tools_traits_incl.cpp similarity index 100% rename from test/compile_test/tools_traits_incl_test.cpp rename to test/compile_test/test_tools_traits_incl.cpp diff --git a/test/compile_test/tools_tuple_inc_test.cpp b/test/compile_test/test_tools_tuple_inc.cpp similarity index 100% rename from test/compile_test/tools_tuple_inc_test.cpp rename to test/compile_test/test_tools_tuple_inc.cpp diff --git a/test/compile_test/test_tools_ulps_heatmap_incl.cpp b/test/compile_test/test_tools_ulps_heatmap_incl.cpp new file mode 100644 index 0000000000..12e3721355 --- /dev/null +++ b/test/compile_test/test_tools_ulps_heatmap_incl.cpp @@ -0,0 +1,22 @@ +// Copyright Nick Thompson 2026. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x, double y) { return x*y; }; + auto g = [](float x, float y) { return x*y; }; + boost::math::tools::ulps_heatmap test(func, 1.0f, 2.0f, 1.0f, 2.0f, 4, 4); + auto dummy = test.add_fn(g, "g").summary(); +} diff --git a/test/compile_test/test_tools_ulps_plot_incl.cpp b/test/compile_test/test_tools_ulps_plot_incl.cpp new file mode 100644 index 0000000000..8fea134130 --- /dev/null +++ b/test/compile_test/test_tools_ulps_plot_incl.cpp @@ -0,0 +1,21 @@ +// Copyright Matt Borland 2021. +// 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) +// +// Basic sanity check that header +// #includes all the files that it needs to. +// +#include +// +// Note this header includes no other headers, this is +// important if this test is to be meaningful: +// +#include "test_compile_result.hpp" + +void compile_and_link_test() +{ + auto func = [](double x) { return x; }; + boost::math::tools::ulps_plot test(func, 1.0f, 2.0f); + auto dummy = test.width(1); +} diff --git a/test/compile_test/tools_workaround_incl_test.cpp b/test/compile_test/test_tools_workaround_incl.cpp similarity index 100% rename from test/compile_test/tools_workaround_incl_test.cpp rename to test/compile_test/test_tools_workaround_incl.cpp diff --git a/test/compile_test/tr1_incl_test.cpp b/test/compile_test/test_tr1_incl.cpp similarity index 100% rename from test/compile_test/tr1_incl_test.cpp rename to test/compile_test/test_tr1_incl.cpp diff --git a/test/compile_test/tools_roots_inc_test.cpp b/test/compile_test/tools_roots_inc_test.cpp deleted file mode 100644 index f4d02bda1e..0000000000 --- a/test/compile_test/tools_roots_inc_test.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright John Maddock 2006. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -#include -#include // for std::pair, our headers don't know what tuple type is to be used, we have to supply it. -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -inline void check_result_imp(std::pair, std::pair){} -inline void check_result_imp(std::pair, std::pair){} -inline void check_result_imp(std::pair, std::pair){} - -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - typedef double (*F)(double); - typedef std::pair (*F2)(double); - typedef boost::math::tuple (*F3)(double); - typedef boost::math::tools::eps_tolerance Tol; - Tol tol(u); - std::uintmax_t max_iter = 0; - F f = 0; - F2 f2 = 0; - F3 f3 = 0; - - check_result >(boost::math::tools::bisect(f, d, d, tol, max_iter)); - check_result >(boost::math::tools::bisect(f, d, d, tol)); - check_result(boost::math::tools::newton_raphson_iterate(f2, d, d, d, i, max_iter)); - check_result(boost::math::tools::halley_iterate(f3, d, d, d, i, max_iter)); - check_result(boost::math::tools::schroder_iterate(f3, d, d, d, i, max_iter)); -} - diff --git a/test/compile_test/tools_ulps_plot_incl_test.cpp b/test/compile_test/tools_ulps_plot_incl_test.cpp deleted file mode 100644 index e30406f0ef..0000000000 --- a/test/compile_test/tools_ulps_plot_incl_test.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright Matt Borland 2021. -// 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) -// -// Basic sanity check that header -// #includes all the files that it needs to. -// -#include -// -// Note this header includes no other headers, this is -// important if this test is to be meaningful: -// -#include "test_compile_result.hpp" - -void compile_and_link_test() -{ - auto f = [](double x) { return x; }; - boost::math::tools::ulps_plot test(f, 1.0f, 2.0f); - auto dummy = test.width(1); -} diff --git a/test/cubic_roots_test.cpp b/test/cubic_roots_test.cpp deleted file mode 100644 index b6ee44af2a..0000000000 --- a/test/cubic_roots_test.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright Nick Thompson, 2021 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - -using boost::math::tools::cubic_root_condition_number; -using boost::math::tools::cubic_root_residual; -using boost::math::tools::cubic_roots; -using std::cbrt; -using std::abs; - -template void test_zero_coefficients() { - Real a = 0; - Real b = 0; - Real c = 0; - Real d = 0; - auto roots = cubic_roots(a, b, c, d); - CHECK_EQUAL(roots[0], Real(0)); - CHECK_EQUAL(roots[1], Real(0)); - CHECK_EQUAL(roots[2], Real(0)); - - a = 1; - roots = cubic_roots(a, b, c, d); - CHECK_EQUAL(roots[0], Real(0)); - CHECK_EQUAL(roots[1], Real(0)); - CHECK_EQUAL(roots[2], Real(0)); - - a = 1; - d = 1; - // x^3 + 1 = 0: - roots = cubic_roots(a, b, c, d); - CHECK_EQUAL(roots[0], Real(-1)); - CHECK_NAN(roots[1]); - CHECK_NAN(roots[2]); - d = -1; - // x^3 - 1 = 0: - roots = cubic_roots(a, b, c, d); - CHECK_EQUAL(roots[0], Real(1)); - CHECK_NAN(roots[1]); - CHECK_NAN(roots[2]); - - d = -2; - // x^3 - 2 = 0 - roots = cubic_roots(a, b, c, d); - CHECK_ULP_CLOSE(roots[0], cbrt(Real(2)), 2); - CHECK_NAN(roots[1]); - CHECK_NAN(roots[2]); - - d = -8; - roots = cubic_roots(a, b, c, d); - CHECK_EQUAL(roots[0], Real(2)); - CHECK_NAN(roots[1]); - CHECK_NAN(roots[2]); - - // (x-1)(x-2)(x-3) = x^3 - 6x^2 + 11x - 6 - roots = cubic_roots(Real(1), Real(-6), Real(11), Real(-6)); - CHECK_ULP_CLOSE(roots[0], Real(1), 2); - CHECK_ULP_CLOSE(roots[1], Real(2), 2); - CHECK_ULP_CLOSE(roots[2], Real(3), 2); - - // Double root: - // (x+1)^2(x-2) = x^3 - 3x - 2: - // Note: This test is unstable wrt to perturbations! - roots = cubic_roots(Real(1), Real(0), Real(-3), Real(-2)); - CHECK_ULP_CLOSE(Real(-1), roots[0], 2); - CHECK_ULP_CLOSE(Real(-1), roots[1], 2); - CHECK_ULP_CLOSE(Real(2), roots[2], 2); - - std::uniform_real_distribution dis(-2, 2); - std::mt19937 gen(12345); - // Expected roots - std::array r; - int trials = 10; - for (int i = 0; i < trials; ++i) { - // Mathematica: - // Expand[(x - r0)*(x - r1)*(x - r2)] - // - r0 r1 r2 + (r0 r1 + r0 r2 + r1 r2) x - // - (r0 + r1 + r2) x^2 + x^3 - for (auto &root : r) { - root = static_cast(dis(gen)); - } - std::sort(r.begin(), r.end()); - Real a = 1; - Real b = -(r[0] + r[1] + r[2]); - Real c = r[0] * r[1] + r[0] * r[2] + r[1] * r[2]; - Real d = -r[0] * r[1] * r[2]; - - auto roots = cubic_roots(a, b, c, d); - // I could check the condition number here, but this is fine right? - if (!CHECK_ULP_CLOSE(r[0], roots[0], (std::numeric_limits::digits > 100 ? 120 : 60))) { - std::cerr << " Polynomial x^3 + " << b << "x^2 + " << c << "x + " - << d << " has roots {"; - std::cerr << r[0] << ", " << r[1] << ", " << r[2] - << "}, but the computed roots are {"; - std::cerr << roots[0] << ", " << roots[1] << ", " << roots[2] - << "}\n"; - } - CHECK_ULP_CLOSE(r[1], roots[1], 80); - CHECK_ULP_CLOSE(r[2], roots[2], (std::numeric_limits::digits > 100 ? 120 : 80)); - for (auto root : roots) { - auto res = cubic_root_residual(a, b, c, d, root); - CHECK_LE(abs(res[0]), res[1]); - } - } -} - -void test_ill_conditioned() { - // An ill-conditioned root reported by SATovstun: - // "Exact" roots produced with a high-precision calculation on Wolfram Alpha: - // NSolve[x^3 + 10000*x^2 + 200*x +1==0,x] - std::array expected_roots{-9999.97999997, - -0.010010015026300100757327057, - -0.009990014973799899662674923}; - auto roots = cubic_roots(1, 10000, 200, 1); - CHECK_ABSOLUTE_ERROR(expected_roots[0], roots[0], - std::numeric_limits::epsilon()); - - if (!(boost::math::isnan)(roots[1])) - { - // This test is so ill-conditioned, that we can't always get here. - // Test case is Clang C++20 mode on MacOS Arm. Best guess is that - // fma is behaving differently there... - CHECK_ABSOLUTE_ERROR(expected_roots[1], roots[1], 1.01e-5); - CHECK_ABSOLUTE_ERROR(expected_roots[2], roots[2], 1.01e-5); - double cond = - cubic_root_condition_number(1, 10000, 200, 1, roots[1]); - double r1 = expected_roots[1]; - // The factor of 10 is a fudge factor to make the test pass. - // Nonetheless, it does show this is basically correct: - CHECK_LE(abs(r1 - roots[1]) / abs(r1), - 10 * std::numeric_limits::epsilon() * cond); - - cond = cubic_root_condition_number(1, 10000, 200, 1, roots[2]); - double r2 = expected_roots[2]; - // The factor of 10 is a fudge factor to make the test pass. - // Nonetheless, it does show this is basically correct: - CHECK_LE(abs(r2 - roots[2]) / abs(r2), - 10 * std::numeric_limits::epsilon() * cond); - } - else - { - CHECK_NAN(roots[2]); - } - // See https://github.com/boostorg/math/issues/757: - // The polynomial is ((x+1)^2+1)*(x+1) which has roots -1, and two complex - // roots: - roots = cubic_roots(1, 3, 4, 2); - CHECK_ULP_CLOSE(roots[0], -1.0, 3); - CHECK_NAN(roots[1]); - CHECK_NAN(roots[2]); - return; -} - -int main() { - test_zero_coefficients(); - test_zero_coefficients(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_zero_coefficients(); -#endif - test_ill_conditioned(); -#ifdef BOOST_HAS_FLOAT128 - // For some reason, the quadmath is way less accurate than the - // float/double/long double: - // test_zero_coefficients(); -#endif - - return boost::math::test::report_errors(); -} diff --git a/test/cuda_jamfile b/test/cuda_jamfile index f2f2c9aa82..146c282d9e 100644 --- a/test/cuda_jamfile +++ b/test/cuda_jamfile @@ -261,10 +261,16 @@ run test_airy_bi_prime_float.cu ; run test_beta_double.cu ; run test_beta_float.cu ; +run test_lbeta_double.cu ; +run test_lbeta_float.cu ; run test_betac_double.cu ; run test_betac_float.cu ; run test_ibeta_double.cu ; run test_ibeta_float.cu ; +run test_libeta_double.cu ; +run test_libeta_float.cu ; +run test_libetac_double.cu ; +run test_libetac_float.cu ; run test_ibeta_derivative_double.cu ; run test_ibeta_derivative_float.cu ; run test_ibeta_inv_double.cu ; @@ -379,6 +385,10 @@ run test_lgamma_q_double.cu ; run test_lgamma_q_float.cu ; run test_lgamma_p_double.cu ; run test_lgamma_p_float.cu ; +run test_ligamma_double.cu ; +run test_ligamma_float.cu ; +run test_ligamma_lower_double.cu ; +run test_ligamma_lower_float.cu ; run test_log1p_double.cu ; run test_log1p_float.cu ; @@ -397,3 +407,8 @@ run test_trigamma_float.cu ; run test_trunc_double.cu ; run test_trunc_float.cu ; +run test_pow1p_double.cu ; +run test_pow1p_float.cu ; + +# Prime sieve (owns its own kernels) +run test_prime_sieve_cuda.cu ; diff --git a/test/daubechies_scaling_test.cpp b/test/daubechies_scaling_test.cpp deleted file mode 100644 index e2dda727e4..0000000000 --- a/test/daubechies_scaling_test.cpp +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright Nick Thompson, John Maddock 2020 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - -using std::sqrt; -// Mallat, Theorem 7.4, characterization number 3: -// A conjugate mirror filter has p vanishing moments iff h^{(n)}(pi) = 0 for 0 <= n < p. -template -void test_daubechies_filters() -{ - using std::sqrt; - - std::cout << "Testing Daubechies filters with " << p << " vanishing moments on type " << boost::core::demangle(typeid(Real).name()) << "\n"; - Real tol = 3*std::numeric_limits::epsilon(); - using boost::math::filters::daubechies_scaling_filter; - using boost::math::filters::daubechies_wavelet_filter; - - auto h = daubechies_scaling_filter(); - auto g = daubechies_wavelet_filter(); - - auto inner = std::inner_product(h.begin(), h.end(), g.begin(), Real(0)); - CHECK_MOLLIFIED_CLOSE(0, inner, tol); - - // This is implied by Fourier transform of the two-scale dilatation equation; - // If this doesn't hold, the infinite product for m_0 diverges. - Real H0 = 0; - for (size_t j = 0; j < h.size(); ++j) - { - H0 += h[j]; - } - CHECK_MOLLIFIED_CLOSE(sqrt(static_cast(2)), H0, tol); - - // This is implied if we choose the scaling function to be an orthonormal basis of V0. - Real scaling = 0; - for (size_t j = 0; j < h.size(); ++j) { - scaling += h[j]*h[j]; - } - CHECK_MOLLIFIED_CLOSE(1, scaling, tol); - - using std::pow; - // Daubechies wavelet of order p has p vanishing moments. - // Unfortunately, the condition number of the sum is infinite. - // Hence we must scale the tolerance by the summation condition number to ensure that we don't get spurious test failures. - for (size_t k = 1; k < p && k < 9; ++k) - { - Real hk = 0; - Real abs_hk = 0; - for (size_t n = 0; n < h.size(); ++n) - { - Real t = static_cast(pow(n, k)*h[n]); - if (n & 1) - { - hk -= t; - } - else - { - hk += t; - } - abs_hk += abs(t); - } - // Multiply the tolerance by the condition number: - Real cond = abs(hk) > 0 ? abs_hk/abs(hk) : 1/std::numeric_limits::epsilon(); - if (!CHECK_MOLLIFIED_CLOSE(0, hk, 2*cond*tol)) - { - std::cerr << " The " << k << "th moment of the p = " << p << " filter did not vanish\n"; - std::cerr << " Condition number = " << abs_hk/abs(hk) << "\n"; - } - } - - // For the scaling function to be orthonormal to its integer translates, - // sum h_k h_{k-2l} = \delta_{0,l}. - // See Theoretical Numerical Analysis, Atkinson, Exercise 4.5.2. - // This is the last condition we could test to ensure that the filters are correct, - // but I'm not gonna bother because it's painful! -} - -// Test that the filters agree with Daubechies, Ten Lenctures on Wavelets, Table 6.1: -void test_agreement_with_ten_lectures() -{ - std::cout << "Testing agreement with Ten Lectures\n"; - std::array h2 = {0.4829629131445341, 0.8365163037378077, 0.2241438680420134, -0.1294095225512603}; - auto h2_ = boost::math::filters::daubechies_scaling_filter(); - for (size_t i = 0; i < h2.size(); ++i) - { - CHECK_ULP_CLOSE(h2[i], h2_[i], 3); - } - - std::array h3 = {0.3326705529500825, 0.8068915093110924, 0.4598775021184914, -0.1350110200102546, -0.0854412738820267, 0.0352262918857095}; - auto h3_ = boost::math::filters::daubechies_scaling_filter(); - for (size_t i = 0; i < h3.size(); ++i) - { - CHECK_ULP_CLOSE(h3[i], h3_[i], 5); - } - - std::array h4 = {0.2303778133088964, 0.7148465705529154, 0.6308807679298587, -0.0279837694168599, -0.1870348117190931, 0.0308413818355607, 0.0328830116668852 , -0.010597401785069}; - auto h4_ = boost::math::filters::daubechies_scaling_filter(); - for (size_t i = 0; i < h4.size(); ++i) - { - if(!CHECK_ULP_CLOSE(h4[i], h4_[i], 18)) - { - std::cerr << " Index " << i << " incorrect.\n"; - } - } - -} - -template -void test_filter_ulp_distance() -{ - std::cout << "Testing filters ULP distance between types " - << boost::core::demangle(typeid(Real1).name()) << "and" - << boost::core::demangle(typeid(Real2).name()) << "\n"; - using boost::math::filters::daubechies_scaling_filter; - auto h1 = daubechies_scaling_filter(); - auto h2 = daubechies_scaling_filter(); - - for (size_t i = 0; i < h1.size(); ++i) - { - if(!CHECK_ULP_CLOSE(h1[i], h2[i], 0)) - { - std::cerr << " Index " << i << " at order " << p << " failed tolerance check\n"; - } - } -} - - -template -void test_integer_grid() -{ - std::cout << "Testing integer grid with " << p << " vanishing moments and " << order << " derivative on type " << boost::core::demangle(typeid(Real).name()) << "\n"; - using boost::math::detail::daubechies_scaling_integer_grid; - using boost::math::tools::summation_condition_number; - Real unit_roundoff = std::numeric_limits::epsilon()/2; - auto grid = daubechies_scaling_integer_grid(); - - if constexpr (order == 0) - { - auto cond = summation_condition_number(0); - for (auto & x : grid) - { - cond += x; - } - CHECK_MOLLIFIED_CLOSE(1, cond.sum(), 6*cond.l1_norm()*unit_roundoff); - } - - if constexpr (order == 1) - { - auto cond = summation_condition_number(0); - for (size_t i = 0; i < grid.size(); ++i) { - cond += i*grid[i]; - } - CHECK_MOLLIFIED_CLOSE(Real(-1), cond.sum(), 2*cond.l1_norm()*unit_roundoff); - - // Differentiate \sum_{k} \phi(x-k) = 1 to get this: - cond = summation_condition_number(0); - for (size_t i = 0; i < grid.size(); ++i) { - cond += grid[i]; - } - CHECK_MOLLIFIED_CLOSE(Real(0), cond.sum(), 2*cond.l1_norm()*unit_roundoff); - } - - if constexpr (order == 2) - { - auto cond = summation_condition_number(0); - for (size_t i = 0; i < grid.size(); ++i) - { - cond += i*i*grid[i]; - } - CHECK_MOLLIFIED_CLOSE(Real(2), cond.sum(), 2*cond.l1_norm()*unit_roundoff); - - // Differentiate \sum_{k} \phi(x-k) = 1 to get this: - cond = summation_condition_number(0); - for (size_t i = 0; i < grid.size(); ++i) - { - cond += grid[i]; - } - CHECK_MOLLIFIED_CLOSE(Real(0), cond.sum(), 2*cond.l1_norm()*unit_roundoff); - } - - if constexpr (order == 3) - { - auto cond = summation_condition_number(0); - for (size_t i = 0; i < grid.size(); ++i) - { - cond += i*i*i*grid[i]; - } - CHECK_MOLLIFIED_CLOSE(Real(-6), cond.sum(), 2*cond.l1_norm()*unit_roundoff); - - // Differentiate \sum_{k} \phi(x-k) = 1 to get this: - cond = summation_condition_number(0); - for (size_t i = 0; i < grid.size(); ++i) - { - cond += grid[i]; - } - CHECK_MOLLIFIED_CLOSE(Real(0), cond.sum(), 2*cond.l1_norm()*unit_roundoff); - } - - if constexpr (order == 4) - { - auto cond = summation_condition_number(0); - for (size_t i = 0; i < grid.size(); ++i) - { - cond += i*i*i*i*grid[i]; - } - CHECK_MOLLIFIED_CLOSE(24, cond.sum(), 2*cond.l1_norm()*unit_roundoff); - - // Differentiate \sum_{k} \phi(x-k) = 1 to get this: - cond = summation_condition_number(0); - for (size_t i = 0; i < grid.size(); ++i) - { - cond += grid[i]; - } - CHECK_MOLLIFIED_CLOSE(Real(0), cond.sum(), 2*cond.l1_norm()*unit_roundoff); - } -} - -template -void test_dyadic_grid() -{ - std::cout << "Testing dyadic grid on type " << boost::core::demangle(typeid(Real).name()) << "\n"; - auto f = [&](auto i) - { - auto phijk = boost::math::daubechies_scaling_dyadic_grid(0); - auto phik = boost::math::detail::daubechies_scaling_integer_grid(); - BOOST_ASSERT(phik.size() == phijk.size()); - - for (size_t k = 0; k < phik.size(); ++k) - { - CHECK_ULP_CLOSE(phik[k], phijk[k], 0); - } - - for (uint64_t j = 1; j < 10; ++j) - { - phijk = boost::math::daubechies_scaling_dyadic_grid(j); - phik = boost::math::detail::daubechies_scaling_integer_grid(); - for (uint64_t l = 0; l < static_cast(phik.size()); ++l) - { - CHECK_ULP_CLOSE(phik[l], phijk[l*(uint64_t(1)<(0); - for (uint64_t l = 0; l < static_cast(phik.size()); ++l) - { - uint64_t idx = l*(uint64_t(1)<::epsilon()); - } - } - if constexpr (std::numeric_limits::digits < 30) - { - CHECK_THROW((boost::math::daubechies_scaling_dyadic_grid)(24), std::logic_error); - } - }; - - boost::hana::for_each(std::make_index_sequence<18>(), f); -} - - -// Taken from Lin, 2005, doi:10.1016/j.amc.2004.12.038, -// "Direct algorithm for computation of derivatives of the Daubechies basis functions" -void test_first_derivative() -{ -#if LDBL_MANT_DIG > 64 - // Limited precision test data means we can't test long double here... -#else - auto phi1_3 = boost::math::detail::daubechies_scaling_integer_grid(); - std::array lin_3{0.0L, 1.638452340884085725014976113635604107L, -2.23275819046313739501774225255380757L, - 0.550159358274017614990556164200803310L, 0.044146491305034055012209974717400368L, 0.0L}; - for (size_t i = 0; i < lin_3.size(); ++i) - { - if(!CHECK_ULP_CLOSE(lin_3[i], phi1_3[i], 0)) - { - std::cerr << " Index " << i << " is incorrect\n"; - } - } - - auto phi1_4 = boost::math::detail::daubechies_scaling_integer_grid(); - std::array lin_4 = {0.0L, 1.776072007522184640093776071522502761L, -2.785349397229543142492784905731245880L, 1.192452536632278174347632339082851360L, - -0.131374515184672958793518896272545740L, -0.053571028220239235953599959390993709L,0.001770396479992522798495350789431024L, 0.0L}; - - for (size_t i = 0; i < lin_4.size(); ++i) - { - if(!CHECK_ULP_CLOSE(lin_4[i], phi1_4[i], 0)) - { - std::cerr << " Index " << i << " is incorrect\n"; - } - } - - std::array lin_5 = {0.0L, 1.558326313047001366564379221011472479L, -2.436012783189551921436895932290077033L, 1.235905129801454293947038906779457610L, -0.367437713693886635994756136622838186L, - -0.021780351175646546588845564309594589L,0.032347193508143688858158541500450925L,-0.001335619912770701035229330817898250L,-0.000012168384743544313849705250972915L,0.0L}; - auto phi1_5 = boost::math::detail::daubechies_scaling_integer_grid(); - for (size_t i = 0; i < lin_5.size(); ++i) - { - if(!CHECK_ULP_CLOSE(lin_5[i], phi1_5[i], 0)) - { - std::cerr << " Index " << i << " is incorrect\n"; - } - } -#endif -} - -template -void test_quadratures() -{ - std::cout << "Testing " << p << " vanishing moment scaling function quadratures on type " << boost::core::demangle(typeid(Real).name()) << "\n"; - using boost::math::quadrature::trapezoidal; - if constexpr (p == 2) - { - // 2phi is truly bizarre, because two successive trapezoidal estimates are always bitwise equal, - // whereas the third is way different. I don' t think that's a reasonable thing to optimize for, - // so one-off it is. - Real h = Real(1)/Real(256); - auto phi = boost::math::daubechies_scaling(); - std::cout << "Scaling functor size is " << phi.bytes() << " bytes" << std::endl; - Real t = 0; - Real Q = 0; - while (t < 3) { - Q += phi(t); - t += h; - } - Q *= h; - CHECK_ULP_CLOSE(Real(1), Q, 32); - - auto [a, b] = phi.support(); - // Now hit the boundary. Much can go wrong here; this just tests for segfaults: - int samples = 500; - Real xlo = a; - Real xhi = b; - for (int i = 0; i < samples; ++i) - { - CHECK_ULP_CLOSE(Real(0), phi(xlo), 0); - CHECK_ULP_CLOSE(Real(0), phi(xhi), 0); - xlo = std::nextafter(xlo, std::numeric_limits::lowest()); - xhi = std::nextafter(xhi, (std::numeric_limits::max)()); - } - - xlo = a; - xhi = b; - for (int i = 0; i < samples; ++i) { - BOOST_ASSERT(abs(phi(xlo)) <= 5); - BOOST_ASSERT(abs(phi(xhi)) <= 5); - xlo = std::nextafter(xlo, (std::numeric_limits::max)()); - xhi = std::nextafter(xhi, std::numeric_limits::lowest()); - } - - return; - } - else if constexpr (p > 2) - { - auto phi = boost::math::daubechies_scaling(); - std::cout << "Scaling functor size is " << phi.bytes() << " bytes" << std::endl; - - Real tol = std::numeric_limits::epsilon(); - Real error_estimate = std::numeric_limits::quiet_NaN(); - Real L1 = std::numeric_limits::quiet_NaN(); - auto [a, b] = phi.support(); - Real Q = trapezoidal(phi, a, b, tol, 15, &error_estimate, &L1); - if (!CHECK_MOLLIFIED_CLOSE(Real(1), Q, Real(0.0001))) - { - std::cerr << " Quadrature of " << p << " vanishing moment scaling function is not equal 1.\n"; - std::cerr << " Error estimate is " << error_estimate << ", L1 norm is " << L1 << "\n"; - } - - auto phi_sq = [phi](Real x) { Real t = phi(x); return t*t; }; - Q = trapezoidal(phi, a, b, tol, 15, &error_estimate, &L1); - if (!CHECK_MOLLIFIED_CLOSE(Real(1), Q, 20*std::sqrt(std::numeric_limits::epsilon())/(p*p))) - { - std::cerr << " L2 norm of " << p << " vanishing moment scaling function is not equal 1.\n"; - std::cerr << " Error estimate is " << error_estimate << ", L1 norm is " << L1 << "\n"; - } - - std::random_device rd; - Real t = static_cast(rd())/static_cast((rd.max)()); - Real S = phi(t); - Real dS = phi.prime(t); - while (t < b) - { - t += 1; - S += phi(t); - dS += phi.prime(t); - } - - if(!CHECK_ULP_CLOSE(Real(1), S, 64)) - { - std::cerr << " Normalizing sum for " << p << " vanishing moment scaling function is incorrect.\n"; - } - - // The p = 3, 4 convergence rate is very slow, making this produce false positives: - if constexpr(p > 4) - { - if(!CHECK_MOLLIFIED_CLOSE(Real(0), dS, 100*std::sqrt(std::numeric_limits::epsilon()))) - { - std::cerr << " Derivative of normalizing sum for " << p << " vanishing moment scaling function doesn't vanish.\n"; - } - } - - // Test boundary for segfaults: - int samples = 500; - Real xlo = a; - Real xhi = b; - for (int i = 0; i < samples; ++i) - { - CHECK_ULP_CLOSE(Real(0), phi(xlo), 0); - CHECK_ULP_CLOSE(Real(0), phi(xhi), 0); - if constexpr (p > 2) { - BOOST_ASSERT(abs(phi.prime(xlo)) <= 5); - BOOST_ASSERT(abs(phi.prime(xhi)) <= 5); - if constexpr (p > 5) { - BOOST_ASSERT(abs(phi.double_prime(xlo)) <= 5); - BOOST_ASSERT(abs(phi.double_prime(xhi)) <= 5); - } - } - xlo = std::nextafter(xlo, std::numeric_limits::lowest()); - xhi = std::nextafter(xhi, (std::numeric_limits::max)()); - } - - xlo = a; - xhi = b; - for (int i = 0; i < samples; ++i) { - BOOST_ASSERT(abs(phi(xlo)) <= 5); - BOOST_ASSERT(abs(phi(xhi)) <= 5); - xlo = std::nextafter(xlo, (std::numeric_limits::max)()); - xhi = std::nextafter(xhi, std::numeric_limits::lowest()); - } - } -} - -int main() -{ - #ifndef __MINGW32__ - boost::hana::for_each(std::make_index_sequence<18>(), [&](auto i){ - test_quadratures(); - test_quadratures(); - }); - - test_agreement_with_ten_lectures(); - - boost::hana::for_each(std::make_index_sequence<19>(), [&](auto i){ - test_daubechies_filters(); - test_daubechies_filters(); - test_daubechies_filters(); - }); - - test_first_derivative(); - - // All scaling functions have a first derivative. - boost::hana::for_each(std::make_index_sequence<18>(), [&](auto idx){ - test_integer_grid(); - test_integer_grid(); - test_integer_grid(); - test_integer_grid(); - test_integer_grid(); - test_integer_grid(); - #ifdef BOOST_HAS_FLOAT128 - test_integer_grid(); - test_integer_grid(); - #endif - }); - - // 4-tap (2 vanishing moment) scaling function does not have a second derivative; - // all other scaling functions do. - boost::hana::for_each(std::make_index_sequence<17>(), [&](auto idx){ - test_integer_grid(); - test_integer_grid(); - test_integer_grid(); - #ifdef BOOST_HAS_FLOAT128 - test_integer_grid(); - #endif - }); - - // 8-tap filter (4 vanishing moments) is the first to have a third derivative. - boost::hana::for_each(std::make_index_sequence<16>(), [&](auto idx){ - test_integer_grid(); - test_integer_grid(); - test_integer_grid(); - #ifdef BOOST_HAS_FLOAT128 - test_integer_grid(); - #endif - }); - - // 10-tap filter (5 vanishing moments) is the first to have a fourth derivative. - boost::hana::for_each(std::make_index_sequence<15>(), [&](auto idx){ - test_integer_grid(); - test_integer_grid(); - test_integer_grid(); - #ifdef BOOST_HAS_FLOAT128 - test_integer_grid(); - #endif - }); - - test_dyadic_grid(); - test_dyadic_grid(); - test_dyadic_grid(); - #ifdef BOOST_HAS_FLOAT128 - test_dyadic_grid(); - #endif - - - #ifdef BOOST_HAS_FLOAT128 - boost::hana::for_each(std::make_index_sequence<19>(), [&](auto i){ - test_filter_ulp_distance(); - test_filter_ulp_distance(); - test_filter_ulp_distance(); - }); - - boost::hana::for_each(std::make_index_sequence<19>(), [&](auto i){ - test_daubechies_filters(); - }); - #endif - #endif // compiler guard for CI - return boost::math::test::report_errors(); -} diff --git a/test/daubechies_wavelet_test.cpp b/test/daubechies_wavelet_test.cpp deleted file mode 100644 index 376b0fef91..0000000000 --- a/test/daubechies_wavelet_test.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright Nick Thompson, 2020 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - - -using boost::math::constants::pi; -using boost::math::constants::root_two; - -template -void test_exact_value() -{ - // The global phase of the wavelet is not constrained by anything other than convention. - // Make sure that our conventions match the rest of the world: - auto psi = boost::math::daubechies_wavelet(2); - Real computed = psi(1); - Real expected = -1.366025403784439; - CHECK_MOLLIFIED_CLOSE(expected, computed, 0.0001); -} - -template -void test_quadratures() -{ - std::cout << "Testing quadratures of " << p << " vanishing moment Daubechies wavelet on type " << boost::core::demangle(typeid(Real).name()) << "\n"; - using boost::math::quadrature::trapezoidal; - auto psi = boost::math::daubechies_wavelet(); - std::cout << "Wavelet functor size is " << psi.bytes() << " bytes" << std::endl; - - Real tol = std::numeric_limits::epsilon(); - Real error_estimate = std::numeric_limits::quiet_NaN(); - Real L1 = std::numeric_limits::quiet_NaN(); - auto [a, b] = psi.support(); - CHECK_ULP_CLOSE(Real(-p+1), a, 0); - CHECK_ULP_CLOSE(Real(p), b, 0); - // A wavelet is a function of zero average; ensure the quadrature over its support is zero. - Real Q = trapezoidal(psi, a, b, tol, 15, &error_estimate, &L1); - if (!CHECK_MOLLIFIED_CLOSE(Real(0), Q, Real(0.0001))) - { - std::cerr << " Quadrature of " << p << " vanishing moment wavelet does not vanish.\n"; - std::cerr << " Error estimate: " << error_estimate << ", L1 norm: " << L1 << "\n"; - } - auto psi_sq = [psi](Real x) { - Real t = psi(x); - return t*t; - }; - Q = trapezoidal(psi_sq, a, b, tol, 15, &error_estimate, &L1); - Real quad_tol = 2000*std::sqrt(std::numeric_limits::epsilon())/(p*p*p); - if (!CHECK_MOLLIFIED_CLOSE(Real(1), Q, quad_tol)) - { - std::cerr << " L2 norm of " << p << " vanishing moment wavelet does not vanish.\n"; - std::cerr << " Error estimate: " << error_estimate << ", L1 norm: " << L1 << "\n"; - } - // psi is orthogonal to its integer translates: \int \psi(x-k) \psi(x) \, \mathrm{d}x = 0 - // g_n = 1/sqrt(2) (Mallat, 7.55) - - // Now hit the boundary. Much can go wrong here; this just tests for segfaults: - int samples = 500; - Real xlo = a; - Real xhi = b; - for (int i = 0; i < samples; ++i) - { - CHECK_ULP_CLOSE(Real(0), psi(xlo), 0); - CHECK_ULP_CLOSE(Real(0), psi(xhi), 0); - if constexpr (p > 2) - { - CHECK_ULP_CLOSE(Real(0), psi.prime(xlo), 0); - CHECK_ULP_CLOSE(Real(0), psi.prime(xhi), 0); - if constexpr (p >= 6) { - CHECK_ULP_CLOSE(Real(0), psi.double_prime(xlo), 0); - CHECK_ULP_CLOSE(Real(0), psi.double_prime(xhi), 0); - } - } - xlo = std::nextafter(xlo, std::numeric_limits::lowest()); - xhi = std::nextafter(xhi, (std::numeric_limits::max)()); - } - - xlo = a; - xhi = b; - for (int i = 0; i < samples; ++i) { - std::cout << std::setprecision(std::numeric_limits::max_digits10); - BOOST_ASSERT(abs(psi(xlo)) <= 5); - BOOST_ASSERT(abs(psi(xhi)) <= 5); - if constexpr (p > 2) - { - BOOST_ASSERT(abs(psi.prime(xlo)) <= 5); - BOOST_ASSERT(abs(psi.prime(xhi)) <= 5); - if constexpr (p >= 6) - { - BOOST_ASSERT(abs(psi.double_prime(xlo)) <= 5); - BOOST_ASSERT(abs(psi.double_prime(xhi)) <= 5); - } - } - xlo = std::nextafter(xlo, (std::numeric_limits::max)()); - xhi = std::nextafter(xhi, std::numeric_limits::lowest()); - } -} - -int main() -{ - #ifndef __MINGW32__ - try - { - test_exact_value(); - - boost::hana::for_each(std::make_index_sequence<17>(), [&](auto i) { - test_quadratures(); - test_quadratures(); - }); - } - catch (std::bad_alloc) - { - // not much we can do about this, this test uses lots of memory! - } - #endif - return boost::math::test::report_errors(); -} diff --git a/test/differential_evolution_test.cpp b/test/differential_evolution_test.cpp deleted file mode 100644 index fdbb97dfad..0000000000 --- a/test/differential_evolution_test.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright Nick Thompson, 2023 - * 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) - */ - -#include "math_unit_test.hpp" -#include "test_functions_for_optimization.hpp" -#include -#include - -using boost::math::optimization::differential_evolution; -using boost::math::optimization::differential_evolution_parameters; -using boost::math::optimization::validate_differential_evolution_parameters; -using boost::math::optimization::detail::best_indices; -using boost::math::optimization::detail::random_initial_population; -using boost::math::optimization::detail::validate_initial_guess; - -void test_random_initial_population() { - std::array lower_bounds = {-5, -5}; - std::array upper_bounds = {5, 5}; - size_t n = 500; - std::mt19937_64 gen(12345); - auto population = random_initial_population(lower_bounds, upper_bounds, n, gen); - CHECK_EQUAL(population.size(), n); - for (auto const & individual : population) { - validate_initial_guess(individual, lower_bounds, upper_bounds); - } - // Reproducibility: - gen.seed(12345); - auto population2 = random_initial_population(lower_bounds, upper_bounds, n, gen); - for (size_t i = 0; i < n; ++i) { - for (size_t j = 0; j < 2; ++j) { - CHECK_EQUAL(population[i][j], population2[i][j]); - } - } -} -void test_nan_sorting() { - auto nan = std::numeric_limits::quiet_NaN(); - std::vector v{-1.2, nan, -3.5, 2.3, nan, 8.7, -4.2}; - auto indices = best_indices(v); - CHECK_EQUAL(indices[0], size_t(6)); - CHECK_EQUAL(indices[1], size_t(2)); - CHECK_EQUAL(indices[2], size_t(0)); - CHECK_EQUAL(indices[3], size_t(3)); - CHECK_EQUAL(indices[4], size_t(5)); - CHECK_NAN(v[indices[5]]); - CHECK_NAN(v[indices[6]]); -} - -void test_parameter_checks() { - using ArgType = std::array; - auto de_params = differential_evolution_parameters(); - de_params.threads = 0; - bool caught = false; - try { - validate_differential_evolution_parameters(de_params); - } catch(std::exception const &) { - caught = true; - } - CHECK_TRUE(caught); - caught = false; - de_params = differential_evolution_parameters(); - de_params.NP = 1; - try { - validate_differential_evolution_parameters(de_params); - } catch(std::exception const &) { - caught = true; - } - CHECK_TRUE(caught); -} -template void test_ackley() { - std::cout << "Testing differential evolution on the Ackley function . . .\n"; - using ArgType = std::array; - auto de_params = differential_evolution_parameters(); - de_params.lower_bounds = {-5, -5}; - de_params.upper_bounds = {5, 5}; - - std::mt19937_64 gen(12345); - auto local_minima = differential_evolution(ackley, de_params, gen); - CHECK_LE(std::abs(local_minima[0]), 10 * std::numeric_limits::epsilon()); - CHECK_LE(std::abs(local_minima[1]), 10 * std::numeric_limits::epsilon()); - - // Does it work with a lambda? - auto ack = [](std::array const &x) { return ackley(x); }; - local_minima = differential_evolution(ack, de_params, gen); - CHECK_LE(std::abs(local_minima[0]), 10 * std::numeric_limits::epsilon()); - CHECK_LE(std::abs(local_minima[1]), 10 * std::numeric_limits::epsilon()); - - // Test that if an intial guess is the exact solution, the returned solution is the exact solution: - std::array initial_guess{0, 0}; - de_params.initial_guess = &initial_guess; - local_minima = differential_evolution(ack, de_params, gen); - CHECK_EQUAL(local_minima[0], Real(0)); - CHECK_EQUAL(local_minima[1], Real(0)); -} - -template void test_rosenbrock_saddle() { - std::cout << "Testing differential evolution on the Rosenbrock saddle . . .\n"; - using ArgType = std::array; - auto de_params = differential_evolution_parameters(); - de_params.lower_bounds = {0.5, 0.5}; - de_params.upper_bounds = {2.048, 2.048}; - std::mt19937_64 gen(234568); - auto local_minima = differential_evolution(rosenbrock_saddle, de_params, gen); - - CHECK_ABSOLUTE_ERROR(Real(1), local_minima[0], 10 * std::numeric_limits::epsilon()); - CHECK_ABSOLUTE_ERROR(Real(1), local_minima[1], 10 * std::numeric_limits::epsilon()); - - // Does cancellation work? - std::atomic cancel = true; - gen.seed(12345); - local_minima = - differential_evolution(rosenbrock_saddle, de_params, gen, std::numeric_limits::quiet_NaN(), &cancel); - CHECK_GE(std::abs(local_minima[0] - Real(1)), std::sqrt(std::numeric_limits::epsilon())); -} - -template void test_rastrigin() { - std::cout << "Testing differential evolution on the Rastrigin function . . .\n"; - using ArgType = std::vector; - auto de_params = differential_evolution_parameters(); - de_params.lower_bounds.resize(8, static_cast(-5.12)); - de_params.upper_bounds.resize(8, static_cast(5.12)); - std::mt19937_64 gen(34567); - auto local_minima = differential_evolution(rastrigin, de_params, gen); - for (auto x : local_minima) { - CHECK_ABSOLUTE_ERROR(x, Real(0), Real(2e-4)); - } - - // By definition, the value of the function which a target value is provided must be <= target_value. - auto target_value = static_cast(1e-3); - local_minima = differential_evolution(rastrigin, de_params, gen, target_value); - CHECK_LE(rastrigin(local_minima), target_value); -} - -// Tests NaN return types and return type != input type: -void test_sphere() { - std::cout << "Testing differential evolution on the sphere function . . .\n"; - using ArgType = std::vector; - auto de_params = differential_evolution_parameters(); - de_params.lower_bounds.resize(3, -1); - de_params.upper_bounds.resize(3, 1); - de_params.NP *= 10; - de_params.max_generations *= 10; - de_params.crossover_probability = 0.9; - double target_value = 1e-8; - de_params.threads = 1; - std::mt19937_64 gen(56789); - auto local_minima = differential_evolution(sphere, de_params, gen, target_value); - CHECK_LE(sphere(local_minima), target_value); - // Check computational reproducibility: - gen.seed(56789); - auto local_minima_2 = differential_evolution(sphere, de_params, gen, target_value); - for (size_t i = 0; i < local_minima.size(); ++i) { - CHECK_EQUAL(local_minima[i], local_minima_2[i]); - } -} - -template -void test_three_hump_camel() { - std::cout << "Testing differential evolution on the three hump camel . . .\n"; - using ArgType = std::array; - auto de_params = differential_evolution_parameters(); - de_params.lower_bounds[0] = -5.0; - de_params.lower_bounds[1] = -5.0; - de_params.upper_bounds[0] = 5.0; - de_params.upper_bounds[1] = 5.0; - std::mt19937_64 gen(56789); - auto local_minima = differential_evolution(three_hump_camel, de_params, gen); - for (auto x : local_minima) { - CHECK_ABSOLUTE_ERROR(0.0f, x, 2e-4f); - } -} - -template -void test_beale() { - std::cout << "Testing differential evolution on the Beale function . . .\n"; - using ArgType = std::array; - auto de_params = differential_evolution_parameters(); - de_params.lower_bounds[0] = -5.0; - de_params.lower_bounds[1] = -5.0; - de_params.upper_bounds[0]= 5.0; - de_params.upper_bounds[1]= 5.0; - std::mt19937_64 gen(56789); - auto local_minima = differential_evolution(beale, de_params, gen); - CHECK_ABSOLUTE_ERROR(Real(3), local_minima[0], Real(2e-4)); - CHECK_ABSOLUTE_ERROR(Real(1)/Real(2), local_minima[1], Real(2e-4)); -} - -int main() { - -#if defined(__clang__) || defined(_MSC_VER) - test_ackley(); - test_ackley(); - test_rosenbrock_saddle(); - test_rastrigin(); - test_three_hump_camel(); - test_beale(); -#endif - test_sphere(); - test_parameter_checks(); - return boost::math::test::report_errors(); -} diff --git a/test/erf_limits_test.cpp b/test/erf_limits_test.cpp deleted file mode 100644 index cf05bbd7a9..0000000000 --- a/test/erf_limits_test.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// (C) Copyright John Maddock 2021. -// 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) - -// -// This test verifies that the limits we use in the numerical approximations to erf/erc -// are indeed correct. The values tested must of course match the values used in erf.hpp. -// See https://github.com/boostorg/math/issues/710 -// - -#define BOOST_TEST_MODULE erf_limits - -#include -#include -#include - -#include - -BOOST_AUTO_TEST_CASE(limits_53_digits) -{ - double arg = 5.93f; - - double t = (double)boost::math::erf(boost::multiprecision::cpp_bin_float_50(arg)); - BOOST_CHECK_EQUAL(t, 1.0); - - arg = 5.9; - BOOST_CHECK_LT(boost::math::erf(arg), 1.0); - - arg = 28; - t = (double)boost::math::erfc(boost::multiprecision::cpp_bin_float_50(arg)); - BOOST_CHECK_EQUAL(t, 0.0); - - arg = 27.2; - - BOOST_CHECK_GT(boost::math::erfc(arg), 0.0); -} - -BOOST_AUTO_TEST_CASE(limits_64_digits) -{ - float arg = 6.6f; - - boost::multiprecision::cpp_bin_float_double_extended t = (boost::multiprecision::cpp_bin_float_double_extended)boost::math::erf(boost::multiprecision::cpp_bin_float_50(arg)); - BOOST_CHECK_EQUAL(t, 1.0); - -#if (LDBL_MANT_DIG == 64) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) - arg = 6.5; - BOOST_CHECK_LT(boost::math::erf(static_cast(arg)), 1.0L); -#endif - arg = 110; - t = (boost::multiprecision::cpp_bin_float_double_extended)boost::math::erfc(boost::multiprecision::cpp_bin_float_50(arg)); - BOOST_CHECK_EQUAL(t, 0.0); - -#if (LDBL_MANT_DIG == 64) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) - arg = 106.5; - BOOST_CHECK_GT(boost::math::erfc(static_cast(arg)), 0.0L); -#endif -} - -BOOST_AUTO_TEST_CASE(limits_113_digits) -{ - // - // This limit is not actually used in the code, logged here for future reference... - // - float arg = 8.8f; - - boost::multiprecision::cpp_bin_float_quad t = (boost::multiprecision::cpp_bin_float_quad)boost::math::erf(boost::multiprecision::cpp_bin_float_50(arg)); - BOOST_CHECK_EQUAL(t, 1.0); - - arg = 110; - t = (boost::multiprecision::cpp_bin_float_quad)boost::math::erfc(boost::multiprecision::cpp_bin_float_50(arg)); - BOOST_CHECK_EQUAL(t, 0.0); -} diff --git a/test/exp_sinh_quadrature_test.cpp b/test/exp_sinh_quadrature_test.cpp deleted file mode 100644 index deed18c922..0000000000 --- a/test/exp_sinh_quadrature_test.cpp +++ /dev/null @@ -1,728 +0,0 @@ -// Copyright Nick Thompson, 2017 -// 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) - -#define BOOST_TEST_MODULE exp_sinh_quadrature_test - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - -#if __has_include() -# include -#endif - -using std::exp; -using std::cos; -using std::tan; -using std::log; -using std::sqrt; -using std::abs; -using std::sinh; -using std::cosh; -using std::pow; -using std::atan; -using boost::multiprecision::cpp_bin_float_50; -using boost::multiprecision::cpp_bin_float_100; -using boost::multiprecision::cpp_bin_float_quad; -using boost::math::constants::pi; -using boost::math::constants::half_pi; -using boost::math::constants::two_div_pi; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::catalan; -using boost::math::constants::ln_two; -using boost::math::constants::root_two; -using boost::math::constants::root_two_pi; -using boost::math::constants::root_pi; -using boost::math::quadrature::exp_sinh; - -#if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) && !defined(TEST4) && !defined(TEST5) && !defined(TEST6) && !defined(TEST7) && !defined(TEST8) && !defined(TEST9) && !defined(TEST10) -# define TEST1 -# define TEST2 -# define TEST3 -# define TEST4 -# define TEST5 -# define TEST6 -# define TEST7 -# define TEST8 -# define TEST9 -# define TEST10 -#endif - -#ifdef _MSC_VER -#pragma warning (disable:4127) -#endif - -// -// Coefficient generation code: -// -template -void print_levels(const T& v, const char* suffix) -{ - std::cout << "{\n"; - for (unsigned i = 0; i < v.size(); ++i) - { - std::cout << " { "; - for (unsigned j = 0; j < v[i].size(); ++j) - { - std::cout << v[i][j] << suffix << ", "; - } - std::cout << "},\n"; - } - std::cout << " };\n"; -} - -template -void print_levels(const std::pair& p, const char* suffix = "") -{ - std::cout << " static const std::vector > abscissa = "; - print_levels(p.first, suffix); - std::cout << " static const std::vector > weights = "; - print_levels(p.second, suffix); -} - -template -std::pair>, std::vector> > generate_constants(unsigned max_rows) -{ - using boost::math::constants::half_pi; - using boost::math::constants::two_div_pi; - using boost::math::constants::pi; - auto g = [](Real t)->Real { return exp(half_pi()*sinh(t)); }; - auto w = [](Real t)->Real { return cosh(t)*half_pi()*exp(half_pi()*sinh(t)); }; - - std::vector> abscissa, weights; - - std::vector temp; - - Real tmp = (Real(boost::math::tools::log_min_value()) + log(Real(boost::math::tools::epsilon())))*0.5f; - Real t_min = asinh(two_div_pi()*tmp); - // truncate t_min to an exact binary value: - t_min = floor(t_min * 128) / 128; - - std::cout << "m_t_min = " << t_min << ";\n"; - - // t_max is chosen to make g'(t_max) ~ sqrt(max) (g' grows faster than g). - // This will allow some flexibility on the users part; they can at least square a number function without overflow. - // But there is no unique choice; the further out we can evaluate the function, the better we can do on slowly decaying integrands. - const Real t_max = log(2 * two_div_pi()*log(2 * two_div_pi()*sqrt(Real(boost::math::tools::max_value())))); - - Real h = 1; - for (Real t = t_min; t < t_max; t += h) - { - temp.push_back(g(t)); - } - abscissa.push_back(temp); - temp.clear(); - - for (Real t = t_min; t < t_max; t += h) - { - temp.push_back(w(t * h)); - } - weights.push_back(temp); - temp.clear(); - - for (unsigned row = 1; row < max_rows; ++row) - { - h /= 2; - for (Real t = t_min + h; t < t_max; t += 2 * h) - temp.push_back(g(t)); - abscissa.push_back(temp); - temp.clear(); - } - h = 1; - for (unsigned row = 1; row < max_rows; ++row) - { - h /= 2; - for (Real t = t_min + h; t < t_max; t += 2 * h) - temp.push_back(w(t)); - weights.push_back(temp); - temp.clear(); - } - - return std::make_pair(abscissa, weights); -} - - -template -const exp_sinh& get_integrator() -{ - static const exp_sinh integrator(14); - return integrator; -} - -template -Real get_convergence_tolerance() -{ - return boost::math::tools::root_epsilon(); -} - -template -void test_right_limit_infinite() -{ - std::cout << "Testing right limit infinite for tanh_sinh in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real Q; - Real Q_expected; - Real error; - Real L1; - const auto& integrator = get_integrator(); - - // Example 12 - const auto f2 = [](const Real& t)->Real { return exp(-t)/sqrt(t); }; - Q = integrator.integrate(f2, get_convergence_tolerance(), &error, &L1); - Q_expected = root_pi(); - Real tol_mult = 1; - // Multiprecision type have higher error rates, probably evaluation of f() is less accurate: - if (!std::numeric_limits::digits10 || (std::numeric_limits::digits10 > 25)) - tol_mult = 1200; - else if (std::numeric_limits::digits10 > std::numeric_limits::digits10) - tol_mult = 5; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol * tol_mult); - // The integrand is strictly positive, so it coincides with the value of the integral: - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol * tol_mult); - - #ifdef BOOST_MATH_STANDALONE - BOOST_IF_CONSTEXPR (std::is_fundamental::value) - #endif - { - auto f3 = [](Real t)->Real { Real z = exp(-t); if (z == 0) { return z; } return z*cos(t); }; - Q = integrator.integrate(f3, get_convergence_tolerance(), &error, &L1); - Q_expected = half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - Q = integrator.integrate(f3, 10, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = BOOST_MATH_TEST_VALUE(Real, -6.6976341310426674140007086979326069121526743314567805278252392932e-6); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 10 * tol); - // Integrating through zero risks precision loss: - Q = integrator.integrate(f3, -10, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = BOOST_MATH_TEST_VALUE(Real, -15232.3213626280525704332288302799653087046646639974940243044623285817777006); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, std::numeric_limits::digits10 > 30 ? 1000 * tol : tol); - - auto f4 = [](Real t)->Real { return 1/(1+t*t); }; - Q = integrator.integrate(f4, 1, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = pi()/4; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - Q = integrator.integrate(f4, 20, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = BOOST_MATH_TEST_VALUE(Real, 0.0499583957219427614100062870348448814912770804235071744108534548299835954767); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - Q = integrator.integrate(f4, 500, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = BOOST_MATH_TEST_VALUE(Real, 0.0019999973333397333150476759363217553199063513829126652556286269630); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - } -} - -template -void test_left_limit_infinite() -{ - std::cout << "Testing left limit infinite for 1/(1+t^2) on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real Q; - Real Q_expected; - Real error; - Real L1; - const auto& integrator = get_integrator(); - - // Example 11: - #ifdef BOOST_MATH_STANDALONE - BOOST_IF_CONSTEXPR (std::is_fundamental::value) - #endif - { - auto f1 = [](const Real& t)->Real { return 1/(1+t*t);}; - Q = integrator.integrate(f1, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), 0, get_convergence_tolerance(), &error, &L1); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - Q = integrator.integrate(f1, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), -20, get_convergence_tolerance(), &error, &L1); - Q_expected = BOOST_MATH_TEST_VALUE(Real, 0.0499583957219427614100062870348448814912770804235071744108534548299835954767); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - Q = integrator.integrate(f1, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), -500, get_convergence_tolerance(), &error, &L1); - Q_expected = BOOST_MATH_TEST_VALUE(Real, 0.0019999973333397333150476759363217553199063513829126652556286269630); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - } -} - - -// Some examples of tough integrals from NR, section 4.5.4: -template -void test_nr_examples() -{ - using std::sin; - using std::cos; - using std::pow; - using std::exp; - using std::sqrt; - std::cout << "Testing type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - std::cout << std::setprecision(std::numeric_limits::digits10); - Real Q; - Real Q_expected; - Real L1; - Real error; - const auto& integrator = get_integrator(); - - auto f0 = [] (Real)->Real { return (Real) 0; }; - Q = integrator.integrate(f0, get_convergence_tolerance(), &error, &L1); - Q_expected = 0; - BOOST_CHECK_CLOSE_FRACTION(Q, 0.0f, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, 0.0f, tol); - - auto f = [](const Real& x)->Real { return 1/(1+x*x); }; - Q = integrator.integrate(f, get_convergence_tolerance(), &error, &L1); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - auto f1 = [](Real x)->Real { - Real z1 = exp(-x); - if (z1 == 0) - { - return (Real) 0; - } - Real z2 = pow(x, -3*half())*z1; - if (z2 == 0) - { - return (Real) 0; - } - return sin(x*half())*z2; - }; - - Q = integrator.integrate(f1, get_convergence_tolerance(), &error, &L1); - Q_expected = sqrt(pi()*(sqrt((Real) 5) - 2)); - - // The integrand is oscillatory; the accuracy is low. - Real tol_mul = 1; - if (std::numeric_limits::digits10 > 40) - tol_mul = 500000; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol_mul * tol); - - auto f2 = [](Real x)->Real { return x > boost::math::tools::log_max_value() ? Real(0) : Real(pow(x, -(Real) 2/(Real) 7)*exp(-x*x)); }; - Q = integrator.integrate(f2, get_convergence_tolerance(), &error, &L1); - Q_expected = half()*boost::math::tgamma((Real) 5/ (Real) 14); - tol_mul = 1; - if ((std::numeric_limits::is_specialized == false) || (std::numeric_limits::digits10 > 40)) - tol_mul = 500; - else - tol_mul = 3; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol_mul * tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol_mul * tol); - - auto f3 = [](Real x)->Real { return (Real) 1/ (sqrt(x)*(1+x)); }; - Q = integrator.integrate(f3, get_convergence_tolerance(), &error, &L1); - Q_expected = pi(); - - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 10*boost::math::tools::epsilon()); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, 10*boost::math::tools::epsilon()); - - auto f4 = [](const Real& t)->Real { return t > boost::math::tools::log_max_value() ? Real(0) : Real(exp(-t*t*half())); }; - Q = integrator.integrate(f4, get_convergence_tolerance(), &error, &L1); - Q_expected = root_two_pi()/2; - tol_mul = 1; - if (std::numeric_limits::digits10 > 40) - tol_mul = 5000; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol_mul * tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol_mul * tol); - - auto f5 = [](const Real& t)->Real { return 1/cosh(t);}; - Q = integrator.integrate(f5, get_convergence_tolerance(), &error, &L1); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol * 12); // Fails at float precision without higher error rate - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol * 12); -} - -// Definite integrals found in the CRC Handbook of Mathematical Formulas -template -void test_crc() -{ - using std::sin; - using std::pow; - using std::exp; - using std::sqrt; - using std::log; - using std::cos; - std::cout << "Testing integral from CRC handbook on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - std::cout << std::setprecision(std::numeric_limits::digits10); - Real Q; - Real Q_expected; - Real L1; - Real error; - const auto& integrator = get_integrator(); - - auto f0 = [](const Real& x)->Real { return x > boost::math::tools::log_max_value() ? Real(0) : Real(log(x)*exp(-x)); }; - Q = integrator.integrate(f0, get_convergence_tolerance(), &error, &L1); - Q_expected = -boost::math::constants::euler(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Test the integral representation of the gamma function: - auto f1 = [](Real t)->Real { Real x = exp(-t); - if(x == 0) - { - return (Real) 0; - } - return pow(t, (Real) 12 - 1)*x; - }; - - Q = integrator.integrate(f1, get_convergence_tolerance(), &error, &L1); - Q_expected = boost::math::tgamma(12.0f); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Integral representation of the modified bessel function: - // K_5(12) - auto f2 = [](Real t)->Real { - Real x = 12*cosh(t); - if (x > boost::math::tools::log_max_value()) - { - return (Real) 0; - } - return exp(-x)*cosh(5*t); - }; - Q = integrator.integrate(f2, get_convergence_tolerance(), &error, &L1); - Q_expected = boost::math::cyl_bessel_k(5, 12); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - // Laplace transform of cos(at) - Real a = 20; - Real s = 1; - auto f3 = [&](Real t)->Real { - Real x = s * t; - if (x > boost::math::tools::log_max_value()) - { - return (Real) 0; - } - return cos(a * t) * exp(-x); - }; - - // Since the integrand is oscillatory, we increase the tolerance: - Real tol_mult = 10; - // Multiprecision type have higher error rates, probably evaluation of f() is less accurate: - if (!std::is_class::value) - { - // For high oscillation frequency, the quadrature sum is ill-conditioned. - Q = integrator.integrate(f3, get_convergence_tolerance(), &error, &L1); - Q_expected = s/(a*a+s*s); - if (std::numeric_limits::digits10 > std::numeric_limits::digits10) - tol_mult = 500000; // we should really investigate this more?? - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol_mult*tol); - } - - // - // This one doesn't pass for real_concept.. - // - if (std::numeric_limits::is_specialized) - { - // Laplace transform of J_0(t): - auto f4 = [&](Real t)->Real { - Real x = s * t; - if (x > boost::math::tools::log_max_value()) - { - return (Real)0; - } - return boost::math::cyl_bessel_j(0, t) * exp(-x); - }; - - Q = integrator.integrate(f4, get_convergence_tolerance(), &error, &L1); - Q_expected = 1 / sqrt(1 + s*s); - tol_mult = 3; - // Multiprecision type have higher error rates, probably evaluation of f() is less accurate: - if ((std::numeric_limits::digits10 > std::numeric_limits::digits10) || (std::numeric_limits::digits > 100) || !std::numeric_limits::digits) - tol_mult = 50000; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol_mult * tol); - } - auto f6 = [](const Real& t)->Real { return t > boost::math::tools::log_max_value() ? Real(0) : Real(exp(-t*t)*log(t));}; - Q = integrator.integrate(f6, get_convergence_tolerance(), &error, &L1); - Q_expected = -boost::math::constants::root_pi()*(boost::math::constants::euler() + 2*ln_two())/4; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // CRC Section 5.5, integral 591 - // The parameter p allows us to control the strength of the singularity. - // Rapid convergence is not guaranteed for this function, as the branch cut makes it non-analytic on a disk. - // This converges only when our test type has an extended exponent range as all the area of the integral - // occurs so close to 0 (or 1) that we need abscissa values exceptionally small to find it. - // "There's a lot of room at the bottom". - // This version is transformed via argument substitution (exp(-x) for x) so that the integral is spread - // over (0, INF). - tol *= boost::math::tools::digits() > 100 ? 100000 : 75; - for (Real pn = 99; pn > 0; pn -= 10) { - Real p = pn / 100; - auto f = [&](Real x)->Real - { - return x > 1000 * boost::math::tools::log_max_value() ? Real(0) : Real(exp(-x * (1 - p) + p * log(-boost::math::expm1(-x)))); - }; - Q = integrator.integrate(f, get_convergence_tolerance(), &error, &L1); - Q_expected = 1 / boost::math::sinc_pi(p*pi()); - /* - std::cout << std::setprecision(std::numeric_limits::max_digits10) << p << std::endl; - std::cout << std::setprecision(std::numeric_limits::max_digits10) << Q << std::endl; - std::cout << std::setprecision(std::numeric_limits::max_digits10) << Q_expected << std::endl; - std::cout << fabs((Q - Q_expected) / Q_expected) << std::endl; - */ - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - } - // and for p < 1: - for (Real p = -0.99; p < 0; p += 0.1) { - auto f = [&](Real x)->Real - { - return x > 1000 * boost::math::tools::log_max_value() ? Real(0) : Real(exp(-p * log(-boost::math::expm1(-x)) - (1 + p) * x)); - }; - Q = integrator.integrate(f, get_convergence_tolerance(), &error, &L1); - Q_expected = 1 / boost::math::sinc_pi(p*pi()); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - } -} - -template -void test_complex_modified_bessel() -{ - std::cout << "Testing complex modified Bessel function on type " << boost::typeindex::type_id().pretty_name() << "\n"; - typedef typename Complex::value_type Real; - Real tol = 100 * boost::math::tools::epsilon(); - Real error; - Real L1; - const auto& integrator = get_integrator(); - - // Integral Representation of Modified Complex Bessel function: - // https://en.wikipedia.org/wiki/Bessel_function#Modified_Bessel_functions - Complex z{2, 3}; - const auto f = [&z](const Real& t)->Complex - { - using std::cosh; - using std::exp; - Real cosht = cosh(t); - if (cosht > boost::math::tools::log_max_value()) - { - return Complex{0, 0}; - } - Complex arg = -z*cosht; - Complex res = exp(arg); - return res; - }; - - Complex K0 = integrator.integrate(f, get_convergence_tolerance(), &error, &L1); - - // Mathematica code: N[BesselK[0, 2 + 3 I], 140] - #ifdef BOOST_MATH_STANDALONE - BOOST_IF_CONSTEXPR (std::is_fundamental::value) - #endif - { - Real K0_x_expected = BOOST_MATH_TEST_VALUE(Real, -0.08296852656762551490517953520589186885781541203818846830385526187936132191822538822296497597191327722262903004145527496422090506197776994); - Real K0_y_expected = BOOST_MATH_TEST_VALUE(Real, 0.027949603635183423629723306332336002340909030265538548521150904238352846705644065168365102147901993976999717171115546662967229050834575193041); - BOOST_CHECK_CLOSE_FRACTION(K0.real(), K0_x_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(K0.imag(), K0_y_expected, tol); - } -} - -template -void test_complex_exponential_integral_E1(){ - std::cout << "Testing complex exponential integral on type " << boost::typeindex::type_id().pretty_name() << "\n"; - typedef typename Complex::value_type Real; - Real tol = 100 * boost::math::tools::epsilon(); - Real error; - Real L1; - const auto& integrator = get_integrator(); - - Complex z{1.5,0.5}; - - // Integral representation of exponential integral E1, valid for Re z > 0 - // https://en.wikipedia.org/wiki/Exponential_integral#Definitions - auto f = [&z](const Real& t)->Complex - { - using std::exp; - return exp(-z*t)/t; - }; - - Real inf = std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(); - - Complex E1 = integrator.integrate(f,1,inf,get_convergence_tolerance(),&error,&L1); - - // Mathematica code: N[ExpIntegral[1,1.5 + 0.5 I],140] - #ifdef BOOST_MATH_STANDALONE - BOOST_IF_CONSTEXPR (std::is_fundamental::value) - #endif - { - Real E1_real_expected = BOOST_MATH_TEST_VALUE(Real, 0.071702995463938694845949672113596046091766639758473558841839765788732549949008866887694451956003503764943496943262401868244277788066634858393); - Real E1_imag_expected = BOOST_MATH_TEST_VALUE(Real, -0.065138628279238400564373880665751377423524428792583839078600260273866805818117625959446311737353882269129094759883720722150048944193926087208); - BOOST_CHECK_CLOSE_FRACTION(E1.real(), E1_real_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(E1.imag(), E1_imag_expected, tol); - } -} - -template -void test_non_central_t() -{ - // - // Bug case from the non-central t distribution: - // - using std::pow; - using std::exp; - using std::sqrt; - - std::cout << "Testing non-central T PDF integral" << std::endl; - - T x = -1.882352352142334; - T v = 77.384613037109375; - T mu = 8.1538467407226562; - T expected = static_cast(4.5098555913703146875364186893655197e+49L); - - boost::math::quadrature::exp_sinh integrator; - T err; - T L1; - std::size_t levels; - T integral = integrator.integrate([&x, v, mu](T y) - { - return pow(y, v) * exp(boost::math::pow<2>((y - mu * x / sqrt(x * x + v))) / -2); - }, - boost::math::tools::root_epsilon(), &err, &L1, &levels); - - T tol = 100 * boost::math::tools::epsilon(); - BOOST_CHECK_CLOSE_FRACTION(integral, expected, tol); -} - - -BOOST_AUTO_TEST_CASE(exp_sinh_quadrature_test) -{ - // - // Uncomment to generate the coefficients: - // - - /* - std::cout << std::scientific << std::setprecision(8); - print_levels(generate_constants(8), "f"); - std::cout << std::setprecision(18); - print_levels(generate_constants(8), ""); - std::cout << std::setprecision(35); - print_levels(generate_constants(8), "L"); - */ - -#ifdef TEST1 - -#ifdef __STDCPP_FLOAT32_T__ - test_left_limit_infinite(); - test_right_limit_infinite(); - test_nr_examples(); - test_crc(); - //test_non_central_t(); -#else - test_left_limit_infinite(); - test_right_limit_infinite(); - test_nr_examples(); - test_crc(); - //test_non_central_t(); -#endif - -#endif -#ifdef TEST2 - -#ifdef __STDCPP_FLOAT64_T__ - test_left_limit_infinite(); - test_right_limit_infinite(); - test_nr_examples(); - test_crc(); - test_non_central_t(); -#else - test_left_limit_infinite(); - test_right_limit_infinite(); - test_nr_examples(); - test_crc(); - test_non_central_t(); -#endif - -#endif -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS -#ifdef TEST3 -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_left_limit_infinite(); - test_right_limit_infinite(); - test_nr_examples(); - test_crc(); - test_non_central_t(); -#endif -#endif -#endif -#if defined(TEST4) && defined(BOOST_MATH_RUN_MP_TESTS) - test_left_limit_infinite(); - test_right_limit_infinite(); - test_nr_examples(); - test_crc(); -#endif - -#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) -#ifdef TEST5 - test_left_limit_infinite(); - test_right_limit_infinite(); - test_nr_examples(); - test_crc(); - test_non_central_t(); -#endif -#endif -#if defined(TEST6) && defined(BOOST_MATH_RUN_MP_TESTS) - test_left_limit_infinite(); - test_right_limit_infinite(); - test_nr_examples(); - test_crc(); -#endif -#if defined(TEST7) && defined(BOOST_MATH_RUN_MP_TESTS) - test_left_limit_infinite(); - test_right_limit_infinite(); - test_nr_examples(); - // - // This one causes stack overflows on the CI machine, but not locally, - // assume it's due to restricted resources on the server, and for now... - // -#if ! BOOST_WORKAROUND(BOOST_MSVC, == 1900) && defined(BOOST_MATH_RUN_MP_TESTS) - test_crc(); -#endif -#endif -#ifdef TEST8 - test_complex_modified_bessel>(); - test_complex_modified_bessel>(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_complex_modified_bessel>(); -#endif -#ifndef BOOST_MATH_NO_MP_TESTS - test_complex_modified_bessel(); -#endif -#endif -#ifdef TEST9 - test_complex_exponential_integral_E1>(); - test_complex_exponential_integral_E1>(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_complex_exponential_integral_E1>(); -#endif -#if defined(BOOST_MATH_RUN_MP_TESTS) - test_complex_exponential_integral_E1(); -#endif -#endif -#ifdef TEST10 -#if defined(BOOST_HAS_FLOAT128) && !defined(BOOST_MATH_NO_MP_TESTS) - test_complex_modified_bessel(); - test_complex_exponential_integral_E1(); -#endif -#endif -} diff --git a/test/float128/log1p_expm1_test.cpp b/test/float128/log1p_expm1_test.cpp deleted file mode 100644 index c46d5b099a..0000000000 --- a/test/float128/log1p_expm1_test.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2002 - 2011. -// Copyright 2011 John Maddock. 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_ -// -// This work is based on an earlier work: -// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", -// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 - -#include "setup.hpp" -#include -#include - -#include "table_type.hpp" - -#include "log1p_expm1_test.hpp" - -// -// DESCRIPTION: -// ~~~~~~~~~~~~ -// -// This file tests the functions log1p and expm1. The accuracy tests -// use values generated with NTL::RR at 1000-bit precision -// and our generic versions of these functions. -// -// Note that when this file is first run on a new platform many of -// these tests will fail: the default accuracy is 1 epsilon which -// is too tight for most platforms. In this situation you will -// need to cast a human eye over the error rates reported and make -// a judgement as to whether they are acceptable. Either way please -// report the results to the Boost mailing list. Acceptable rates of -// error are marked up below as a series of regular expressions that -// identify the compiler/stdlib/platform/data-type/test-data/test-function -// along with the maximum expected peek and RMS mean errors for that -// test. -// - -void expected_results() -{ - // - // Define the max and mean errors expected for - // various compilers and platforms. - // - - // - // Catch all cases come last: - // - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*", // test type(s) - ".*", // test data group - ".*", // test function - 8, // Max Peek error - 5); // Max mean error - - // - // Finish off by printing out the compiler/stdlib/platform names, - // we do this to make it easier to mark up expected error rates. - // - std::cout << "Tests run with " << BOOST_COMPILER << ", " - << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; -} - - -BOOST_AUTO_TEST_CASE( test_main ) -{ - expected_results(); - // - // Test at: - // 18 decimal digits: tests 80-bit long double approximations - // 30 decimal digits: tests 128-bit long double approximations - // 35 decimal digits: tests arbitrary precision code - // - ALL_TESTS -} - diff --git a/test/float128/powm1_sqrtp1m1_test.cpp b/test/float128/powm1_sqrtp1m1_test.cpp deleted file mode 100644 index bfc219bcc6..0000000000 --- a/test/float128/powm1_sqrtp1m1_test.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2002 - 2011. -// Copyright 2011 John Maddock. 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_ -// -// This work is based on an earlier work: -// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", -// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 - -#include "setup.hpp" - -#include -#include -#include - -#include "table_type.hpp" - -#include "powm1_sqrtp1m1_test.hpp" - -// -// DESCRIPTION: -// ~~~~~~~~~~~~ -// -// This file tests the functions log1p and expm1. The accuracy tests -// use values generated with NTL::RR at 1000-bit precision -// and our generic versions of these functions. -// -// Note that when this file is first run on a new platform many of -// these tests will fail: the default accuracy is 1 epsilon which -// is too tight for most platforms. In this situation you will -// need to cast a human eye over the error rates reported and make -// a judgement as to whether they are acceptable. Either way please -// report the results to the Boost mailing list. Acceptable rates of -// error are marked up below as a series of regular expressions that -// identify the compiler/stdlib/platform/data-type/test-data/test-function -// along with the maximum expected peek and RMS mean errors for that -// test. -// - -void expected_results() -{ - // - // Define the max and mean errors expected for - // various compilers and platforms. - // - - // - // Catch all cases come last: - // - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*", // test type(s) - ".*", // test data group - ".*", // test function - 15, // Max Peek error - 5); // Max mean error - - // - // Finish off by printing out the compiler/stdlib/platform names, - // we do this to make it easier to mark up expected error rates. - // - std::cout << "Tests run with " << BOOST_COMPILER << ", " - << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; -} - -template -void test(T t, const char* p) -{ - test_powm1_sqrtp1m1(t, p); -} - -BOOST_AUTO_TEST_CASE( test_main ) -{ - expected_results(); - ALL_TESTS -} - - - diff --git a/test/float128/test_log1p_expm1.cpp b/test/float128/test_log1p_expm1.cpp new file mode 100644 index 0000000000..882881a74b --- /dev/null +++ b/test/float128/test_log1p_expm1.cpp @@ -0,0 +1,79 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. 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_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#include "setup.hpp" +#include +#include + +#include "table_type.hpp" + +#include "test_log1p_expm1.hpp" + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the functions log1p and expm1. The accuracy tests +// use values generated with NTL::RR at 1000-bit precision +// and our generic versions of these functions. +// +// Note that when this file is first run on a new platform many of +// these tests will fail: the default accuracy is 1 epsilon which +// is too tight for most platforms. In this situation you will +// need to cast a human eye over the error rates reported and make +// a judgement as to whether they are acceptable. Either way please +// report the results to the Boost mailing list. Acceptable rates of +// error are marked up below as a series of regular expressions that +// identify the compiler/stdlib/platform/data-type/test-data/test-function +// along with the maximum expected peek and RMS mean errors for that +// test. +// + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + + // + // Catch all cases come last: + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", // test function + 8, // Max Peek error + 5); // Max mean error + + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +BOOST_AUTO_TEST_CASE( test_main ) +{ + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // + ALL_TESTS +} + diff --git a/test/float128/test_powm1_sqrtp1m1.cpp b/test/float128/test_powm1_sqrtp1m1.cpp new file mode 100644 index 0000000000..d72a484f00 --- /dev/null +++ b/test/float128/test_powm1_sqrtp1m1.cpp @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. 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_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#include "setup.hpp" + +#include +#include +#include + +#include "table_type.hpp" + +#include "test_powm1_sqrtp1m1.hpp" + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the functions log1p and expm1. The accuracy tests +// use values generated with NTL::RR at 1000-bit precision +// and our generic versions of these functions. +// +// Note that when this file is first run on a new platform many of +// these tests will fail: the default accuracy is 1 epsilon which +// is too tight for most platforms. In this situation you will +// need to cast a human eye over the error rates reported and make +// a judgement as to whether they are acceptable. Either way please +// report the results to the Boost mailing list. Acceptable rates of +// error are marked up below as a series of regular expressions that +// identify the compiler/stdlib/platform/data-type/test-data/test-function +// along with the maximum expected peek and RMS mean errors for that +// test. +// + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + + // + // Catch all cases come last: + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", // test function + 15, // Max Peek error + 5); // Max mean error + + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + +template +void test(T t, const char* p) +{ + test_powm1_sqrtp1m1(t, p); +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + expected_results(); + ALL_TESTS +} + + + diff --git a/test/float128/test_std_lib.cpp b/test/float128/test_std_lib.cpp index c051cdef41..0f24762540 100644 --- a/test/float128/test_std_lib.cpp +++ b/test/float128/test_std_lib.cpp @@ -306,6 +306,16 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_EQUAL(imag(pow(x, a)), 0); } + { + // https://github.com/boostorg/math/issues/979 + const std::complex x(BOOST_FLOAT128_C(-0.7)); + const boost::float128_t a = BOOST_FLOAT128_C(2.3); + const std::complex result = pow(x, a); + + BOOST_CHECK_CLOSE_FRACTION(real(result), BOOST_FLOAT128_C(0.25878802568257011821501000150048912386011658184359), 10*tol); + BOOST_CHECK_CLOSE_FRACTION(imag(result), BOOST_FLOAT128_C(0.35619115978391923954991722482212002575161366849209), 10*tol); + } + // Check x^a, where x is zero and a is finite. BOOST_CHECK_EQUAL(real(pow(BOOST_FLOATMAX_C(0.0), cm)), 0); BOOST_CHECK_EQUAL(imag(pow(BOOST_FLOATMAX_C(0.0), cm)), 0); diff --git a/test/fourier_transform_daubechies_test.cpp b/test/fourier_transform_daubechies_test.cpp deleted file mode 100644 index 805014de2a..0000000000 --- a/test/fourier_transform_daubechies_test.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// boost-no-inspect -/* - * Copyright Nick Thompson, 2023 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - -using boost::math::fourier_transform_daubechies_scaling; -using boost::math::fourier_transform_daubechies_wavelet; -using boost::math::tools::summation_condition_number; -using boost::math::constants::two_pi; -using boost::math::constants::pi; -using boost::math::constants::one_div_root_two_pi; -using boost::math::quadrature::trapezoidal; -// 𝓕[φ](-ω) = 𝓕[φ](ω)* -template -void test_evaluation_symmetry() { - std::cout << "Testing evaluation symmetry on the " << p << " vanishing moment scaling function.\n"; - auto phi = fourier_transform_daubechies_scaling(0.0); - CHECK_ULP_CLOSE(one_div_root_two_pi(), phi.real(), 3); - CHECK_ULP_CLOSE(static_cast(0), phi.imag(), 3); - - Real domega = Real(1)/128; - for (Real omega = domega; omega < 10; omega += domega) { - auto phi1 = fourier_transform_daubechies_scaling(-omega); - auto phi2 = fourier_transform_daubechies_scaling(omega); - CHECK_ULP_CLOSE(phi1.real(), phi2.real(), 3); - CHECK_ULP_CLOSE(phi1.imag(), -phi2.imag(), 3); - - auto psi1 = fourier_transform_daubechies_wavelet(-omega); - auto psi2 = fourier_transform_daubechies_wavelet(omega); - CHECK_ULP_CLOSE(psi1.real(), psi2.real(), 3); - CHECK_ULP_CLOSE(psi1.imag(), -psi2.imag(), 3); - } - - for (Real omega = 10; omega < std::cbrt(std::numeric_limits::max()); omega *= 10) { - auto phi1 = fourier_transform_daubechies_scaling(-omega); - auto phi2 = fourier_transform_daubechies_scaling(omega); - CHECK_ULP_CLOSE(phi1.real(), phi2.real(), 3); - CHECK_ULP_CLOSE(phi1.imag(), -phi2.imag(), 3); - } - return; -} - -template -void test_roots() { - std::cout << "Testing roots on the " << p << " vanishing moment scaling function.\n"; - for (long n = 1; n < 100; ++n) { - // All arguments of the form 2πn are roots of the complex function: - // See Daubechies, 10 Lectures on Wavelets, Section 6.2: - Real omega = n*two_pi(); - Real residual = std::norm(fourier_transform_daubechies_scaling(omega)); - CHECK_LE(residual, std::numeric_limits::epsilon()*std::numeric_limits::epsilon()); - } - std::cout << "Testing roots on the " << p << " vanishing moment wavelet.\n"; - // If ωₙ is a root of the 𝓕[𝜙], then 2ωₙ is a root of 𝓕[ψ]. - // In addition, m₀(π) = 0, and m₀ is 2π periodic. - // Recalling 𝓕[ψ](ω) = exp(iω/2)m₀(ω/2 + π)^{*}𝓕[𝜙](ω/2)*phase, - // ω=4nπ are also roots: - for (long n = 0; n < 100; ++n) { - Real omega = 4*n*pi(); - Real residual = std::norm(fourier_transform_daubechies_wavelet(omega)); - CHECK_LE(residual, std::numeric_limits::epsilon()*std::numeric_limits::epsilon()); - } -} - -template -void test_scaling_quadrature() { - std::cout << "Testing numerical quadrature of the scaling function with " << p << " vanishing moments matches numerical evaluation.\n"; - auto phi = boost::math::daubechies_scaling(); - auto [tmin, tmax] = phi.support(); - double domega = 1/8.0; - for (double omega = domega; omega < 10; omega += domega) { - // I suspect the quadrature is less accurate than special function evaluation, so this is just a sanity check: - auto f = [&](double t) { - return phi(t)*std::exp(std::complex(0, -omega*t))*one_div_root_two_pi(); - }; - auto expected = trapezoidal(f, tmin, tmax, 2*std::numeric_limits::epsilon()); - auto computed = fourier_transform_daubechies_scaling(static_cast(omega)); - CHECK_MOLLIFIED_CLOSE(static_cast(expected.real()), computed.real(), 1e-4); - CHECK_MOLLIFIED_CLOSE(static_cast(expected.imag()), computed.imag(), 1e-4); - } -} - -template -void test_wavelet_quadrature() { - std::cout << "Testing numerical quadrature of the wavelet with " << p << " vanishing moments matches numerical evaluation.\n"; - auto psi = boost::math::daubechies_wavelet(); - auto [tmin, tmax] = psi.support(); - double domega = 1/8.0; - // There is a root at at ω=0, so skip this one because we can't recover the phase of a root. - for (double omega = 2*domega; omega < 10; omega += domega) { - // I suspect the quadrature is less accurate than special function evaluation, so this is just a sanity check: - auto f = [&](double t) { - return psi(t)*std::exp(std::complex(0, -omega*t))*one_div_root_two_pi(); - }; - auto expected = trapezoidal(f, tmin, tmax, std::numeric_limits::epsilon()); - auto computed = fourier_transform_daubechies_wavelet(omega); - if(!CHECK_ABSOLUTE_ERROR(std::abs(expected), std::abs(computed), 1e-9)) { - std::cerr << " |𝓕[ψ](" << omega << ")| is incorrect.\n"; - } - // Again, lots of evidence that the quadrature is less accurate than what we've implemented. - // Graph of the quadrature phase is super janky; graph of the implementation phase is pretty good. - if(!CHECK_ABSOLUTE_ERROR(std::arg(expected), std::arg(computed), 1e-2)) { - std::cerr << " arg(𝓕[ψ](" << omega << ")) is incorrect.\n"; - } - } -} - - -// Tests Daubechies "Ten Lectures on Wavelets", equation 5.1.19: -template -void test_ten_lectures_eq_5_1_19() { - std::cout << "Testing Ten Lectures equation 5.1.19 on " << p << " vanishing moments.\n"; - Real domega = Real(1)/Real(16); - for (Real omega = 0; omega < 1; omega += domega) { - Real term = std::norm(fourier_transform_daubechies_scaling(omega)); - auto sum = summation_condition_number(term); - int64_t l = 1; - while (l < 10000 && term > 2*std::numeric_limits::epsilon()) { - Real tpl = std::norm(fourier_transform_daubechies_scaling(omega + two_pi()*l)); - Real tml = std::norm(fourier_transform_daubechies_scaling(omega - two_pi()*l)); - - sum += tpl; - sum += tml; - ++l; - } - // With arg promotion, I can get this to 13 ULPS: - if (!CHECK_ULP_CLOSE(1/two_pi(), sum.sum(), 125)) { - std::cerr << " Failure with occurs on " << p << " vanishing moments.\n"; - } - } -} - -// Tests Daubechies "Ten Lectures on Wavelets", equation 5.1.38: -template -void test_ten_lectures_eq_5_1_38() { - std::cout << "Testing Ten Lectures equation 5.1.38 on " << p << " vanishing moments.\n"; - Real domega = Real(1)/Real(16); - for (Real omega = 0; omega < 1; omega += domega) { - Real phi_omega_sq = std::norm(fourier_transform_daubechies_scaling(omega)); - Real psi_omega_sq = std::norm(fourier_transform_daubechies_wavelet(omega)); - Real phi_half_omega_sq = std::norm(fourier_transform_daubechies_scaling(omega/2)); - - if (!CHECK_ULP_CLOSE(phi_half_omega_sq, phi_omega_sq + psi_omega_sq, 125)) { - std::cerr << " Failure with occurs on " << p << " vanishing moments at omega = " << omega << "\n"; - } - } -} - - -int main() -{ - test_roots(); - test_roots(); - test_roots(); - test_roots(); - test_roots(); - test_roots(); - test_roots(); - test_roots(); - test_roots(); - test_roots(); - - test_evaluation_symmetry(); - test_evaluation_symmetry(); - test_evaluation_symmetry(); - test_evaluation_symmetry(); - test_evaluation_symmetry(); - test_evaluation_symmetry(); - test_evaluation_symmetry(); - test_evaluation_symmetry(); - test_evaluation_symmetry(); - test_evaluation_symmetry(); - - // Slow tests: - test_scaling_quadrature<9>(); - test_scaling_quadrature<10>(); - - // This one converges really slowly: - //test_ten_lectures_eq_5_1_19(); - test_ten_lectures_eq_5_1_19(); - test_ten_lectures_eq_5_1_19(); - test_ten_lectures_eq_5_1_19(); - test_ten_lectures_eq_5_1_19(); - test_ten_lectures_eq_5_1_19(); - test_ten_lectures_eq_5_1_19(); - test_ten_lectures_eq_5_1_19(); - test_ten_lectures_eq_5_1_19(); - test_ten_lectures_eq_5_1_19(); - - test_ten_lectures_eq_5_1_38(); - test_ten_lectures_eq_5_1_38(); - test_ten_lectures_eq_5_1_38(); - test_ten_lectures_eq_5_1_38(); - - test_wavelet_quadrature<9>(); - - return boost::math::test::report_errors(); -} diff --git a/test/gauss_kronrod_quadrature_test.cpp b/test/gauss_kronrod_quadrature_test.cpp deleted file mode 100644 index 5877146d71..0000000000 --- a/test/gauss_kronrod_quadrature_test.cpp +++ /dev/null @@ -1,570 +0,0 @@ -// Copyright Nick Thompson, 2017 -// 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) - -#define BOOST_TEST_MODULE Gauss Kronrod_quadrature_test - -#include -#include -#include - -#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && !defined(BOOST_NO_SFINAE_EXPR) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - -#if !defined(TEST1) && !defined(TEST1A) && !defined(TEST2) && !defined(TEST3) -# define TEST1 -# define TEST1A -# define TEST2 -# define TEST3 -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4127) // Conditional expression is constant -#endif - -#if __has_include() -# include -#endif - -using std::expm1; -using std::atan; -using std::tan; -using std::log; -using std::log1p; -using std::asinh; -using std::atanh; -using std::sqrt; -using std::isnormal; -using std::abs; -using std::sinh; -using std::tanh; -using std::cosh; -using std::pow; -using std::exp; -using std::sin; -using std::cos; -using std::string; -using boost::math::quadrature::gauss_kronrod; -using boost::math::constants::pi; -using boost::math::constants::half_pi; -using boost::math::constants::two_div_pi; -using boost::math::constants::two_pi; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::catalan; -using boost::math::constants::ln_two; -using boost::math::constants::root_two; -using boost::math::constants::root_two_pi; -using boost::math::constants::root_pi; -using boost::multiprecision::cpp_bin_float_quad; -using boost::multiprecision::cpp_dec_float_50; -using boost::multiprecision::debug_adaptor; -using boost::multiprecision::number; - -// -// Error rates depend only on the number of points in the approximation, not the type being tested, -// define all our expected errors here: -// - -enum -{ - test_ca_error_id, - test_ca_error_id_2, - test_three_quad_error_id, - test_three_quad_error_id_2, - test_integration_over_real_line_error_id, - test_right_limit_infinite_error_id, - test_left_limit_infinite_error_id -}; - -template -double expected_error(unsigned) -{ - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<15>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 1e-7; - case test_ca_error_id_2: - return 2e-5; - case test_three_quad_error_id: - return 1e-8; - case test_three_quad_error_id_2: - return 3.5e-3; - case test_integration_over_real_line_error_id: - return 6e-3; - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 1e-5; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<17>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 1e-7; - case test_ca_error_id_2: - return 2e-5; - case test_three_quad_error_id: - return 1e-8; - case test_three_quad_error_id_2: - return 3.5e-3; - case test_integration_over_real_line_error_id: - return 6e-3; - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 1e-5; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<21>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 1e-12; - case test_ca_error_id_2: - return 3e-6; - case test_three_quad_error_id: - return 2e-13; - case test_three_quad_error_id_2: - return 2e-3; - case test_integration_over_real_line_error_id: - return 6e-3; // doesn't get any better with more points! - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 5e-8; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<31>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 6e-20; - case test_ca_error_id_2: - return 3e-7; - case test_three_quad_error_id: - return 1e-19; - case test_three_quad_error_id_2: - return 6e-4; - case test_integration_over_real_line_error_id: - return 6e-3; // doesn't get any better with more points! - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 5e-11; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<41>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 1e-26; - case test_ca_error_id_2: - return 1e-7; - case test_three_quad_error_id: - return 3e-27; - case test_three_quad_error_id_2: - return 3e-4; - case test_integration_over_real_line_error_id: - return 5e-5; // doesn't get any better with more points! - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 1e-15; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<51>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 5e-33; - case test_ca_error_id_2: - return 1e-8; - case test_three_quad_error_id: - return 1e-32; - case test_three_quad_error_id_2: - return 3e-4; - case test_integration_over_real_line_error_id: - return 1e-14; - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 3e-19; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<61>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 5e-34; - case test_ca_error_id_2: - return 5e-9; - case test_three_quad_error_id: - return 4e-34; - case test_three_quad_error_id_2: - return 1e-4; - case test_integration_over_real_line_error_id: - return 1e-16; - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 3e-23; - } - return 0; // placeholder, all tests will fail -} - - -template -void test_linear() -{ - std::cout << "Testing linear functions are integrated properly by gauss_kronrod on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - Real error; - auto f = [](const Real& x)->Real - { - return 5*x + 7; - }; - Real L1; - Real Q = gauss_kronrod::integrate(f, (Real) 0, (Real) 1, 0, 0, &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, 9.5, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, 9.5, tol); - - Q = gauss_kronrod::integrate(f, (Real) 1, (Real) 0, 0, 0, &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, -9.5, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, 9.5, tol); - - Q = gauss_kronrod::integrate(f, (Real) 0, (Real) 0, 0, 0, &error, &L1); - BOOST_CHECK_CLOSE(Q, Real(0), tol); -} - -template -void test_quadratic() -{ - std::cout << "Testing quadratic functions are integrated properly by Gauss Kronrod on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - Real error; - - auto f = [](const Real& x)->Real { return 5*x*x + 7*x + 12; }; - Real L1; - Real Q = gauss_kronrod::integrate(f, 0, 1, 0, 0, &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, (Real) 17 + half()*third(), tol); - BOOST_CHECK_CLOSE_FRACTION(L1, (Real) 17 + half()*third(), tol); -} - -// Examples taken from -//http://crd-legacy.lbl.gov/~dhbailey/dhbpapers/quadrature.pdf -template -void test_ca() -{ - std::cout << "Testing integration of C(a) on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_ca_error_id); - Real L1; - Real error; - - auto f1 = [](const Real& x)->Real { return atan(x)/(x*(x*x + 1)) ; }; - Real Q = gauss_kronrod::integrate(f1, 0, 1, 0, 0, &error, &L1); - Real Q_expected = pi()*ln_two()/8 + catalan()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - auto f2 = [](Real x)->Real { Real t0 = x*x + 1; Real t1 = sqrt(t0); return atan(t1)/(t0*t1); }; - Q = gauss_kronrod::integrate(f2, 0 , 1, 0, 0, &error, &L1); - Q_expected = pi()/4 - pi()/root_two() + 3*atan(root_two())/root_two(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - tol = expected_error(test_ca_error_id_2); - auto f5 = [](Real t)->Real { return t*t*log(t)/((t*t - 1)*(t*t*t*t + 1)); }; - Q = gauss_kronrod::integrate(f5, 0, 1, 0); - Q_expected = pi()*pi()*(2 - root_two())/32; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); -} - -template -void test_three_quadrature_schemes_examples() -{ - std::cout << "Testing integral in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_three_quad_error_id); - Real Q; - Real Q_expected; - - // Example 1: - auto f1 = [](const Real& t)->Real { return t*boost::math::log1p(t); }; - Q = gauss_kronrod::integrate(f1, 0 , 1, 0); - Q_expected = half()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - - // Example 2: - auto f2 = [](const Real& t)->Real { return t*t*atan(t); }; - Q = gauss_kronrod::integrate(f2, 0 , 1, 0); - Q_expected = (pi() -2 + 2*ln_two())/12; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 2 * tol); - - // Example 3: - auto f3 = [](const Real& t)->Real { return exp(t)*cos(t); }; - Q = gauss_kronrod::integrate(f3, 0, half_pi(), 0); - Q_expected = boost::math::expm1(half_pi())*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Example 4: - auto f4 = [](Real x)->Real { Real t0 = sqrt(x*x + 2); return atan(t0)/(t0*(x*x+1)); }; - Q = gauss_kronrod::integrate(f4, 0 , 1, 0); - Q_expected = 5*pi()*pi()/96; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - tol = expected_error(test_three_quad_error_id_2); - // Example 5: - auto f5 = [](const Real& t)->Real { return sqrt(t)*log(t); }; - Q = gauss_kronrod::integrate(f5, 0 , 1, 0); - Q_expected = -4/ (Real) 9; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Example 6: - auto f6 = [](const Real& t)->Real { return sqrt(1 - t*t); }; - Q = gauss_kronrod::integrate(f6, 0 , 1, 0); - Q_expected = pi()/4; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); -} - - -template -void test_integration_over_real_line() -{ - std::cout << "Testing integrals over entire real line in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_integration_over_real_line_error_id); - Real Q; - Real Q_expected; - Real L1; - Real error; - - auto f1 = [](const Real& t)->Real { return 1/(1+t*t);}; - Q = gauss_kronrod::integrate(f1, -boost::math::tools::max_value(), boost::math::tools::max_value(), 0, 0, &error, &L1); - Q_expected = pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); -} - -template -void test_right_limit_infinite() -{ - std::cout << "Testing right limit infinite for Gauss Kronrod in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_right_limit_infinite_error_id); - Real Q; - Real Q_expected; - Real L1; - Real error; - - // Example 11: - auto f1 = [](const Real& t)->Real { return 1/(1+t*t);}; - Q = gauss_kronrod::integrate(f1, 0, boost::math::tools::max_value(), 0, 0, &error, &L1); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); - - auto f4 = [](const Real& t)->Real { return 1/(1+t*t); }; - Q = gauss_kronrod::integrate(f4, 1, boost::math::tools::max_value(), 0, 0, &error, &L1); - Q_expected = pi()/4; - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); -} - -template -void test_left_limit_infinite() -{ - std::cout << "Testing left limit infinite for Gauss Kronrod in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_left_limit_infinite_error_id); - Real Q; - Real Q_expected; - - // Example 11: - auto f1 = [](const Real& t)->Real { return 1/(1+t*t);}; - Q = gauss_kronrod::integrate(f1, -boost::math::tools::max_value(), Real(0), 0); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); -} - -template -void test_complex_lambert_w() -{ - std::cout << "Testing that complex-valued integrands are integrated correctly by Gaussian quadrature on type " << boost::typeindex::type_id().pretty_name() << "\n"; - typedef typename Complex::value_type Real; - Real tol = 10e-9; - using boost::math::constants::pi; - Complex z{2, 3}; - auto lw = [&z](Real v)->Complex { - using std::cos; - using std::sin; - using std::exp; - Real sinv = sin(v); - Real cosv = cos(v); - - Real cotv = cosv/sinv; - Real cscv = 1/sinv; - Real t = (1-v*cotv)*(1-v*cotv) + v*v; - Real x = v*cscv*exp(-v*cotv); - Complex den = z + x; - Complex num = t*(z/pi()); - Complex res = num/den; - return res; - }; - - //N[ProductLog[2+3*I], 150] - boost::math::quadrature::gauss_kronrod integrator; - Complex Q = integrator.integrate(lw, (Real) 0, pi()); - BOOST_CHECK_CLOSE_FRACTION(Q.real(), BOOST_MATH_TEST_VALUE(Real, 1.0900765344857908463017778267816696498710210863535777805644), tol); - BOOST_CHECK_CLOSE_FRACTION(Q.imag(), BOOST_MATH_TEST_VALUE(Real, 0.5301397207748388014268602135741217419287056313827031782979), tol); -} - -BOOST_AUTO_TEST_CASE(gauss_quadrature_test) -{ -#ifdef TEST1 - std::cout << "Testing 15 point approximation:\n"; - -#ifdef __STDCPP_FLOAT64_T__ - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#else - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#endif - - // test one case where we do not have pre-computed constants: - std::cout << "Testing 17 point approximation:\n"; - -#ifdef __STDCPP_FLOAT64_T__ - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#else - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#endif - - test_complex_lambert_w>(); - test_complex_lambert_w>(); -#endif -#ifdef TEST1A -#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) // If we have too many digits in a long double, we get build errors due to a constexpr issue. - std::cout << "Testing 21 point approximation:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - std::cout << "Testing 31 point approximation:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#endif -#endif -#ifdef TEST2 -#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) // If we have too many digits in a long double, we get build errors due to a constexpr issue. - std::cout << "Testing 41 point approximation:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - std::cout << "Testing 51 point approximation:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#endif -#endif -#if defined(TEST3) && defined(BOOST_MATH_RUN_MP_TESTS) - // Need at least one set of tests with expression templates turned on: - std::cout << "Testing 61 point approximation:\n"; - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#ifdef BOOST_HAS_FLOAT128 -#if LDBL_MANT_DIG < 100 // If we have too many digits in a long double, we get build errors due to a constexpr issue. - test_complex_lambert_w(); -#endif -#endif -#endif -} - -#else - -int main() { return 0; } - -#endif diff --git a/test/gauss_quadrature_test.cpp b/test/gauss_quadrature_test.cpp deleted file mode 100644 index 0c6431063c..0000000000 --- a/test/gauss_quadrature_test.cpp +++ /dev/null @@ -1,558 +0,0 @@ -// Copyright Nick Thompson, 2017 -// 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) - -#define BOOST_TEST_MODULE tanh_sinh_quadrature_test - -#include -//#include -#include -#include - -#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && !defined(BOOST_NO_SFINAE_EXPR) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4127) // Conditional expression is constant -#endif - -#if __has_include() -# include -#endif - -#if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) -# define TEST1 -# define TEST2 -# define TEST3 -#endif - -using std::expm1; -using std::atan; -using std::tan; -using std::log; -using std::log1p; -using std::asinh; -using std::atanh; -using std::sqrt; -using std::isnormal; -using std::abs; -using std::sinh; -using std::tanh; -using std::cosh; -using std::pow; -using std::exp; -using std::sin; -using std::cos; -using std::string; -using boost::math::quadrature::gauss; -using boost::math::constants::pi; -using boost::math::constants::half_pi; -using boost::math::constants::two_div_pi; -using boost::math::constants::two_pi; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::catalan; -using boost::math::constants::ln_two; -using boost::math::constants::root_two; -using boost::math::constants::root_two_pi; -using boost::math::constants::root_pi; -using boost::multiprecision::cpp_bin_float_quad; - -// -// Error rates depend only on the number of points in the approximation, not the type being tested, -// define all our expected errors here: -// - -enum -{ - test_ca_error_id, - test_ca_error_id_2, - test_three_quad_error_id, - test_three_quad_error_id_2, - test_integration_over_real_line_error_id, - test_right_limit_infinite_error_id, - test_left_limit_infinite_error_id -}; - -template -double expected_error(unsigned) -{ - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<7>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 1e-7; - case test_ca_error_id_2: - return 2e-5; - case test_three_quad_error_id: - return 1e-8; - case test_three_quad_error_id_2: - return 3.5e-3; - case test_integration_over_real_line_error_id: - return 6e-3; - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 1e-5; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<9>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 1e-7; - case test_ca_error_id_2: - return 2e-5; - case test_three_quad_error_id: - return 1e-8; - case test_three_quad_error_id_2: - return 3.5e-3; - case test_integration_over_real_line_error_id: - return 6e-3; - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 1e-5; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<10>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 1e-12; - case test_ca_error_id_2: - return 3e-6; - case test_three_quad_error_id: - return 2e-13; - case test_three_quad_error_id_2: - return 2e-3; - case test_integration_over_real_line_error_id: - return 6e-3; // doesn't get any better with more points! - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 5e-8; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<15>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 6e-20; - case test_ca_error_id_2: - return 3e-7; - case test_three_quad_error_id: - return 1e-19; - case test_three_quad_error_id_2: - return 6e-4; - case test_integration_over_real_line_error_id: - return 6e-3; // doesn't get any better with more points! - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 5e-11; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<20>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 1e-26; - case test_ca_error_id_2: - return 1e-7; - case test_three_quad_error_id: - return 3e-27; - case test_three_quad_error_id_2: - return 3e-4; - case test_integration_over_real_line_error_id: - return 5e-5; // doesn't get any better with more points! - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 1e-15; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<25>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 5e-33; - case test_ca_error_id_2: - return 1e-8; - case test_three_quad_error_id: - return 1e-32; - case test_three_quad_error_id_2: - return 3e-4; - case test_integration_over_real_line_error_id: - return 1e-14; - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 3e-19; - } - return 0; // placeholder, all tests will fail -} - -template <> -double expected_error<30>(unsigned id) -{ - switch (id) - { - case test_ca_error_id: - return 2e-34; - case test_ca_error_id_2: - return 5e-9; - case test_three_quad_error_id: - return 4e-34; - case test_three_quad_error_id_2: - return 1e-4; - case test_integration_over_real_line_error_id: - return 1e-16; - case test_right_limit_infinite_error_id: - case test_left_limit_infinite_error_id: - return 3e-23; - } - return 0; // placeholder, all tests will fail -} - - -template -void test_linear() -{ - std::cout << "Testing linear functions are integrated properly by gauss on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - auto f = [](const Real& x) - { - return 5*x + 7; - }; - Real L1; - Real Q = gauss::integrate(f, (Real) 0, (Real) 1, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, 9.5, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, 9.5, tol); - Q = gauss::integrate(f, (Real) 0, (Real) 0, &L1); - BOOST_CHECK_CLOSE(Q, 0, tol); - Q = gauss::integrate(f, (Real) 1, (Real) 0, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, -9.5, tol); -} - -template -void test_quadratic() -{ - std::cout << "Testing quadratic functions are integrated properly by Gaussian quadrature on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = boost::math::tools::epsilon() * 10; - - auto f = [](const Real& x) { return 5*x*x + 7*x + 12; }; - Real L1; - Real Q = gauss::integrate(f, 0, 1, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, (Real) 17 + half()*third(), tol); - BOOST_CHECK_CLOSE_FRACTION(L1, (Real) 17 + half()*third(), tol); -} - -// Examples taken from -//http://crd-legacy.lbl.gov/~dhbailey/dhbpapers/quadrature.pdf -template -void test_ca() -{ - std::cout << "Testing integration of C(a) on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_ca_error_id); - Real L1; - - auto f1 = [](const Real& x) { - if (x == 0) { - return static_cast(1); - } - return atan(x)/(x*(x*x + 1)) ; - }; - Real Q = gauss::integrate(f1, 0, 1, &L1); - Real Q_expected = pi()*ln_two()/8 + catalan()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - auto f2 = [](Real x)->Real { Real t0 = x*x + 1; Real t1 = sqrt(t0); return atan(t1)/(t0*t1); }; - Q = gauss::integrate(f2, 0 , 1, &L1); - Q_expected = pi()/4 - pi()/root_two() + 3*atan(root_two())/root_two(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - tol = expected_error(test_ca_error_id_2); - auto f5 = [](Real t)->Real { return t*t*log(t)/((t*t - 1)*(t*t*t*t + 1)); }; - Q = gauss::integrate(f5, 0 , 1); - Q_expected = pi()*pi()*(2 - root_two())/32; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); -} - -template -void test_three_quadrature_schemes_examples() -{ - std::cout << "Testing integral in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_three_quad_error_id); - Real Q; - Real Q_expected; - - // Example 1: - auto f1 = [](const Real& t) { return t*boost::math::log1p(t); }; - Q = gauss::integrate(f1, 0 , 1); - Q_expected = half()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - - // Example 2: - auto f2 = [](const Real& t) { return t*t*atan(t); }; - Q = gauss::integrate(f2, 0 , 1); - Q_expected = (pi() -2 + 2*ln_two())/12; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 2 * tol); - - // Example 3: - auto f3 = [](const Real& t) { return exp(t)*cos(t); }; - Q = gauss::integrate(f3, 0, half_pi()); - Q_expected = boost::math::expm1(half_pi())*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Example 4: - auto f4 = [](Real x)->Real { Real t0 = sqrt(x*x + 2); return atan(t0)/(t0*(x*x+1)); }; - Q = gauss::integrate(f4, 0 , 1); - Q_expected = 5*pi()*pi()/96; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - tol = expected_error(test_three_quad_error_id_2); - // Example 5: - auto f5 = [](const Real& t) { return sqrt(t)*log(t); }; - Q = gauss::integrate(f5, 0 , 1); - Q_expected = -4/ (Real) 9; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Example 6: - auto f6 = [](const Real& t) { return sqrt(1 - t*t); }; - Q = gauss::integrate(f6, 0 , 1); - Q_expected = pi()/4; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); -} - - -template -void test_integration_over_real_line() -{ - std::cout << "Testing integrals over entire real line in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_integration_over_real_line_error_id); - Real Q; - Real Q_expected; - Real L1; - - auto f1 = [](const Real& t) { return 1/(1+t*t);}; - Q = gauss::integrate(f1, -boost::math::tools::max_value(), boost::math::tools::max_value(), &L1); - Q_expected = pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); -} - -template -void test_right_limit_infinite() -{ - std::cout << "Testing right limit infinite for Gaussian quadrature in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_right_limit_infinite_error_id); - Real Q; - Real Q_expected; - Real L1; - - // Example 11: - auto f1 = [](const Real& t) { return 1/(1+t*t);}; - Q = gauss::integrate(f1, 0, boost::math::tools::max_value(), &L1); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); - - auto f4 = [](const Real& t) { return 1/(1+t*t); }; - Q = gauss::integrate(f4, 1, boost::math::tools::max_value(), &L1); - Q_expected = pi()/4; - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); -} - -template -void test_left_limit_infinite() -{ - std::cout << "Testing left limit infinite for Gaussian quadrature in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = expected_error(test_left_limit_infinite_error_id); - Real Q; - Real Q_expected; - - // Example 11: - auto f1 = [](const Real& t) { return 1/(1+t*t);}; - Q = gauss::integrate(f1, -boost::math::tools::max_value(), Real(0)); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); -} - -template -void test_complex_lambert_w() -{ - #ifndef BOOST_MATH_STANDALONE - std::cout << "Testing that complex-valued integrands are integrated correctly by Gaussian quadrature on type " << boost::typeindex::type_id().pretty_name() << "\n"; - typedef typename Complex::value_type Real; - Real tol = 10e-9; - using boost::math::constants::pi; - Complex z{2, 3}; - auto lw = [&z](Real v)->Complex { - using std::cos; - using std::sin; - using std::exp; - Real sinv = sin(v); - Real cosv = cos(v); - - Real cotv = cosv/sinv; - Real cscv = 1/sinv; - Real t = (1-v*cotv)*(1-v*cotv) + v*v; - Real x = v*cscv*exp(-v*cotv); - Complex den = z + x; - Complex num = t*(z/pi()); - Complex res = num/den; - return res; - }; - - //N[ProductLog[2+3*I], 150] - Complex Q = gauss::integrate(lw, (Real) 0, pi()); - BOOST_CHECK_CLOSE_FRACTION(Q.real(), BOOST_MATH_TEST_VALUE(Real, 1.0900765344857908463017778267816696498710210863535777805644), tol); - BOOST_CHECK_CLOSE_FRACTION(Q.imag(), BOOST_MATH_TEST_VALUE(Real, 0.5301397207748388014268602135741217419287056313827031782979), tol); - #endif -} - -BOOST_AUTO_TEST_CASE(gauss_quadrature_test) -{ - -#ifdef TEST1 - -#ifdef __STDCPP_FLOAT64_T__ - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#else - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#endif - -#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); -#endif -#endif -#ifdef TEST2 -#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - - test_linear(); - test_quadratic(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_integration_over_real_line(); - test_right_limit_infinite(); - test_left_limit_infinite(); - -#endif -#endif -#ifdef TEST3 -#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) - test_left_limit_infinite(); -#endif - test_complex_lambert_w>(); - test_complex_lambert_w>(); -#ifdef BOOST_HAS_FLOAT128 - test_left_limit_infinite(); - test_complex_lambert_w(); -#endif -#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) - test_complex_lambert_w(); -#endif -#endif -} - -#else - -int main() { return 0; } - -#endif diff --git a/test/git_issue_1006.cpp b/test/git_issue_1006.cpp index f8d6dfa239..26745b3e6c 100644 --- a/test/git_issue_1006.cpp +++ b/test/git_issue_1006.cpp @@ -3,12 +3,27 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// This has to precede the library headers: the optimizer may otherwise speculate +// a division that overflows, and raise a flag for a branch that is never taken. +#pragma STDC FENV_ACCESS ON + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + #include "math_unit_test.hpp" + +#ifndef BOOST_MATH_BUILD_MODULE #include #include -#include +#endif -#pragma STDC FENV_ACCESS ON +// FE_* macros require a textual /; on libstdc++ that wrapper pulls +// bits/c++config.h, which redefines std entities import std already provides. The +// fp-exception check is diagnostic, so it is a no-op in a module build. +#ifndef BOOST_MATH_BUILD_MODULE // Show and then clear the fenv flags void show_fpexcept_flags() @@ -40,6 +55,9 @@ void show_fpexcept_flags() std::feclearexcept(FE_ALL_EXCEPT); } +#else +void show_fpexcept_flags() {} +#endif int main() { diff --git a/test/git_issue_1120.cpp b/test/git_issue_1120.cpp index 3a74d9c218..71becc2665 100644 --- a/test/git_issue_1120.cpp +++ b/test/git_issue_1120.cpp @@ -19,8 +19,15 @@ #define BOOST_MATH_INSTRUMENT_SKEW_NORMAL_ITERATIONS -#include +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif #include "math_unit_test.hpp" std::uintmax_t global_iter_count; diff --git a/test/git_issue_1139.cpp b/test/git_issue_1139.cpp index 5bca58ec8e..e58fe98d4f 100644 --- a/test/git_issue_1139.cpp +++ b/test/git_issue_1139.cpp @@ -5,8 +5,13 @@ // // See: https://github.com/boostorg/math/issues/1139 -#include "math_unit_test.hpp" +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" int main() { diff --git a/test/git_issue_1175.cpp b/test/git_issue_1175.cpp index 9770acf537..b32933a57f 100644 --- a/test/git_issue_1175.cpp +++ b/test/git_issue_1175.cpp @@ -3,14 +3,22 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + #include "math_unit_test.hpp" + +#ifndef BOOST_MATH_BUILD_MODULE #include -#include +#endif using namespace std; using boost::math::beta_distribution; -int main(int argc, char* argv[]) +int main() { double a = 5.0; double b = 5.0; diff --git a/test/git_issue_1194.cpp b/test/git_issue_1194.cpp index 1c364a0c4d..577b8e06ae 100644 --- a/test/git_issue_1194.cpp +++ b/test/git_issue_1194.cpp @@ -3,9 +3,15 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#include "math_unit_test.hpp" +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#else +import boost.math; +#include +#endif + +#include "math_unit_test.hpp" int main() { diff --git a/test/git_issue_1203.cpp b/test/git_issue_1203.cpp new file mode 100644 index 0000000000..fd6d5b8eb6 --- /dev/null +++ b/test/git_issue_1203.cpp @@ -0,0 +1,176 @@ +// Copyright Nick Thompson, 2026 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See: https://github.com/boostorg/math/issues/1203 +// +// By default the quantile of a discrete distribution is the smallest k with +// cdf(k) >= p, and quantile(complement(d, q)) the smallest k with +// cdf(complement(d, k)) <= q, as in R, SciPy, Julia and Mathematica. The +// expected values below are from R 4.6.1 (qpois, qbinom, qnbinom, qgeom and +// qhyper); SciPy 1.18.1 and Distributions.jl 0.25.131 give the same values. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif +#include "math_unit_test.hpp" + +template +void check(const Dist& d, const double (&expected)[9]) +{ + const double p[] = { 0.01, 0.1, 0.25, 0.49, 0.5, 0.51, 0.75, 0.9, 0.99 }; + for (int i = 0; i < 9; ++i) + { + CHECK_EQUAL(quantile(d, p[i]), expected[i]); + // The upper quantiles are the lower ones in reverse: + CHECK_EQUAL(quantile(complement(d, p[i])), expected[8 - i]); + } +} + +int main() +{ + // The issue's example, which used to give one less for every p < 0.5: + { + const double expected[] = { + 2599, 2613, 2621, 2628, 2634, 2638, 2642, 2646, 2649, 2652, 2655, 2658, 2660, 2663, 2665, 2667, 2669, 2671, 2673, 2675, + 2677, 2679, 2681, 2682, 2684, 2685, 2687, 2689, 2690, 2692, 2693, 2695, 2696, 2697, 2699, 2700, 2702, 2703, 2704, 2706, + 2707, 2708, 2710, 2711, 2712, 2714, 2715, 2716, 2718, 2719, 2720, 2722, 2723, 2724, 2726, 2727, 2728, 2729, 2731, 2732, + 2734, 2735, 2736, 2738, 2739, 2740, 2742, 2743, 2745, 2746, 2748, 2749, 2751, 2753, 2754, 2756, 2758, 2759, 2761, 2763, + 2765, 2767, 2769, 2771, 2773, 2775, 2778, 2780, 2783, 2786, 2789, 2793, 2796, 2800, 2805, 2811, 2818, 2827, 2841 }; + boost::math::poisson_distribution d(2719.13); + for (int i = 1; i <= 99; ++i) + { + CHECK_EQUAL(quantile(d, i / 100.0), expected[i - 1]); + CHECK_EQUAL(quantile(complement(d, i / 100.0)), expected[99 - i]); + } + } + + { + const double expected[] = { 8, 11, 13, 15, 15, 15, 17, 19, 23 }; + check(boost::math::binomial_distribution(50, 0.3), expected); + } + { + const double expected[] = { 0, 3, 4, 7, 7, 7, 10, 13, 20 }; + check(boost::math::negative_binomial_distribution(5, 0.4), expected); + } + { + // The geometric used to return a real value whatever the policy: + const double expected[] = { 0, 0, 1, 3, 3, 3, 6, 10, 20 }; + check(boost::math::geometric_distribution(0.2), expected); + } + { + // 25 defective items in 60, sample 20: + const double expected[] = { 4, 6, 7, 8, 8, 8, 10, 11, 13 }; + check(boost::math::hypergeometric_distribution(25, 20, 60), expected); + } + + // p exactly on a step: quantile(cdf(k)) == k, and one ulp above gives k + 1. + { + boost::math::poisson_distribution d(2719.13); + boost::math::geometric_distribution g(0.2); + boost::math::hypergeometric_distribution h(25, 20, 60); + for (double k : { 2600.0, 2718.0, 2719.0, 2840.0 }) + { + CHECK_EQUAL(quantile(d, cdf(d, k)), k); + CHECK_EQUAL(quantile(d, std::nextafter(cdf(d, k), 1.0)), k + 1); + CHECK_EQUAL(quantile(complement(d, cdf(complement(d, k)))), k); + CHECK_EQUAL(quantile(complement(d, std::nextafter(cdf(complement(d, k)), 0.0))), k + 1); + } + for (double k : { 1.0, 4.0, 13.0 }) + { + CHECK_EQUAL(quantile(g, cdf(g, k)), k); + CHECK_EQUAL(quantile(complement(g, cdf(complement(g, k)))), k); + } + for (double k : { 4.0, 8.0, 12.0 }) + { + CHECK_EQUAL(quantile(h, cdf(h, k)), k); + CHECK_EQUAL(quantile(h, std::nextafter(cdf(h, k), 1.0)), k + 1); + CHECK_EQUAL(quantile(complement(h, cdf(complement(h, k)))), k); + CHECK_EQUAL(quantile(complement(h, std::nextafter(cdf(complement(h, k)), 0.0))), k + 1); + } + } + + // Near p = 1 the cdf can round to the same value at consecutive k. The + // smallest k with cdf(k) >= p is then the first of that run. + { + boost::math::poisson_distribution d(4.5); + for (double k = 20; k < 60; ++k) + { + const double p = cdf(d, k); + if ((p < 1) && (cdf(d, k - 1) < p)) + CHECK_EQUAL(quantile(d, p), k); + } + } + + // A long run: with a small success fraction the cdf rounds to the same + // value just below 1 for a thousand or so consecutive k. + { + using namespace boost::math::policies; + boost::math::geometric_distribution up(0.001); + boost::math::geometric_distribution>> down(0.001); + const double p = std::nextafter(1.0, 0.0); + const double ku = quantile(up, p); + CHECK_EQUAL(cdf(up, ku) >= p, true); + CHECK_EQUAL(cdf(up, ku - 1) < p, true); + const double kd = quantile(down, p); + CHECK_EQUAL(cdf(down, kd) <= p, true); + CHECK_EQUAL(cdf(down, kd + 1) > p, true); + } + + // q one ulp below cdf(complement(d, 0)): the answer is 1, not 0. + { + boost::math::geometric_distribution d(0.3); + const double q = std::nextafter(cdf(complement(d, 0.0)), 0.0); + CHECK_EQUAL(quantile(complement(d, q)), 1.0); + const double p = std::nextafter(cdf(d, 0.0), 1.0); + CHECK_EQUAL(quantile(d, p), 1.0); + } + + // The Bernoulli has its own quantile, with the same definition: + for (double sf : { 0.25, 0.5, 0.75 }) + { + boost::math::bernoulli_distribution d(sf); + for (double k : { 0.0, 1.0 }) + { + CHECK_EQUAL(quantile(d, cdf(d, k)), k); + CHECK_EQUAL(quantile(complement(d, cdf(complement(d, k)))), k); + } + // P(X > 0) == sf, so q >= sf gives 0 and q < sf gives 1: + CHECK_EQUAL(quantile(complement(d, std::nextafter(sf, 1.0))), 0.0); + CHECK_EQUAL(quantile(complement(d, std::nextafter(sf, 0.0))), 1.0); + CHECK_EQUAL(quantile(d, std::nextafter(1 - sf, 1.0)), 1.0); + } + +#ifndef BOOST_NO_EXCEPTIONS + // Running out of iterations while settling the result is an error, not a + // silently returned guess: + { + using namespace boost::math::policies; + boost::math::geometric_distribution>> d(0.5); + bool thrown = false; + try + { + (void)quantile(d, 0.75); // Has to look at k = 0 as well as k = 1. + } + catch (const boost::math::evaluation_error&) + { + thrown = true; + } + CHECK_EQUAL(thrown, true); + } +#endif + + return boost::math::test::report_errors(); +} diff --git a/test/git_issue_1249.cpp b/test/git_issue_1249.cpp index 5e0fa90d2e..1b94f64c97 100644 --- a/test/git_issue_1249.cpp +++ b/test/git_issue_1249.cpp @@ -32,7 +32,7 @@ struct test_lower return tgamma_lower(a, x, c_policy()); } - T expected(T a) const + T expected(T /*a*/) const { return T(0.0); } diff --git a/test/git_issue_1255.cpp b/test/git_issue_1255.cpp index 133986a2d6..333b3e0f99 100644 --- a/test/git_issue_1255.cpp +++ b/test/git_issue_1255.cpp @@ -5,11 +5,27 @@ // See also: https://godbolt.org/z/nhMsKb8Yr +#ifndef BOOST_MATH_STANDALONE #include -#include +#endif +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifdef BOOST_MATH_STANDALONE +// Standalone/module builds cannot use Boost.Core; map lightweight_test onto math_unit_test.hpp. +#include "math_unit_test.hpp" +#define BOOST_TEST(expr) CHECK_TRUE((expr)) +namespace boost { inline int report_errors() { return ::boost::math::test::report_errors(); } } +#endif + +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif namespace local { diff --git a/test/git_issue_1294.cpp b/test/git_issue_1294.cpp index 047a8ea7b3..3fd4c3f6b0 100644 --- a/test/git_issue_1294.cpp +++ b/test/git_issue_1294.cpp @@ -6,7 +6,12 @@ // // See: https://github.com/boostorg/math/issues/1294 +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + #include "math_unit_test.hpp" int main() diff --git a/test/git_issue_1419.cpp b/test/git_issue_1419.cpp new file mode 100644 index 0000000000..3b9e537c4e --- /dev/null +++ b/test/git_issue_1419.cpp @@ -0,0 +1,26 @@ +// Copyright Matt Borland 2026 +// 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) +// +// See: https://github.com/boostorg/math/issues/1419 + +#include +#include +#include +#include "math_unit_test.hpp" + +int main() +{ + std::vector v = {3, 2, 1, 2}; + const auto modes_unsorted = boost::math::statistics::mode(v); + + std::sort(v.begin(), v.end()); + const auto modes_sorted = boost::math::statistics::mode(v); + + CHECK_EQUAL(modes_unsorted.size(), modes_sorted.size()); + CHECK_EQUAL(modes_unsorted.front(), modes_sorted.front()); + CHECK_EQUAL(modes_unsorted.front(), 2); + + return boost::math::test::report_errors(); +} diff --git a/test/git_issue_1421.cpp b/test/git_issue_1421.cpp new file mode 100644 index 0000000000..5940e13b1e --- /dev/null +++ b/test/git_issue_1421.cpp @@ -0,0 +1,22 @@ +// Copyright Matt Borland 2026 +// 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) +// +// See: https://github.com/boostorg/math/issues/1421 + +#include +#include +#include + +int main() +{ + std::istringstream iss {"1 2 3 4 5 6 7 8 9"}; + std::istream_iterator first {iss}; + const std::istream_iterator last {}; + + // std::istream_iterator is an input iterator, so this must not compile. + const auto m = boost::math::statistics::mean(first, last); + + return static_cast(m); +} diff --git a/test/git_issue_705.cpp b/test/git_issue_705.cpp index 4b205421a7..e72b22660f 100644 --- a/test/git_issue_705.cpp +++ b/test/git_issue_705.cpp @@ -5,25 +5,38 @@ #define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error -#include "math_unit_test.hpp" -#include +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif +#include "math_unit_test.hpp" template void test() { CHECK_EQUAL(std::pow(T(0), T(2)) - 1, boost::math::powm1(T(0), T(2))); - CHECK_EQUAL(std::pow(T(0), T(-2)) - 1, boost::math::powm1(T(0), T(-2))); CHECK_EQUAL(std::pow(T(0), T(0.1)) - 1, boost::math::powm1(T(0), T(0.1))); + + // These return infinity only under the ignore_error overflow policy; the macro + // cannot reach the precompiled module (which throws), so keep them textual. + #ifndef BOOST_MATH_BUILD_MODULE + CHECK_EQUAL(std::pow(T(0), T(-2)) - 1, boost::math::powm1(T(0), T(-2))); CHECK_EQUAL(std::pow(T(0), T(-0.1)) - 1, boost::math::powm1(T(0), T(-0.1))); + #endif } int main() { test(); test(); - - #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + + // long double is excluded from the module build (double and float only). + #if !defined(BOOST_MATH_BUILD_MODULE) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) test(); #endif diff --git a/test/git_issue_800.cpp b/test/git_issue_800.cpp index 64d3f012ce..a5980d3034 100644 --- a/test/git_issue_800.cpp +++ b/test/git_issue_800.cpp @@ -3,8 +3,13 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#include "math_unit_test.hpp" +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" template void test() diff --git a/test/git_issue_810.cpp b/test/git_issue_810.cpp index 07748a7fdc..c017d371b5 100644 --- a/test/git_issue_810.cpp +++ b/test/git_issue_810.cpp @@ -3,9 +3,17 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + #include "math_unit_test.hpp" + +#ifndef BOOST_MATH_BUILD_MODULE #include -#include +#endif template void test() @@ -20,7 +28,6 @@ void test() int main(void) { test(); - test(); return boost::math::test::report_errors(); } diff --git a/test/git_issue_826.cpp b/test/git_issue_826.cpp index dbe0945e03..01923440ac 100644 --- a/test/git_issue_826.cpp +++ b/test/git_issue_826.cpp @@ -3,29 +3,48 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) -#include -#include +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif + +// FE_ALL_EXCEPT / FE_OVERFLOW come from the pure-C header, which is safe to +// include textually alongside import std. feclearexcept / fetestexcept are the +// global functions it declares (the std:: overloads would need , which +// must not be included in module mode). +#include + #include "math_unit_test.hpp" #pragma STDC FENV_ACCESS ON -int main() { +int main() +{ constexpr double q {0.999995}; constexpr double a {2}; constexpr double b {99999}; - std::feclearexcept(FE_ALL_EXCEPT); + feclearexcept(FE_ALL_EXCEPT); boost::math::beta_distribution d {a, b}; const auto ans = boost::math::quantile(d, q); - if(std::fetestexcept(FE_OVERFLOW)) { + if (fetestexcept(FE_OVERFLOW)) + { std::cout << "overflow reported" << std::endl; - } else { + } + else + { std::cout << "overflow not reported" << std::endl; } std::cout << std::setprecision(16) << "Ans is: " << ans << std::endl; - return 0; CHECK_ULP_CLOSE(ans, 0.000149761910560502, 1); + + return boost::math::test::report_errors(); } // overflow reported // Ans is: 0.000149761910560502 diff --git a/test/git_issue_898.cpp b/test/git_issue_898.cpp index 4316dfbd4d..79e38ec53a 100644 --- a/test/git_issue_898.cpp +++ b/test/git_issue_898.cpp @@ -4,10 +4,17 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#else +import boost.math; +#endif + #include "math_unit_test.hpp" // numerically evaluate the integral for Stefan-Boltzmann Law from Planck's Law diff --git a/test/git_issue_935.cpp b/test/git_issue_935.cpp new file mode 100644 index 0000000000..418d6a13a9 --- /dev/null +++ b/test/git_issue_935.cpp @@ -0,0 +1,174 @@ +// Copyright Nick Thompson, 2026 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See: https://github.com/boostorg/math/issues/935 +// See: https://github.com/scipy/scipy/pull/17432 +// +// The integer quantiles of the discrete distributions are found by solving +// the continuous cdf(x) = p and rounding. When p is within a few ulps of +// cdf(k) the continuous root is only known to within noise, and the rounded +// result used to be off by one. Check that quantile(cdf(k)) round-trips, +// with p nudged a few ulps either side of cdf(k), for every integer rounding +// policy, both tails, and each discrete distribution. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif +#include "math_unit_test.hpp" + +using namespace boost::math::policies; + +enum class rounding { up, down, outwards, inwards, nearest }; + +// The answer each policy should give, from G[k] = cdf(k) - p (or +// p - cdf(complement(d, k)) for the complement), which increases with k. +// Returns -1 if the answer may lie beyond the tabulated k. +long expected_quantile(const std::vector& G, rounding r, double lower_p) +{ + const bool up = (r == rounding::up) || (r == rounding::outwards && lower_p >= 0.5) || (r == rounding::inwards && lower_p < 0.5); + const long n = static_cast(G.size()); + if (G[0] >= 0) + return 0; + if (up) + { + // Smallest k with cdf(k) >= p: + long k = 0; + while ((k < n) && (G[k] < 0)) + ++k; + return k == n ? -1 : k; + } + // Largest k with cdf(k) <= p: + long k = n - 1; + while ((k >= 0) && (G[k] > 0)) + --k; + return k == n - 1 ? -1 : k; +} + +template +void check_round_trips(const Dist& d, rounding r) +{ + std::vector lower, upper; + for (int k = 0; (k < 400) && (k <= support(d).second); ++k) + { + lower.push_back(cdf(d, static_cast(k))); + upper.push_back(cdf(complement(d, static_cast(k)))); + if (lower.back() > 0.9999) + break; + } + std::vector G(lower.size()); + for (int comp = 0; comp < 2; ++comp) + { + for (std::size_t k = 0; k < lower.size(); ++k) + { + for (int ulps : { 0, -1, 1, -10, 10 }) + { + double p = comp ? upper[k] : lower[k]; + for (int i = 0; i < std::abs(ulps); ++i) + p = std::nextafter(p, ulps < 0 ? 0.0 : 1.0); + if ((p <= 0) || (p >= 1)) + continue; + for (std::size_t i = 0; i < lower.size(); ++i) + G[i] = comp ? p - upper[i] : lower[i] - p; + const double q = comp ? quantile(complement(d, p)) : quantile(d, p); + if (r == rounding::nearest) + { + // Whatever "nearest" means for this distribution, it is round + // up's answer or the one below it, and round up's when p is + // exactly on a step: + const long up = expected_quantile(G, rounding::up, 0.5); + if (up < 0) + continue; + if ((G[up] == 0) || (up == 0)) + CHECK_EQUAL(q, static_cast(up)); + else if ((q != up) && (q != up - 1)) + CHECK_EQUAL(q, static_cast(up)); + continue; + } + const long expected = expected_quantile(G, r, comp ? 1 - p : p); + if (expected < 0) + continue; + CHECK_EQUAL(q, static_cast(expected)); + } + } + } +} + +template +void test_policy(rounding r) +{ + for (double successes : { 0.5, 3.0, 5.0, 17.5 }) + for (double p : { 0.05, 0.5, 0.9 }) + check_round_trips(boost::math::negative_binomial_distribution(successes, p), r); + // 5.5: the binomial accepts fractional trials, so the support need not + // end on an integer. + for (double trials : { 5.0, 5.5, 100.0 }) + for (double p : { 0.1, 0.5, 0.9 }) + check_round_trips(boost::math::binomial_distribution(trials, p), r); + for (double mean : { 0.1, 4.5, 30.0 }) + check_round_trips(boost::math::poisson_distribution(mean), r); + // These two find the quantile without inverse_discrete_quantile (in + // closed form, and by summing the pdf), but round the same way: + for (double p : { 0.05, 0.5, 0.9 }) + check_round_trips(boost::math::geometric_distribution(p), r); + check_round_trips(boost::math::hypergeometric_distribution(25, 20, 60), r); + check_round_trips(boost::math::hypergeometric_distribution(300, 150, 1000), r); +} + +int main() +{ + // The case reported from SciPy: cdf(6) nudged down by 10 ulps must give 6. + using scipy_policy = policy>; + boost::math::negative_binomial_distribution nb(5.0, 0.5); + double c = cdf(nb, 6.0); + c -= 10 * (std::nextafter(c, 1.0) - c); + CHECK_EQUAL(quantile(nb, c), 6.0); + + // With fractional trials, p above cdf(floor(trials)) must not evaluate the + // cdf outside the support: round down gives the last integer in it, round + // up the next integer. + { + boost::math::binomial_distribution>> down(5.5, 0.5); + boost::math::binomial_distribution>> up(5.5, 0.5); + const double p = (cdf(down, 5.0) + 1) / 2; + CHECK_EQUAL(quantile(down, p), 5.0); + CHECK_EQUAL(quantile(complement(down, 1 - p)), 5.0); + CHECK_EQUAL(quantile(up, p), 6.0); + CHECK_EQUAL(quantile(complement(up, 1 - p)), 6.0); + } + + test_policy>>(rounding::up); + test_policy>>(rounding::down); + test_policy>>(rounding::outwards); + test_policy>>(rounding::inwards); + test_policy>>(rounding::nearest); + + // float is evaluated in double, but cdf() is rounded to float, and the + // hypergeometric quantile must allow for that: + { + using namespace boost::math; + hypergeometric_distribution up(25, 20, 60); + hypergeometric_distribution>> down(25, 20, 60); + for (float k = 1; k < 15; ++k) + { + CHECK_EQUAL(quantile(up, cdf(up, k)), k); + CHECK_EQUAL(quantile(complement(up, cdf(complement(up, k)))), k); + CHECK_EQUAL(quantile(down, cdf(down, k)), k); + CHECK_EQUAL(quantile(complement(down, cdf(complement(down, k)))), k); + } + } + + return boost::math::test::report_errors(); +} diff --git a/test/git_issue_961.cpp b/test/git_issue_961.cpp index 7594dcd6fc..dd192c8fee 100644 --- a/test/git_issue_961.cpp +++ b/test/git_issue_961.cpp @@ -67,7 +67,7 @@ int test() return 0; } -int main(int argc, char* argv[]) +int main() { using namespace boost::math::policies; if (test>()) diff --git a/test/issue893.cpp b/test/issue893.cpp index 4464df8846..ba5da746b9 100644 --- a/test/issue893.cpp +++ b/test/issue893.cpp @@ -4,11 +4,10 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_TEST_MODULE issue893 #include #include -#include +#include "math_unit_test.hpp" #include #include @@ -16,10 +15,10 @@ using boost::math::quadrature::tanh_sinh; #include -BOOST_AUTO_TEST_CASE(issue893) { +void issue893() { typedef boost::multiprecision::cpp_bin_float_100 real; - auto fun = [](real x) -> real { + auto fun = [](real /*x*/) -> real { return 1.0; }; @@ -28,5 +27,11 @@ BOOST_AUTO_TEST_CASE(issue893) { const real b = -0.9999995515592481132478776023609116290187750667053638330158486516399489191171270344610533516275817076; real y = integrator.integrate(fun, -b, a); - BOOST_CHECK(y < 1); + CHECK_TRUE(y < 1); +} + +int main() +{ + issue893(); + return boost::math::test::report_errors(); } diff --git a/test/jso_test.cpp b/test/jso_test.cpp deleted file mode 100644 index df57baba9f..0000000000 --- a/test/jso_test.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Nick Thompson, 2024 - * 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) - */ - -#include "math_unit_test.hpp" -#include "test_functions_for_optimization.hpp" -#include -#include -#include - -using boost::math::optimization::jso; -using boost::math::optimization::jso_parameters; -using boost::math::optimization::detail::weighted_lehmer_mean; - -void test_weighted_lehmer_mean() { - size_t n = 50; - std::vector weights(n, 1.0); - std::vector values(n, 2.5); - // Technically, this is not a fully general weighted Lehmer mean, - // but just a weighted contraharmonic mean. - // So we have a few more invariants available to us: - CHECK_ULP_CLOSE(2.5, weighted_lehmer_mean(values, weights), n); - std::mt19937_64 gen(12345); - std::uniform_real_distribution unif(std::numeric_limits::epsilon(),1); - for (size_t i = 0; i < n; ++i) { - weights[i] = unif(gen); - values[i] = unif(gen); - } - auto mean = weighted_lehmer_mean(values, weights); - CHECK_LE(mean, 1.0); - CHECK_LE(std::numeric_limits::epsilon(), mean); -} - -template void test_ackley() { - std::cout << "Testing jSO on Ackley function . . .\n"; - using ArgType = std::array; - auto jso_params = jso_parameters(); - jso_params.lower_bounds = {-5, -5}; - jso_params.upper_bounds = {5, 5}; - - std::mt19937_64 gen(12345); - auto local_minima = jso(ackley, jso_params, gen); - CHECK_LE(std::abs(local_minima[0]), 10 * std::numeric_limits::epsilon()); - CHECK_LE(std::abs(local_minima[1]), 10 * std::numeric_limits::epsilon()); - - // Does it work with a lambda? - auto ack = [](std::array const &x) { return ackley(x); }; - local_minima = jso(ack, jso_params, gen); - CHECK_LE(std::abs(local_minima[0]), 10 * std::numeric_limits::epsilon()); - CHECK_LE(std::abs(local_minima[1]), 10 * std::numeric_limits::epsilon()); - - // Test that if an intial guess is the exact solution, the returned solution is the exact solution: - std::array initial_guess{0, 0}; - jso_params.initial_guess = &initial_guess; - local_minima = jso(ack, jso_params, gen); - - using std::fabs; - CHECK_LE(fabs(local_minima[0]), 128 * boost::math::tools::epsilon()); - CHECK_LE(fabs(local_minima[1]), 128 * boost::math::tools::epsilon()); -} - -template void test_rosenbrock_saddle() { - std::cout << "Testing jSO on Rosenbrock saddle . . .\n"; - using ArgType = std::array; - jso_parameters jso_params { }; - jso_params.lower_bounds = {0.5, 0.5}; - jso_params.upper_bounds = {2.048, 2.048}; - std::mt19937_64 gen(234568); - auto local_minima = jso(rosenbrock_saddle, jso_params, gen); - - CHECK_ABSOLUTE_ERROR(Real(1), local_minima[0], 10 * std::numeric_limits::epsilon()); - CHECK_ABSOLUTE_ERROR(Real(1), local_minima[1], 10 * std::numeric_limits::epsilon()); - - // Does cancellation work? - std::atomic cancel = true; - gen.seed(12345); - local_minima = - jso(rosenbrock_saddle, jso_params, gen, std::numeric_limits::quiet_NaN(), &cancel); - CHECK_GE(std::abs(local_minima[0] - Real(1)), std::sqrt(std::numeric_limits::epsilon())); -} - - - -template void test_rastrigin() { - std::cout << "Testing jSO on Rastrigin function (global minimum = (0,0,...,0))\n"; - using ArgType = std::vector; - auto jso_params = jso_parameters(); - jso_params.lower_bounds.resize(3, static_cast(-5.12)); - jso_params.upper_bounds.resize(3, static_cast(5.12)); - jso_params.initial_population_size = 5000; - jso_params.max_function_evaluations = 1000000; - std::mt19937_64 gen(34567); - - // By definition, the value of the function which a target value is provided must be <= target_value. - Real target_value = 1e-3; - auto local_minima = jso(rastrigin, jso_params, gen, target_value); - CHECK_LE(rastrigin(local_minima), target_value); -} - -// Tests NaN return types and return type != input type: -void test_sphere() { - std::cout << "Testing jSO on sphere . . .\n"; - using ArgType = std::vector; - auto jso_params = jso_parameters(); - jso_params.lower_bounds.resize(8, -1); - jso_params.upper_bounds.resize(8, 1); - std::mt19937_64 gen(56789); - auto local_minima = jso(sphere, jso_params, gen); - for (auto x : local_minima) { - CHECK_ABSOLUTE_ERROR(0.0f, x, 2e-4f); - } -} - -template -void test_three_hump_camel() { - std::cout << "Testing jSO on three hump camel . . .\n"; - using ArgType = std::array; - auto jso_params = jso_parameters(); - jso_params.lower_bounds[0] = -5.0; - jso_params.lower_bounds[1] = -5.0; - jso_params.upper_bounds[0] = 5.0; - jso_params.upper_bounds[1] = 5.0; - std::mt19937_64 gen(56789); - auto local_minima = jso(three_hump_camel, jso_params, gen); - for (auto x : local_minima) { - CHECK_ABSOLUTE_ERROR(0.0f, x, 2e-4f); - } -} - -template -void test_beale() { - std::cout << "Testing jSO on the Beale function . . .\n"; - using ArgType = std::array; - auto jso_params = jso_parameters(); - jso_params.lower_bounds[0] = -5.0; - jso_params.lower_bounds[1] = -5.0; - jso_params.upper_bounds[0]= 5.0; - jso_params.upper_bounds[1]= 5.0; - std::mt19937_64 gen(56789); - auto local_minima = jso(beale, jso_params, gen); - CHECK_ABSOLUTE_ERROR(Real(3), local_minima[0], Real(2e-4)); - CHECK_ABSOLUTE_ERROR(Real(1)/Real(2), local_minima[1], Real(2e-4)); -} - -int main() { - test_ackley(); - test_ackley(); - test_rosenbrock_saddle(); - test_rastrigin(); - test_three_hump_camel(); - test_beale(); - test_sphere(); - test_weighted_lehmer_mean(); - return boost::math::test::report_errors(); -} diff --git a/test/lanczos_smoothing_test.cpp b/test/lanczos_smoothing_test.cpp deleted file mode 100644 index f2e15a24af..0000000000 --- a/test/lanczos_smoothing_test.cpp +++ /dev/null @@ -1,708 +0,0 @@ -/* - * Copyright Nick Thompson, 2019 - * 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) - */ -#define BOOST_TEST_MODULE lanczos_smoothing_test - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // for float_distance -#include - -using std::abs; -using std::pow; -using std::sqrt; -using std::sin; -using boost::math::constants::two_pi; -using boost::multiprecision::cpp_bin_float_50; -using boost::multiprecision::cpp_bin_float_100; -using boost::math::differentiation::discrete_lanczos_derivative; -using boost::math::differentiation::detail::discrete_legendre; -using boost::math::differentiation::detail::interior_velocity_filter; -using boost::math::differentiation::detail::boundary_velocity_filter; -using boost::math::tools::summation_condition_number; - -template -void test_dlp_norms() -{ - std::cout << "Testing Discrete Legendre Polynomial norms on type " << typeid(Real).name() << "\n"; - Real tol = std::numeric_limits::epsilon(); - auto dlp = discrete_legendre(1, Real(0)); - BOOST_CHECK_CLOSE_FRACTION(dlp.norm_sq(0), 3, tol); - BOOST_CHECK_CLOSE_FRACTION(dlp.norm_sq(1), 2, tol); - dlp = discrete_legendre(2, Real(0)); - BOOST_CHECK_CLOSE_FRACTION(dlp.norm_sq(0), Real(5)/Real(2), tol); - BOOST_CHECK_CLOSE_FRACTION(dlp.norm_sq(1), Real(5)/Real(4), tol); - BOOST_CHECK_CLOSE_FRACTION(dlp.norm_sq(2), Real(3*3*7)/Real(pow(2,6)), 2*tol); - dlp = discrete_legendre(200, Real(0)); - for(size_t r = 0; r < 10; ++r) - { - Real calc = dlp.norm_sq(r); - Real expected = Real(2)/Real(2*r+1); - // As long as r << n, ||q_r||^2 -> 2/(2r+1) as n->infty - BOOST_CHECK_CLOSE_FRACTION(calc, expected, 0.05); - } - -} - -template -void test_dlp_evaluation() -{ - std::cout << "Testing evaluation of Discrete Legendre polynomials on type " << typeid(Real).name() << "\n"; - Real tol = std::numeric_limits::epsilon(); - size_t n = 25; - Real x = 0.72; - auto dlp = discrete_legendre(n, x); - Real q0 = dlp(x, 0); - BOOST_TEST(q0 == 1); - Real q1 = dlp(x, 1); - BOOST_TEST(q1 == x); - Real q2 = dlp(x, 2); - int N = 2*n+1; - Real expected = 0.5*(3*x*x - Real(N*N - 1)/Real(4*n*n)); - BOOST_CHECK_CLOSE_FRACTION(q2, expected, tol); - Real q3 = dlp(x, 3); - expected = (x/3)*(5*expected - (Real(N*N - 4))/(2*n*n)); - BOOST_CHECK_CLOSE_FRACTION(q3, expected, 2*tol); - - // q_r(x) is even for even r, and odd for odd r: - for (size_t n = 8; n < 22; ++n) - { - dlp = discrete_legendre(n, x); - for(size_t r = 2; r <= n; ++r) - { - if (r & 1) - { - Real q1 = dlp(x, r); - Real q2 = -dlp(-x, r); - BOOST_CHECK_CLOSE_FRACTION(q1, q2, tol); - } - else - { - Real q1 = dlp(x, r); - Real q2 = dlp(-x, r); - BOOST_CHECK_CLOSE_FRACTION(q1, q2, tol); - } - - Real l2_sq = 0; - for (int j = -(int)n; j <= (int) n; ++j) - { - Real y = Real(j)/Real(n); - Real term = dlp(y, r); - l2_sq += term*term; - } - l2_sq /= n; - Real l2_sq_expected = dlp.norm_sq(r); - BOOST_CHECK_CLOSE_FRACTION(l2_sq, l2_sq_expected, 20*tol); - } - } -} - -template -void test_dlp_next() -{ - std::cout << "Testing Discrete Legendre polynomial 'next' function on type " << typeid(Real).name() << "\n"; - Real tol = std::numeric_limits::epsilon(); - - for(size_t n = 2; n < 20; ++n) - { - for(Real x = -1; x <= 1; x += 0.1) - { - auto dlp = discrete_legendre(n, x); - for (size_t k = 2; k < n; ++k) - { - BOOST_CHECK_CLOSE(dlp.next(), dlp(x, k), tol); - } - - dlp = discrete_legendre(n, x); - for (size_t k = 2; k < n; ++k) - { - BOOST_CHECK_CLOSE(dlp.next_prime(), dlp.prime(x, k), tol); - } - } - } -} - - -template -void test_dlp_derivatives() -{ - std::cout << "Testing Discrete Legendre polynomial derivatives on type " << typeid(Real).name() << "\n"; - Real tol = 10*std::numeric_limits::epsilon(); - int n = 25; - Real x = 0.72; - auto dlp = discrete_legendre(n, x); - Real q0p = dlp.prime(x, 0); - BOOST_TEST(q0p == 0); - Real q1p = dlp.prime(x, 1); - BOOST_TEST(q1p == 1); - Real q2p = dlp.prime(x, 2); - Real expected = 3*x; - BOOST_CHECK_CLOSE_FRACTION(q2p, expected, tol); -} - -template -void test_dlp_second_derivative() -{ - std::cout << "Testing Discrete Legendre polynomial derivatives on type " << typeid(Real).name() << "\n"; - int n = 25; - Real x = Real(1)/Real(3); - auto dlp = discrete_legendre(n, x); - Real q2pp = dlp.next_dbl_prime(); - BOOST_TEST(q2pp == 3); -} - - -template -void test_interior_velocity_filter() -{ - using boost::math::constants::half; - std::cout << "Testing interior filter on type " << typeid(Real).name() << "\n"; - Real tol = std::numeric_limits::epsilon(); - for(int n = 1; n < 10; ++n) - { - for (int p = 1; p < n; p += 2) - { - auto f = interior_velocity_filter(n,p); - // Since we only store half the filter coefficients, - // we need to reindex the moment sums: - auto cond = summation_condition_number(0); - for (size_t j = 0; j < f.size(); ++j) - { - cond += j*f[j]; - } - BOOST_CHECK_CLOSE_FRACTION(cond.sum(), half(), 2*cond()*tol); - - for (int l = 3; l <= p; l += 2) - { - cond = summation_condition_number(0); - for (size_t j = 0; j < f.size() - 1; ++j) - { - cond += pow(Real(j), l)*f[j]; - } - Real expected = -pow(Real(f.size() - 1), l)*f[f.size()-1]; - BOOST_CHECK_CLOSE_FRACTION(expected, cond.sum(), 15*cond()*tol); - } - //std::cout << "(n,p) = (" << n << "," << p << ") = {"; - //for (auto & x : f) - //{ - // std::cout << x << ", "; - //} - //std::cout << "}\n"; - } - } -} - -template -void test_interior_lanczos() -{ - std::cout << "Testing interior Lanczos on type " << typeid(Real).name() << "\n"; - Real tol = std::numeric_limits::epsilon(); - std::vector v(500); - std::fill(v.begin(), v.end(), 7); - - for (size_t n = 1; n < 10; ++n) - { - for (size_t p = 2; p < 2*n; p += 2) - { - auto dld = discrete_lanczos_derivative(Real(0.1), n, p); - for (size_t m = n; m < v.size() - n; ++m) - { - Real dvdt = dld(v, m); - BOOST_CHECK_SMALL(dvdt, tol); - } - auto dvdt = dld(v); - for (size_t m = n; m < v.size() - n; ++m) - { - BOOST_CHECK_SMALL(dvdt[m], tol); - } - } - } - - - for(size_t i = 0; i < v.size(); ++i) - { - v[i] = 7*i+8; - } - - for (size_t n = 1; n < 10; ++n) - { - for (size_t p = 2; p < 2*n; p += 2) - { - auto dld = discrete_lanczos_derivative(Real(1), n, p); - for (size_t m = n; m < v.size() - n; ++m) - { - Real dvdt = dld(v, m); - BOOST_CHECK_CLOSE_FRACTION(dvdt, 7, 2000*tol); - } - auto dvdt = dld(v); - for (size_t m = n; m < v.size() - n; ++m) - { - BOOST_CHECK_CLOSE_FRACTION(dvdt[m], 7, 2000*tol); - } - } - } - - //std::random_device rd{}; - //auto seed = rd(); - //std::cout << "Seed = " << seed << "\n"; - std::mt19937 gen(4172378669); - std::normal_distribution<> dis{0, 0.01}; - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = 7*i+8 + dis(gen); - } - - for (size_t n = 1; n < 10; ++n) - { - for (size_t p = 2; p < 2*n; p += 2) - { - auto dld = discrete_lanczos_derivative(Real(1), n, p); - for (size_t m = n; m < v.size() - n; ++m) - { - BOOST_CHECK_CLOSE_FRACTION(dld(v, m), Real(7), Real(0.0042)); - } - } - } - - - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = 15*i*i + 7*i+8 + dis(gen); - } - - for (size_t n = 1; n < 10; ++n) - { - for (size_t p = 2; p < 2*n; p += 2) - { - auto dld = discrete_lanczos_derivative(Real(1), n, p); - for (size_t m = n; m < v.size() - n; ++m) - { - BOOST_CHECK_CLOSE_FRACTION(dld(v,m), Real(30*m + 7), Real(0.00008)); - } - } - } - - std::normal_distribution<> dis1{0, 0.0001}; - Real omega = Real(1)/Real(16); - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = sin(i*omega) + dis1(gen); - } - - for (size_t n = 10; n < 20; ++n) - { - for (size_t p = 3; p < 100 && p < n/2; p += 2) - { - auto dld = discrete_lanczos_derivative(Real(1), n, p); - - for (size_t m = n; m < v.size() - n && m < n + 10; ++m) - { - BOOST_CHECK_CLOSE_FRACTION(dld(v,m), omega*cos(omega*m), Real(0.03)); - } - } - } -} - -template -void test_boundary_velocity_filters() -{ - std::cout << "Testing boundary filters on type " << typeid(Real).name() << "\n"; - Real tol = std::numeric_limits::epsilon(); - for(int n = 1; n < 5; ++n) - { - for (int p = 1; p < 2*n+1; ++p) - { - for (int s = -n; s <= n; ++s) - { - auto f = boundary_velocity_filter(n, p, s); - // Sum is zero: - auto cond = summation_condition_number(0); - for (size_t i = 0; i < f.size() - 1; ++i) - { - cond += f[i]; - } - - BOOST_CHECK_CLOSE_FRACTION(cond.sum(), -f[f.size()-1], 6*cond()*tol); - - cond = summation_condition_number(0); - for (size_t k = 0; k < f.size(); ++k) - { - Real j = Real(k) - Real(n); - // note the shifted index here: - cond += (j-s)*f[k]; - } - BOOST_CHECK_CLOSE_FRACTION(cond.sum(), 1, 6*cond()*tol); - - - for (int l = 2; l <= p; ++l) - { - cond = summation_condition_number(0); - for (size_t k = 0; k < f.size() - 1; ++k) - { - Real j = Real(k) - Real(n); - // The condition number of this sum is infinite! - // No need to get to worked up about the tolerance. - cond += pow(j-s, l)*f[k]; - } - - Real expected = -pow(Real(f.size()-1) - Real(n) - Real(s), l)*f[f.size()-1]; - if (expected == 0) - { - BOOST_CHECK_SMALL(cond.sum(), cond()*tol); - } - else - { - BOOST_CHECK_CLOSE_FRACTION(expected, cond.sum(), 200*cond()*tol); - } - } - - //std::cout << "(n,p,s) = ("<< n << ", " << p << "," << s << ") = {"; - //for (auto & x : f) - //{ - // std::cout << x << ", "; - //} - //std::cout << "}\n";*/ - } - } - } -} - -template -void test_boundary_lanczos() -{ - std::cout << "Testing Lanczos boundary on type " << typeid(Real).name() << "\n"; - Real tol = std::numeric_limits::epsilon(); - std::vector v(500, 7); - - for (size_t n = 1; n < 10; ++n) - { - for (size_t p = 2; p < 2*n; ++p) - { - auto lsd = discrete_lanczos_derivative(Real(0.0125), n, p); - for (size_t m = 0; m < n; ++m) - { - Real dvdt = lsd(v,m); - BOOST_CHECK_SMALL(dvdt, 4*sqrt(tol)); - } - for (size_t m = v.size() - n; m < v.size(); ++m) - { - Real dvdt = lsd(v,m); - BOOST_CHECK_SMALL(dvdt, 4*sqrt(tol)); - } - } - } - - for(size_t i = 0; i < v.size(); ++i) - { - v[i] = 7*i+8; - } - - for (size_t n = 3; n < 10; ++n) - { - for (size_t p = 2; p < 2*n; ++p) - { - auto lsd = discrete_lanczos_derivative(Real(1), n, p); - for (size_t m = 0; m < n; ++m) - { - Real dvdt = lsd(v,m); - BOOST_CHECK_CLOSE_FRACTION(dvdt, 7, sqrt(tol)); - } - - for (size_t m = v.size() - n; m < v.size(); ++m) - { - Real dvdt = lsd(v,m); - BOOST_CHECK_CLOSE_FRACTION(dvdt, 7, 4*sqrt(tol)); - } - } - } - - for (size_t i = 0; i < v.size(); ++i) - { - v[i] = 15*i*i + 7*i+8; - } - - for (size_t n = 1; n < 10; ++n) - { - for (size_t p = 2; p < 2*n; ++p) - { - auto lsd = discrete_lanczos_derivative(Real(1), n, p); - for (size_t m = 0; m < v.size(); ++m) - { - BOOST_CHECK_CLOSE_FRACTION(lsd(v,m), 30*m+7, 30*sqrt(tol)); - } - } - } - - // Demonstrate that the boundary filters are also denoising: - //std::random_device rd{}; - //auto seed = rd(); - //std::cout << "seed = " << seed << "\n"; - std::mt19937 gen(311354333); - std::normal_distribution<> dis{0, 0.01}; - for (size_t i = 0; i < v.size(); ++i) - { - v[i] += dis(gen); - } - - for (size_t n = 1; n < 10; ++n) - { - for (size_t p = 2; p < n; ++p) - { - auto lsd = discrete_lanczos_derivative(Real(1), n, p); - for (size_t m = 0; m < v.size(); ++m) - { - BOOST_CHECK_CLOSE_FRACTION(lsd(v,m), 30*m+7, 0.005); - } - auto dvdt = lsd(v); - for (size_t m = 0; m < v.size(); ++m) - { - BOOST_CHECK_CLOSE_FRACTION(dvdt[m], 30*m+7, 0.005); - } - } - } -} - -template -void test_acceleration_filters() -{ - Real eps = std::numeric_limits::epsilon(); - for (size_t n = 1; n < 5; ++n) - { - for(size_t p = 3; p <= 2*n; ++p) - { - for(int64_t s = -int64_t(n); s <= 0; ++s) - { - auto g = boost::math::differentiation::detail::acceleration_filter(n,p,s); - - std::vector f(g.size()); - for (size_t i = 0; i < g.size(); ++i) - { - f[i] = static_cast(g[i]); - } - - auto cond = summation_condition_number(0); - - for (size_t i = 0; i < f.size() - 1; ++i) - { - cond += f[i]; - } - BOOST_CHECK_CLOSE_FRACTION(cond.sum(), -f[f.size()-1], 10*cond()*eps); - - - cond = summation_condition_number(0); - for (size_t k = 0; k < f.size() -1; ++k) - { - Real j = Real(k) - Real(n); - cond += (j-s)*f[k]; - } - Real expected = -(Real(f.size()-1)- Real(n) - s)*f[f.size()-1]; - BOOST_CHECK_CLOSE_FRACTION(cond.sum(), expected, 10*cond()*eps); - - cond = summation_condition_number(0); - for (size_t k = 0; k < f.size(); ++k) - { - Real j = Real(k) - Real(n); - cond += (j-s)*(j-s)*f[k]; - } - BOOST_CHECK_CLOSE_FRACTION(cond.sum(), 2, 100*cond()*eps); - // See unlabelled equation in McDevitt, 2012, just after equation 26: - // It appears that there is an off-by-one error in that equation, since p + 1 moments don't vanish, only p. - // This test is itself suspect; the condition number of the moment sum is infinite. - // So the *slightest* error in the filter gets amplified by the test; in terms of the - // behavior of the actual filter, it's not a big deal. - for (size_t l = 3; l <= p; ++l) - { - cond = summation_condition_number(0); - for (size_t k = 0; k < f.size() - 1; ++k) - { - Real j = Real(k) - Real(n); - cond += pow((j-s), l)*f[k]; - } - Real expected = -pow(Real(f.size()- 1 - n -s), l)*f[f.size()-1]; - BOOST_CHECK_CLOSE_FRACTION(cond.sum(), expected, 1000*cond()*eps); - } - } - } - } -} - -template -void test_lanczos_acceleration() -{ - Real eps = std::numeric_limits::epsilon(); - std::vector v(100, 7); - auto lanczos = discrete_lanczos_derivative(Real(1), 4, 3); - for (size_t i = 0; i < v.size(); ++i) - { - BOOST_CHECK_SMALL(lanczos(v, i), eps); - } - - for(size_t i = 0; i < v.size(); ++i) - { - v[i] = 7*i + 6; - } - for (size_t i = 0; i < v.size(); ++i) - { - BOOST_CHECK_SMALL(lanczos(v,i), 200*eps); - } - - for(size_t i = 0; i < v.size(); ++i) - { - v[i] = 7*i*i + 9*i + 6; - } - for (size_t i = 0; i < v.size(); ++i) - { - BOOST_CHECK_CLOSE_FRACTION(lanczos(v, i), 14, 1500*eps); - } - - // Now add noise, and kick up the smoothing of the Lanzcos derivative (increase n): - //std::random_device rd{}; - //auto seed = rd(); - //std::cout << "seed = " << seed << "\n"; - size_t seed = 2507134629; - std::mt19937 gen(seed); - Real std_dev = 0.1; - std::normal_distribution dis{0, std_dev}; - for (size_t i = 0; i < v.size(); ++i) - { - v[i] += dis(gen); - } - lanczos = discrete_lanczos_derivative(Real(1), 18, 3); - auto w = lanczos(v); - for (size_t i = 0; i < v.size(); ++i) - { - BOOST_CHECK_CLOSE_FRACTION(w[i], 14, std_dev/200); - } -} - -template -void test_rescaling() -{ - std::cout << "Test rescaling on type " << typeid(Real).name() << "\n"; - Real tol = std::numeric_limits::epsilon(); - std::vector v(500); - for(size_t i = 0; i < v.size(); ++i) - { - v[i] = 7*i*i + 9*i + 6; - } - std::vector dvdt1(500); - std::vector dvdt2(500); - auto lanczos1 = discrete_lanczos_derivative(Real(1)); - auto lanczos2 = discrete_lanczos_derivative(Real(2)); - - lanczos1(v, dvdt1); - lanczos2(v, dvdt2); - - for(size_t i = 0; i < v.size(); ++i) - { - BOOST_CHECK_CLOSE_FRACTION(dvdt1[i], 2*dvdt2[i], tol); - } - - auto lanczos3 = discrete_lanczos_derivative(Real(1)); - auto lanczos4 = discrete_lanczos_derivative(Real(2)); - - - std::vector dv2dt21(500); - std::vector dv2dt22(500); - - for(size_t i = 0; i < v.size(); ++i) - { - BOOST_CHECK_CLOSE_FRACTION(dv2dt21[i], 4*dv2dt22[i], tol); - } -} - -template -void test_data_representations() -{ - std::cout << "Test rescaling on type " << typeid(Real).name() << "\n"; - Real tol = 150*std::numeric_limits::epsilon(); - std::array v; - for(size_t i = 0; i < v.size(); ++i) - { - v[i] = 9*i + 6; - } - std::array dvdt; - auto lanczos = discrete_lanczos_derivative(Real(1)); - - lanczos(v, dvdt); - - for(size_t i = 0; i < v.size(); ++i) - { - BOOST_CHECK_CLOSE_FRACTION(dvdt[i], 9, tol); - } - - boost::numeric::ublas::vector w(500); - boost::numeric::ublas::vector dwdt(500); - for(size_t i = 0; i < w.size(); ++i) - { - w[i] = 9*i + 6; - } - - lanczos(w, dwdt); - - for(size_t i = 0; i < v.size(); ++i) - { - BOOST_CHECK_CLOSE_FRACTION(dwdt[i], 9, tol); - } - - auto v1 = boost::make_iterator_range(v.begin(), v.end()); - auto v2 = boost::make_iterator_range(dvdt.begin(), dvdt.end()); - lanczos(v1, v2); - - for(size_t i = 0; i < v2.size(); ++i) - { - BOOST_CHECK_CLOSE_FRACTION(v2[i], 9, tol); - } - - auto lanczos2 = discrete_lanczos_derivative(Real(1)); - - lanczos2(v1, v2); - - for(size_t i = 0; i < v2.size(); ++i) - { - BOOST_CHECK_SMALL(v2[i], 10*tol); - } - -} - -BOOST_AUTO_TEST_CASE(lanczos_smoothing_test) -{ - test_dlp_second_derivative(); - test_dlp_norms(); - test_dlp_evaluation(); - test_dlp_derivatives(); - test_dlp_next(); - - // Takes too long! - //test_dlp_norms(); - test_boundary_velocity_filters(); - test_boundary_velocity_filters(); - // Takes too long! - //test_boundary_velocity_filters(); - test_boundary_lanczos(); - test_boundary_lanczos(); - // Takes too long! - //test_boundary_lanczos(); - - test_interior_velocity_filter(); - test_interior_velocity_filter(); - test_interior_lanczos(); - - test_acceleration_filters(); - - test_lanczos_acceleration(); - test_lanczos_acceleration(); - - test_rescaling(); - test_data_representations(); -} diff --git a/test/legendre_stieltjes_test.cpp b/test/legendre_stieltjes_test.cpp deleted file mode 100644 index 6fda15099e..0000000000 --- a/test/legendre_stieltjes_test.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright Nick Thompson 2017. -// 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) - -#define BOOST_TEST_MAIN - -#include -#include -#include -#include -#include - - -using boost::math::legendre_stieltjes; -using boost::math::legendre_p; -using boost::multiprecision::cpp_bin_float_quad; - - -template -void test_legendre_stieltjes() -{ - std::cout << std::setprecision(std::numeric_limits::digits10); - using std::sqrt; - using std::abs; - using boost::math::constants::third; - using boost::math::constants::half; - - Real tol = std::numeric_limits::epsilon(); - legendre_stieltjes ls1(1); - legendre_stieltjes ls2(2); - legendre_stieltjes ls3(3); - legendre_stieltjes ls4(4); - legendre_stieltjes ls5(5); - legendre_stieltjes ls8(8); - Real x = -1; - while(x <= 1) - { - BOOST_CHECK_CLOSE_FRACTION(ls1(x), x, tol); - BOOST_CHECK_CLOSE_FRACTION(ls1.prime(x), 1, tol); - - Real p2 = legendre_p(2, x); - BOOST_CHECK_CLOSE_FRACTION(ls2(x), p2 - 2/static_cast(5), tol); - BOOST_CHECK_CLOSE_FRACTION(ls2.prime(x), 3*x, tol); - - Real p3 = legendre_p(3, x); - BOOST_CHECK_CLOSE_FRACTION(ls3(x), p3 - 9*x/static_cast(14), 600*tol); - BOOST_CHECK_CLOSE_FRACTION(ls3.prime(x), 15*x*x*half() -3*half()-9/static_cast(14), 100*tol); - - Real p4 = legendre_p(4, x); - //-20P_2(x)/27 + 14P_0(x)/891 - Real E4 = p4 - 20*p2/static_cast(27) + 14/static_cast(891); - BOOST_CHECK_CLOSE_FRACTION(ls4(x), E4, 250*tol); - BOOST_CHECK_CLOSE_FRACTION(ls4.prime(x), 35*x*(9*x*x -5)/static_cast(18), 250*tol); - - Real p5 = legendre_p(5, x); - Real E5 = p5 - 35*p3/static_cast(44) + 135*x/static_cast(12584); - BOOST_CHECK_CLOSE_FRACTION(ls5(x), E5, 29000*tol); - Real E5prime = (315*(123 + 143*x*x*(11*x*x-9)))/static_cast(12584); - BOOST_CHECK_CLOSE_FRACTION(ls5.prime(x), E5prime, 29000*tol); - x += 1/static_cast(1 << 9); - } - - // Test norm: - // E_1 = x - Real expected_norm_sq = 2*third(); - BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls1.norm_sq(), tol); - - // E_2 = P[sub 2](x) - 2P[sup 0](x)/5 - expected_norm_sq = 2/static_cast(5) + 8/static_cast(25); - BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls2.norm_sq(), tol); - - // E_3 = P[sub 3](x) - 9P[sub 1]/14 - expected_norm_sq = 2/static_cast(7) + 9*9*2*third()/static_cast(14*14); - BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls3.norm_sq(), tol); - - // E_4 = P[sub 4](x) -20P[sub 2](x)/27 + 14P[sub 0](x)/891 - expected_norm_sq = static_cast(2)/static_cast(9) + static_cast(20*20*2)/static_cast(27*27*5) + 14*14*2/static_cast(891*891); - BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls4.norm_sq(), tol); - - // E_5 = P[sub 5](x) - 35P[sub 3](x)/44 + 135P[sub 1](x)/12584 - expected_norm_sq = 2/static_cast(11) + (35*35/static_cast(44*44))*(2/static_cast(7)) + (135*135/static_cast(12584*12584))*2*third(); - BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls5.norm_sq(), tol); - - // Only zero of E1 is 0: - std::vector zeros = ls1.zeros(); - BOOST_CHECK(zeros.size() == 1); - BOOST_CHECK_SMALL(zeros[0], tol); - BOOST_CHECK_SMALL(ls1(zeros[0]), tol); - - zeros = ls2.zeros(); - BOOST_CHECK(zeros.size() == 1); - BOOST_CHECK_CLOSE_FRACTION(zeros[0], sqrt(3/static_cast(5)), tol); - BOOST_CHECK_SMALL(ls2(zeros[0]), tol); - - zeros = ls3.zeros(); - BOOST_CHECK(zeros.size() == 2); - BOOST_CHECK_SMALL(zeros[0], tol); - BOOST_CHECK_CLOSE_FRACTION(zeros[1], sqrt(6/static_cast(7)), tol); - - - zeros = ls4.zeros(); - BOOST_CHECK(zeros.size() == 2); - Real expected = sqrt( (55 - 2*sqrt(static_cast(330)))/static_cast(11) )/static_cast(3); - BOOST_CHECK_CLOSE_FRACTION(zeros[0], expected, tol); - - expected = sqrt( (55 + 2*sqrt(static_cast(330)))/static_cast(11) )/static_cast(3); - BOOST_CHECK_CLOSE_FRACTION(zeros[1], expected, 10*tol); - - - zeros = ls5.zeros(); - BOOST_CHECK(zeros.size() == 3); - BOOST_CHECK_SMALL(zeros[0], tol); - - expected = sqrt( ( 195 - sqrt(static_cast(6045)) )/static_cast(286)); - BOOST_CHECK_CLOSE_FRACTION(zeros[1], expected, tol); - - expected = sqrt( ( 195 + sqrt(static_cast(6045)) )/static_cast(286)); - BOOST_CHECK_CLOSE_FRACTION(zeros[2], expected, tol); - - - for (size_t i = 6; i < 50; ++i) - { - legendre_stieltjes En(i); - zeros = En.zeros(); - for(auto const & zero : zeros) - { - BOOST_CHECK_SMALL(En(zero), 50*tol); - } - } - -#ifndef BOOST_MATH_NO_EXCEPTIONS - BOOST_CHECK_THROW(legendre_stieltjes(0), std::domain_error); -#endif -} - - -BOOST_AUTO_TEST_CASE(LegendreStieltjesZeros) -{ - test_legendre_stieltjes(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_legendre_stieltjes(); -#endif - test_legendre_stieltjes(); - //test_legendre_stieltjes(); -} diff --git a/test/linear_regression_test.cpp b/test/linear_regression_test.cpp deleted file mode 100644 index 03570c53ac..0000000000 --- a/test/linear_regression_test.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright Nick Thompson, 2019 - * Copyright Matt Borland, 2021 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#include - -using boost::math::statistics::simple_ordinary_least_squares; -using boost::math::statistics::simple_ordinary_least_squares_with_R_squared; - -template -void test_line() -{ - std::vector x(128); - std::vector y(128); - Real expected_c0 = 7; - Real expected_c1 = 12; - for (size_t i = 0; i < x.size(); ++i) { - x[i] = i; - y[i] = expected_c0 + expected_c1*x[i]; - } - - std::pair temp = simple_ordinary_least_squares(x, y); - Real computed_c0 = std::get<0>(temp); - Real computed_c1 = std::get<1>(temp); - - CHECK_ULP_CLOSE(expected_c0, computed_c0, 0); - CHECK_ULP_CLOSE(expected_c1, computed_c1, 0); - - std::tuple temp_with_R = simple_ordinary_least_squares_with_R_squared(x, y); - Real computed_c0_R = std::get<0>(temp_with_R); - Real computed_c1_R = std::get<1>(temp_with_R); - Real Rsquared = std::get<2>(temp_with_R); - - Real expected_Rsquared = 1; - CHECK_ULP_CLOSE(expected_c0, computed_c0_R, 0); - CHECK_ULP_CLOSE(expected_c1, computed_c1_R, 0); - CHECK_ULP_CLOSE(expected_Rsquared, Rsquared, 0); - -} - -template -void test_integer_line() -{ - std::vector x(128); - std::vector y(128); - double expected_c0 = 7; - double expected_c1 = 12; - for (size_t i = 0; i < x.size(); ++i) { - x[i] = i; - y[i] = expected_c0 + expected_c1*x[i]; - } - - std::pair temp = simple_ordinary_least_squares(x, y); - double computed_c0 = std::get<0>(temp); - double computed_c1 = std::get<1>(temp); - - CHECK_ULP_CLOSE(expected_c0, computed_c0, 0); - CHECK_ULP_CLOSE(expected_c1, computed_c1, 0); - - std::tuple temp_with_R = simple_ordinary_least_squares_with_R_squared(x, y); - double computed_c0_R = std::get<0>(temp_with_R); - double computed_c1_R = std::get<1>(temp_with_R); - double Rsquared = std::get<2>(temp_with_R); - - double expected_Rsquared = 1; - CHECK_ULP_CLOSE(expected_c0, computed_c0_R, 0); - CHECK_ULP_CLOSE(expected_c1, computed_c1_R, 0); - CHECK_ULP_CLOSE(expected_Rsquared, Rsquared, 0); - -} - -template -void test_constant() -{ - std::vector x(128); - std::vector y(128); - Real expected_c0 = 7; - Real expected_c1 = 0; - for (size_t i = 0; i < x.size(); ++i) { - x[i] = i; - y[i] = expected_c0 + expected_c1*x[i]; - } - - std::pair temp = simple_ordinary_least_squares(x, y); - Real computed_c0 = std::get<0>(temp); - Real computed_c1 = std::get<1>(temp); - - CHECK_ULP_CLOSE(expected_c0, computed_c0, 0); - CHECK_ULP_CLOSE(expected_c1, computed_c1, 0); - - std::tuple temp_with_R = simple_ordinary_least_squares_with_R_squared(x, y); - Real computed_c0_R = std::get<0>(temp_with_R); - Real computed_c1_R = std::get<1>(temp_with_R); - Real Rsquared = std::get<2>(temp_with_R); - - Real expected_Rsquared = 1; - CHECK_ULP_CLOSE(expected_c0, computed_c0_R, 0); - CHECK_ULP_CLOSE(expected_c1, computed_c1_R, 0); - CHECK_ULP_CLOSE(expected_Rsquared, Rsquared, 0); - -} - -template -void test_integer_constant() -{ - std::vector x(128); - std::vector y(128); - double expected_c0 = 7; - double expected_c1 = 0; - for (size_t i = 0; i < x.size(); ++i) { - x[i] = i; - y[i] = expected_c0 + expected_c1*x[i]; - } - - std::pair temp = simple_ordinary_least_squares(x, y); - double computed_c0 = std::get<0>(temp); - double computed_c1 = std::get<1>(temp); - - CHECK_ULP_CLOSE(expected_c0, computed_c0, 0); - CHECK_ULP_CLOSE(expected_c1, computed_c1, 0); - - std::tuple temp_with_R = simple_ordinary_least_squares_with_R_squared(x, y); - double computed_c0_R = std::get<0>(temp_with_R); - double computed_c1_R = std::get<1>(temp_with_R); - double Rsquared = std::get<2>(temp_with_R); - - double expected_Rsquared = 1; - CHECK_ULP_CLOSE(expected_c0, computed_c0_R, 0); - CHECK_ULP_CLOSE(expected_c1, computed_c1_R, 0); - CHECK_ULP_CLOSE(expected_Rsquared, Rsquared, 0); - -} - -template -void test_permutation_invariance() -{ - std::vector x(256); - std::vector y(256); - std::mt19937_64 gen{123456}; - std::normal_distribution dis(0, 0.1); - - Real expected_c0 = -7.2; - Real expected_c1 = -13.5; - - x[0] = 0; - y[0] = expected_c0 + dis(gen); - for(size_t i = 1; i < x.size(); ++i) { - Real t = dis(gen); - x[i] = x[i-1] + t*t; - y[i] = expected_c0 + expected_c1*x[i] + dis(gen); - } - - std::tuple temp = simple_ordinary_least_squares_with_R_squared(x, y); - Real c0 = std::get<0>(temp); - Real c1 = std::get<1>(temp); - Real Rsquared = std::get<2>(temp); - CHECK_MOLLIFIED_CLOSE(expected_c0, c0, 0.003); - CHECK_MOLLIFIED_CLOSE(expected_c1, c1, 0.002); - - int j = 0; - std::mt19937_64 gen1{12345}; - std::mt19937_64 gen2{12345}; - while(j++ < 10) { - std::shuffle(x.begin(), x.end(), gen1); - std::shuffle(y.begin(), y.end(), gen2); - - std::tuple temp_ = simple_ordinary_least_squares_with_R_squared(x, y); - Real c0_ = std::get<0>(temp_); - Real c1_ = std::get<1>(temp_); - Real Rsquared_ = std::get<2>(temp_); - - CHECK_ULP_CLOSE(c0, c0_, 100); - CHECK_ULP_CLOSE(c1, c1_, 100); - CHECK_ULP_CLOSE(Rsquared, Rsquared_, 65); - } -} - -template -void test_scaling_relations() -{ - std::vector x(256); - std::vector y(256); - std::mt19937_64 gen{123456}; - std::normal_distribution dis(0, 0.1); - - Real expected_c0 = 3.2; - Real expected_c1 = -13.5; - - x[0] = 0; - y[0] = expected_c0 + dis(gen); - for(size_t i = 1; i < x.size(); ++i) { - Real t = dis(gen); - x[i] = x[i-1] + t*t; - y[i] = expected_c0 + expected_c1*x[i] + dis(gen); - } - - std::tuple temp = simple_ordinary_least_squares_with_R_squared(x, y); - Real c0 = std::get<0>(temp); - Real c1 = std::get<1>(temp); - Real Rsquared = std::get<2>(temp); - CHECK_MOLLIFIED_CLOSE(expected_c0, c0, 0.006); - CHECK_MOLLIFIED_CLOSE(expected_c1, c1, 0.005); - - // If y -> lambda y, then c0 -> lambda c0 and c1 -> lambda c1. - Real lambda = 6; - - for (auto& s : y) { - s *= lambda; - } - - temp = simple_ordinary_least_squares_with_R_squared(x, y); - Real c0_lambda = std::get<0>(temp); - Real c1_lambda = std::get<1>(temp); - Real Rsquared_lambda = std::get<2>(temp); - - CHECK_ULP_CLOSE(lambda*c0, c0_lambda, 70); - CHECK_ULP_CLOSE(lambda*c1, c1_lambda, 30); - CHECK_ULP_CLOSE(Rsquared, Rsquared_lambda, 3); - - // If x -> lambda x, then c0 -> c0 and c1 -> c1/lambda - for (auto& s : x) { - s *= lambda; - } - // Put y back into it's original state: - for (auto& s : y) { - s /= lambda; - } - - temp = simple_ordinary_least_squares_with_R_squared(x, y); - Real c0_ = std::get<0>(temp); - Real c1_ = std::get<1>(temp); - Real Rsquared_ = std::get<2>(temp); - - CHECK_ULP_CLOSE(c0, c0_, 100); - CHECK_ULP_CLOSE(c1, c1_*lambda, 50); - CHECK_ULP_CLOSE(Rsquared, Rsquared_, 50); - -} - - -int main() -{ - test_line(); - test_line(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_line(); -#endif - test_integer_line(); - test_integer_line(); - test_integer_line(); - test_integer_line(); - - test_constant(); - test_constant(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_constant(); -#endif - test_integer_constant(); - test_integer_constant(); - test_integer_constant(); - test_integer_constant(); - - test_permutation_invariance(); - test_permutation_invariance(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_permutation_invariance(); -#endif - - test_scaling_relations(); - test_scaling_relations(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_scaling_relations(); -#endif - return boost::math::test::report_errors(); -} diff --git a/test/ljung_box_test.cpp b/test/ljung_box_test.cpp deleted file mode 100644 index 59d0827032..0000000000 --- a/test/ljung_box_test.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Nick Thompson, 2019 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include - -using boost::math::statistics::ljung_box; - -template -void test_trivial() -{ - - // Validate in R: - // > v <- c(1,2) - // > Box.test(v, lag=1, "Ljung") - // Box-Ljung test - // data: v - // X-squared = 2, df = 1, p-value = 0.1573 - - std::vector v{1,2}; - - double expected_statistic = 2; - double expected_pvalue = 0.15729920705028455; - - auto [computed_statistic, computed_pvalue] = ljung_box(v, 1); - CHECK_ULP_CLOSE(expected_statistic, computed_statistic, 10); - CHECK_ULP_CLOSE(expected_pvalue, computed_pvalue, 30); -} - - -void test_agreement_with_mathematica() -{ - std::vector v{0.7739928761039216,-0.4468259278452086,0.98287381303903,-0.3943029116201079,0.6569015496559457}; - double expected_statistic = 10.2076093223439; - double expected_pvalue = 0.00607359458123835072; - - auto [computed_statistic, computed_pvalue] = ljung_box(v); - CHECK_ULP_CLOSE(expected_statistic, computed_statistic, 3); - CHECK_ULP_CLOSE(expected_pvalue, computed_pvalue, 3); -} - -int main() -{ - test_trivial(); - test_agreement_with_mathematica(); - return boost::math::test::report_errors(); -} diff --git a/test/log1p_expm1_extra_test.cpp b/test/log1p_expm1_extra_test.cpp deleted file mode 100644 index eb0ff079db..0000000000 --- a/test/log1p_expm1_extra_test.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright John Maddock 2005. -// Copyright Paul A. Bristow 2010 -// 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) - -#include - -#define SC_(x) static_cast(BOOST_STRINGIZE(x)) - -#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error - -#define BOOST_TEST_MAIN -#include -#include -#include -#include -#include "log1p_expm1_test.hpp" -#include - -// -// DESCRIPTION: -// ~~~~~~~~~~~~ -// -// This file tests the functions log1p and expm1. The accuracy tests -// use values generated with NTL::RR at 1000-bit precision -// and our generic versions of these functions. -// -// Note that this tests the generic versions of our functions using -// software emulated types. This ensures these still get tested -// even though we mostly defer to std::expm1 and std::log1p at -// these precisions nowadays -// - -void expected_results() -{ - // - // Define the max and mean errors expected for - // various compilers and platforms. - // - - // - // Catch all cases come last: - // - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*", // test type(s) - ".*", // test data group - ".*", // test function - 4, // Max Peek error - 3); // Max mean error - - // - // Finish off by printing out the compiler/stdlib/platform names, - // we do this to make it easier to mark up expected error rates. - // - std::cout << "Tests run with " << BOOST_COMPILER << ", " - << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; -} - - -BOOST_AUTO_TEST_CASE( test_main ) -{ - expected_results(); - BOOST_MATH_CONTROL_FP; - test(boost::multiprecision::cpp_bin_float_single(0), "cpp_bin_float_single"); - test(boost::multiprecision::cpp_bin_float_double(0), "cpp_bin_float_double"); - test(boost::multiprecision::cpp_bin_float_double_extended(0), "cpp_bin_float_double_extended"); - test(boost::multiprecision::cpp_bin_float_quad(0), "cpp_bin_float_quad"); -} - diff --git a/test/log1p_expm1_stdfloat_test.cpp b/test/log1p_expm1_stdfloat_test.cpp deleted file mode 100644 index 7ad71b4d21..0000000000 --- a/test/log1p_expm1_stdfloat_test.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright John Maddock 2005. -// Copyright Paul A. Bristow 2010 -// 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) - -#include - -#if defined __has_include -# if __cplusplus > 202002L || _MSVC_LANG > 202002L -# if __has_include () -# include -# endif -# endif -#endif - -#define SC_(x) static_cast(BOOST_MATH_BIG_CONSTANT(T, 128, x)) - -#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error - -#define BOOST_TEST_MAIN -#include -#include -#include -#include -#include -#include "log1p_expm1_test.hpp" - -// -// DESCRIPTION: -// ~~~~~~~~~~~~ -// -// This file tests the functions log1p and expm1. The accuracy tests -// use values generated with NTL::RR at 1000-bit precision -// and our generic versions of these functions. -// -// Note that this tests the generic versions of our functions using -// software emulated types. This ensures these still get tested -// even though we mostly defer to std::expm1 and std::log1p at -// these precisions nowadays -// - -void expected_results() -{ - // - // Define the max and mean errors expected for - // various compilers and platforms. - // - - // - // Catch all cases come last: - // - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*", // test type(s) - ".*", // test data group - ".*", // test function - 4, // Max Peek error - 3); // Max mean error - - // - // Finish off by printing out the compiler/stdlib/platform names, - // we do this to make it easier to mark up expected error rates. - // - std::cout << "Tests run with " << BOOST_COMPILER << ", " - << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; -} - - -BOOST_AUTO_TEST_CASE( test_main ) -{ - expected_results(); - BOOST_MATH_CONTROL_FP; -#ifdef __STDCPP_FLOAT32_T__ - test(std::float32_t(0), "std::float32_t"); -#endif -#ifdef __STDCPP_FLOAT64_T__ - test(std::float64_t(0), "std::float64_t"); -#endif -#ifdef __STDCPP_FLOAT128_T__ - // As of gcc-13 this does not work as float128_t has no std::math function overloads - //test(std::float128_t(0), "std::float128_t"); -#endif -} - diff --git a/test/log1p_expm1_test.cpp b/test/log1p_expm1_test.cpp deleted file mode 100644 index 04d45e2c52..0000000000 --- a/test/log1p_expm1_test.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright John Maddock 2005. -// Copyright Paul A. Bristow 2010 -// 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) - -#include - -// Requires MS extensions permitted or fails to link. - - -#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error - -#include -#define BOOST_TEST_MAIN -#include -#include -#include -#include "log1p_expm1_test.hpp" - -// -// DESCRIPTION: -// ~~~~~~~~~~~~ -// -// This file tests the functions log1p and expm1. The accuracy tests -// use values generated with NTL::RR at 1000-bit precision -// and our generic versions of these functions. -// -// Note that when this file is first run on a new platform many of -// these tests will fail: the default accuracy is 1 epsilon which -// is too tight for most platforms. In this situation you will -// need to cast a human eye over the error rates reported and make -// a judgement as to whether they are acceptable. Either way please -// report the results to the Boost mailing list. Acceptable rates of -// error are marked up below as a series of regular expressions that -// identify the compiler/stdlib/platform/data-type/test-data/test-function -// along with the maximum expected peek and RMS mean errors for that -// test. -// - -void expected_results() -{ - // - // Define the max and mean errors expected for - // various compilers and platforms. - // - - // - // Catch all cases come last: - // - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*", // test type(s) - ".*", // test data group - ".*", // test function - 4, // Max Peek error - 3); // Max mean error - - // - // Finish off by printing out the compiler/stdlib/platform names, - // we do this to make it easier to mark up expected error rates. - // - std::cout << "Tests run with " << BOOST_COMPILER << ", " - << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; -} - - -BOOST_AUTO_TEST_CASE( test_main ) -{ - expected_results(); - BOOST_MATH_CONTROL_FP; - test(float(0), "float"); - test(double(0), "double"); - // - // The long double version of these tests fails on some platforms - // due to poor std lib support (not enough digits returned from - // std::log and std::exp): - // -#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) - test((long double)(0), "long double"); -#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS - test((boost::math::concepts::real_concept)(0), "real_concept"); -#endif -#else - std::cout << "The long double tests have been disabled on this platform " - "either because the long double overloads of the usual math functions are " - "not available at all, or because they are too inaccurate for these tests " - "to pass." << std::endl; -#endif -} - diff --git a/test/makima_test.cpp b/test/makima_test.cpp deleted file mode 100644 index 393c15da3a..0000000000 --- a/test/makima_test.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright Nick Thompson, 2020 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - -#if __has_include() -# include -#endif - -using boost::math::interpolators::makima; - -template -void test_constant() -{ - - std::vector x{0,1,2,3, 9, 22, 81}; - std::vector y(x.size()); - for (auto & t : y) { - t = 7; - } - - auto x_copy = x; - auto y_copy = y; - auto akima = makima(std::move(x_copy), std::move(y_copy)); - - for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { - CHECK_ULP_CLOSE(Real(7), akima(t), 2); - CHECK_ULP_CLOSE(Real(0), akima.prime(t), 2); - } - - boost::circular_buffer x_buf(x.size()); - for (auto & t : x) { - x_buf.push_back(t); - } - - boost::circular_buffer y_buf(x.size()); - for (auto & t : y) { - y_buf.push_back(t); - } - - auto circular_akima = makima(std::move(x_buf), std::move(y_buf)); - - for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { - CHECK_ULP_CLOSE(Real(7), circular_akima(t), 2); - CHECK_ULP_CLOSE(Real(0), akima.prime(t), 2); - } - - circular_akima.push_back(x.back() + 1, 7); - CHECK_ULP_CLOSE(Real(0), circular_akima.prime(x.back()+1), 2); - -} - -template -void test_linear() -{ - std::vector x{0,1,2,3}; - std::vector y{0,1,2,3}; - - auto x_copy = x; - auto y_copy = y; - auto akima = makima(std::move(x_copy), std::move(y_copy)); - - CHECK_ULP_CLOSE(y[0], akima(x[0]), 0); - CHECK_ULP_CLOSE(Real(1)/Real(2), akima(Real(1)/Real(2)), 10); - CHECK_ULP_CLOSE(y[1], akima(x[1]), 0); - CHECK_ULP_CLOSE(Real(3)/Real(2), akima(Real(3)/Real(2)), 10); - CHECK_ULP_CLOSE(y[2], akima(x[2]), 0); - CHECK_ULP_CLOSE(Real(5)/Real(2), akima(Real(5)/Real(2)), 10); - CHECK_ULP_CLOSE(y[3], akima(x[3]), 0); - - x.resize(45); - y.resize(45); - for (size_t i = 0; i < x.size(); ++i) { - x[i] = i; - y[i] = i; - } - - x_copy = x; - y_copy = y; - akima = makima(std::move(x_copy), std::move(y_copy)); - for (Real t = 0; t < x.back(); t += Real(0.5)) { - CHECK_ULP_CLOSE(t, akima(t), 0); - CHECK_ULP_CLOSE(Real(1), akima.prime(t), 0); - } - - x_copy = x; - y_copy = y; - // Test endpoint derivatives: - akima = makima(std::move(x_copy), std::move(y_copy), Real(1), Real(1)); - for (Real t = 0; t < x.back(); t += Real(0.5)) { - CHECK_ULP_CLOSE(t, akima(t), 0); - CHECK_ULP_CLOSE(Real(1), akima.prime(t), 0); - } - - - boost::circular_buffer x_buf(x.size()); - for (auto & t : x) { - x_buf.push_back(t); - } - - boost::circular_buffer y_buf(x.size()); - for (auto & t : y) { - y_buf.push_back(t); - } - - auto circular_akima = makima(std::move(x_buf), std::move(y_buf)); - - for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { - CHECK_ULP_CLOSE(t, circular_akima(t), 2); - CHECK_ULP_CLOSE(Real(1), circular_akima.prime(t), 2); - } - - circular_akima.push_back(x.back() + 1, y.back()+1); - - CHECK_ULP_CLOSE(Real(y.back() + 1), circular_akima(Real(x.back()+1)), 2); - CHECK_ULP_CLOSE(Real(1), circular_akima.prime(Real(x.back()+1)), 2); - -} - -template -void test_interpolation_condition() -{ - for (size_t n = 4; n < 50; ++n) { - std::vector x(n); - std::vector y(n); - std::default_random_engine rd; - std::uniform_real_distribution dis(0,1); - Real x0 = dis(rd); - x[0] = x0; - y[0] = dis(rd); - for (size_t i = 1; i < n; ++i) { - x[i] = x[i-1] + dis(rd); - y[i] = dis(rd); - } - - auto x_copy = x; - auto y_copy = y; - auto s = makima(std::move(x_copy), std::move(y_copy)); - //std::cout << "s = " << s << "\n"; - for (size_t i = 0; i < x.size(); ++i) { - CHECK_ULP_CLOSE(y[i], s(x[i]), 2); - } - - x_copy = x; - y_copy = y; - // The interpolation condition is not affected by the endpoint derivatives, even though these derivatives might be super weird: - s = makima(std::move(x_copy), std::move(y_copy), Real(0), Real(0)); - //std::cout << "s = " << s << "\n"; - for (size_t i = 0; i < x.size(); ++i) { - CHECK_ULP_CLOSE(y[i], s(x[i]), 2); - } - - } -} - -int main() -{ -#if (__GNUC__ > 7) || defined(_MSC_VER) || defined(__clang__) - - #ifdef __STDCPP_FLOAT32_T__ - test_constant(); - test_linear(); - test_interpolation_condition(); - #else - test_constant(); - test_linear(); - test_interpolation_condition(); - #endif - - #ifdef __STDCPP_FLOAT64_T__ - test_constant(); - test_linear(); - test_interpolation_condition(); - #else - test_constant(); - test_linear(); - test_interpolation_condition(); - #endif - - test_constant(); - test_linear(); - test_interpolation_condition(); - -#ifdef BOOST_HAS_FLOAT128 - test_constant(); - test_linear(); -#endif -#endif - return boost::math::test::report_errors(); -} diff --git a/test/math_unit_test.hpp b/test/math_unit_test.hpp index bd85caa86b..b165a53414 100644 --- a/test/math_unit_test.hpp +++ b/test/math_unit_test.hpp @@ -6,16 +6,32 @@ #ifndef BOOST_MATH_TEST_TEST_HPP #define BOOST_MATH_TEST_TEST_HPP +// A module build always consumes the standard library through `import std;`. +// Nothing standard may be included textually in module mode: another Boost +// header pulling in a std header after the import would trip a concept-merge +// failure, so every std include below is confined to the non-module branch. +#ifdef BOOST_MATH_BUILD_MODULE +import std; +#include +#include +#else +#include #include #include #include -#include // for std::isnan #include #include +#endif #include +// In module mode these declarations come from `import boost.math;`, which the +// including test performs before this header. +#ifndef BOOST_MATH_BUILD_MODULE #include #include -#if defined __has_include +#endif +// pulls /bits/exception.h, which redefine std entities that +// import std already provides; skip it in module mode (demangle then falls back). +#if !defined(BOOST_MATH_BUILD_MODULE) && defined __has_include # if __has_include() #define BOOST_MATH_HAS_CXX_ABI 1 # include @@ -24,8 +40,10 @@ namespace boost { namespace math { namespace test { namespace detail { - static std::atomic global_error_count{0}; - static std::atomic total_ulp_distance{0}; + // Function-local statics of inline functions, so that a test built from several + // translation units shares one error count: + inline std::atomic& global_error_count() { static std::atomic c{0}; return c; } + inline std::atomic& total_ulp_distance() { static std::atomic c{0}; return c; } inline std::string demangle(char const * name) { @@ -41,7 +59,7 @@ namespace detail { } template -bool check_mollified_close(Real expected, Real computed, Real tol, std::string const & filename, std::string const & function, int line) +bool check_mollified_close(Real expected, Real computed, Real tol, char const * filename, char const * function, int line) { using std::isnan; BOOST_MATH_ASSERT_MSG(!isnan(tol), "Tolerance cannot be a nan."); @@ -53,7 +71,7 @@ bool check_mollified_close(Real expected, Real computed, Real tol, std::string c std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << ":\n" << " \033[0m Computed value is a nan\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } using std::max; @@ -63,7 +81,7 @@ bool check_mollified_close(Real expected, Real computed, Real tol, std::string c if (mollified_relative_error > tol) { Real dist = abs(boost::math::float_distance(expected, computed)); - detail::total_ulp_distance += static_cast(dist); + detail::total_ulp_distance() += static_cast(dist); std::ios_base::fmtflags f( std::cerr.flags() ); std::cerr << std::setprecision(3); std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << ":\n" @@ -75,7 +93,7 @@ bool check_mollified_close(Real expected, Real computed, Real tol, std::string c << std::defaultfloat << " ULP distance: " << dist << "\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } @@ -83,7 +101,7 @@ bool check_mollified_close(Real expected, Real computed, Real tol, std::string c } template -bool check_ulp_close(PreciseReal expected1, Real computed, size_t ulps, std::string const & filename, std::string const & function, int line) +bool check_ulp_close(PreciseReal expected1, Real computed, size_t ulps, char const * filename, char const * function, int line) { using std::max; using std::abs; @@ -112,7 +130,7 @@ bool check_ulp_close(PreciseReal expected1, Real computed, size_t ulps, std::str std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << ":\n" << " \033[0m Computed value is a nan\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } @@ -120,7 +138,7 @@ bool check_ulp_close(PreciseReal expected1, Real computed, size_t ulps, std::str Real dist = abs(boost::math::float_distance(expected, computed)); if (dist > ulps) { - detail::total_ulp_distance += static_cast(lltrunc(dist)); + detail::total_ulp_distance() += static_cast(lltrunc(dist)); Real abs_expected = abs(expected); Real denom = (max)(abs_expected, Real(1)); Real mollified_relative_error = abs(expected - computed)/denom; @@ -143,14 +161,14 @@ bool check_ulp_close(PreciseReal expected1, Real computed, size_t ulps, std::str << std::defaultfloat << " Mollified relative error: " << mollified_relative_error << "\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } return true; } template -bool check_le(Real lesser, Real greater, std::string const & filename, std::string const & function, int line) +bool check_le(Real lesser, Real greater, char const * filename, char const * function, int line) { using std::max; using std::abs; @@ -164,7 +182,7 @@ bool check_le(Real lesser, Real greater, std::string const & filename, std::stri std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << ":\n" << " \033[0m Lesser value is a nan\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } @@ -175,7 +193,7 @@ bool check_le(Real lesser, Real greater, std::string const & filename, std::stri std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << ":\n" << " \033[0m Greater value is a nan\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } } @@ -191,7 +209,7 @@ bool check_le(Real lesser, Real greater, std::string const & filename, std::stri << " \"Greater\": " << std::defaultfloat << std::fixed << greater << " = " << std::scientific << greater << std::hexfloat << " = " << greater << "\n" << std::defaultfloat; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } return true; @@ -199,7 +217,7 @@ bool check_le(Real lesser, Real greater, std::string const & filename, std::stri template -bool check_conditioned_error(Real abscissa, PreciseReal expected1, PreciseReal expected_derivative, Real computed, Real acceptable_badness, std::string const & filename, std::string const & function, int line) +bool check_conditioned_error(Real abscissa, PreciseReal expected1, PreciseReal expected_derivative, Real computed, Real acceptable_badness, char const * filename, char const * function, int line) { using std::max; using std::abs; @@ -221,7 +239,7 @@ bool check_conditioned_error(Real abscissa, PreciseReal expected1, PreciseReal e std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << ":\n" << " \033[0m Computed value is a nan\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } @@ -241,7 +259,7 @@ bool check_conditioned_error(Real abscissa, PreciseReal expected1, PreciseReal e std::cerr << " Given that the expected value is zero, the computed value in " << detail::demangle(typeid(Real).name()) << " precision must satisfy |f(x)| <= " << tol << ".\n"; std::cerr << " But the computed value is " << std::defaultfloat << std::fixed << computed << std::hexfloat << " = " << computed << "\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } } @@ -272,7 +290,7 @@ bool check_conditioned_error(Real abscissa, PreciseReal expected1, PreciseReal e << " Condition number of function evaluation: " << std::noshowpos << std::defaultfloat << std::scientific << cond << " = " << std::fixed << cond << "\n" << " Badness scale required to make this message go away: " << std::defaultfloat << relative_error/(cond*mu) << "\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } return true; @@ -280,7 +298,7 @@ bool check_conditioned_error(Real abscissa, PreciseReal expected1, PreciseReal e template -bool check_absolute_error(PreciseReal expected1, Real computed, Real acceptable_error, std::string const & filename, std::string const & function, int line) +bool check_absolute_error(PreciseReal expected1, Real computed, Real acceptable_error, char const * filename, char const * function, int line) { using std::max; using std::abs; @@ -289,18 +307,18 @@ bool check_absolute_error(PreciseReal expected1, Real computed, Real acceptable_ if (!std::is_integral::value) { BOOST_MATH_ASSERT_MSG(sizeof(PreciseReal) >= sizeof(Real), "The expected number must be computed in higher (or equal) precision than the number being tested."); - BOOST_MATH_ASSERT_MSG(!isnan(expected1), "Expected value cannot be a nan (use CHECK_NAN if this is your intention)."); + BOOST_MATH_ASSERT_MSG(!boost::math::isnan(expected1), "Expected value cannot be a nan (use CHECK_NAN if this is your intention)."); } BOOST_MATH_ASSERT_MSG(acceptable_error > 0, "Error must be > 0."); - if (isnan(computed)) + if (boost::math::isnan(computed)) { std::ios_base::fmtflags f(std::cerr.flags()); std::cerr << std::setprecision(3); std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << ":\n" << " \033[0m Computed value is a nan\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } @@ -319,14 +337,57 @@ bool check_absolute_error(PreciseReal expected1, Real computed, Real acceptable_ << " Computed: " << std::defaultfloat << std::fixed << computed << " = " << std::scientific << computed<< std::hexfloat << " = " << computed << "\n" << " Error/Acceptable error: " << std::defaultfloat << error/acceptable_error << "\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } return true; } +// The relative comparison of Boost.Test's BOOST_CHECK_CLOSE_FRACTION: passes when +// |x - y| <= tol*|x| and |x - y| <= tol*|y|. (BOOST_CHECK_CLOSE(x, y, p) is this with tol = p/100.) template -bool check_nan(Real x, std::string const & filename, std::string const & function, int line) +bool check_relative_error_impl(Real x, Real y, Real tol, char const * filename, char const * function, int line) +{ + using std::abs; + using std::max; + const Real big = boost::math::tools::max_value(); + const Real small = boost::math::tools::min_value(); + // Boost.Test's safe division, which saturates rather than overflow or underflow: + auto safe_div = [&](Real num, Real den) -> Real { + if ((den < Real(1)) && (num > den*big)) { return big; } + if ((abs(num) <= small) || ((den > Real(1)) && (num < den*small))) { return Real(0); } + return num/den; + }; + Real diff = abs(x - y); + Real rel = (max)(safe_div(diff, abs(y)), safe_div(diff, abs(x))); + if (!(rel <= tol)) + { + std::ios_base::fmtflags f( std::cerr.flags() ); + std::cerr << std::setprecision(3); + std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << ":\n" + << " \033[0m Relative error in " << detail::demangle(typeid(Real).name()) << " precision is " << rel + << ", which exceeds " << tol << ", error/tol = " << rel/tol << ".\n" + << std::setprecision(std::numeric_limits::max_digits10) << std::showpos + << " Expected: " << std::defaultfloat << std::fixed << x << std::hexfloat << " = " << x << "\n" + << " Computed: " << std::defaultfloat << std::fixed << y << std::hexfloat << " = " << y << "\n" + << std::defaultfloat; + std::cerr.flags(f); + ++detail::global_error_count(); + return false; + } + return true; +} + +// Compares in the common type of x and y, to which the tolerance is also converted, as Boost.Test does: +template +bool check_relative_error(X const & x, Y const & y, Tol const & tol, char const * filename, char const * function, int line) +{ + using Real = typename std::common_type::type; + return check_relative_error_impl(static_cast(x), static_cast(y), static_cast(tol), filename, function, line); +} + +template +bool check_nan(Real x, char const * filename, char const * function, int line) { using std::isnan; if (!isnan(x)) { @@ -334,14 +395,14 @@ bool check_nan(Real x, std::string const & filename, std::string const & functio std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << "\n"; std::cerr << "\033[0m The computed value should be a nan, but is instead " << std::defaultfloat << std::fixed << x << " = " << std::scientific << x << std::hexfloat << " = " << x << "\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } return true; } template -bool check_equal(Real x, Real y, std::string const & filename, std::string const & function, int line) +bool check_equal(Real x, Real y, char const * filename, char const * function, int line) { using std::isnan; if (x != y) { @@ -357,53 +418,59 @@ bool check_equal(Real x, Real y, std::string const & filename, std::string const std::cerr << " Computed: " << y << " = " << "0x" << std::hex << y << "\n"; } std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } return true; } -bool check_true(bool condition, std::string const & filename, std::string const & function, int line) +inline bool check_true(bool condition, char const * filename, char const * function, int line) { if (!condition) { std::ios_base::fmtflags f( std::cerr.flags() ); std::cerr << "\033[0;31mError at " << filename << ":" << function << ":" << line << "\n"; std::cerr << "\033[0m Boolean condition is not satisfied:\n"; std::cerr.flags(f); - ++detail::global_error_count; + ++detail::global_error_count(); return false; } return true; } -void report_non_throw(const std::string& file, int line) +inline void report_non_throw(char const * file, int line) { std::cerr << "Expected exception not thrown in test at: " << file << ":" << line << std::endl; - ++detail::global_error_count; + ++detail::global_error_count(); } -void report_incorrect_throw(const std::string& file, int line) +inline void report_unexpected_throw(char const * file, int line) +{ + std::cerr << "Unexpected exception thrown in test at: " << file << ":" << line << std::endl; + ++detail::global_error_count(); +} + +inline void report_incorrect_throw(char const * file, int line) { std::cerr << "Exception of the wrong type thrown in test at: " << file << ":" << line << std::endl; - ++detail::global_error_count; + ++detail::global_error_count(); } -int report_errors() +inline int report_errors() { - if (detail::global_error_count > 0) + if (detail::global_error_count() > 0) { - std::cerr << "\033[0;31mError count: " << detail::global_error_count; - if (detail::total_ulp_distance > 0) { - std::cerr << ", total ulp distance = " << detail::total_ulp_distance << "\n\033[0m"; + std::cerr << "\033[0;31mError count: " << detail::global_error_count(); + if (detail::total_ulp_distance() > 0) { + std::cerr << ", total ulp distance = " << detail::total_ulp_distance() << "\n\033[0m"; } else { // else we overflowed the ULPs counter and all we could print is a bizarre negative number. std::cerr << "\n\033[0m"; } - detail::global_error_count = 0; - detail::total_ulp_distance = 0; + detail::global_error_count() = 0; + detail::total_ulp_distance() = 0; return 1; } std::cout << "\x1B[32mNo errors detected.\n\033[0m"; @@ -426,10 +493,21 @@ int report_errors() #define CHECK_CONDITIONED_ERROR(V, W, X, Y, Z) boost::math::test::check_conditioned_error((V), (W), (X), (Y), (Z), __FILE__, __func__, __LINE__) +#define CHECK_RELATIVE_ERROR(X, Y, Z) boost::math::test::check_relative_error((X), (Y), (Z), __FILE__, __func__, __LINE__) + #define CHECK_ABSOLUTE_ERROR(X, Y, Z) boost::math::test::check_absolute_error((X), (Y), (Z), __FILE__, __func__, __LINE__) #define CHECK_TRUE(X) boost::math::test::check_true((X), __FILE__, __func__, __LINE__) +// Without exceptions (GPU and SYCL builds, -fno-exceptions) errors don't throw, so there is nothing to check; +// as BOOST_MATH_CHECK_THROW does there, the expressions aren't evaluated. +#ifdef BOOST_MATH_NO_EXCEPTIONS +#define CHECK_THROW(x, what) +#define CHECK_NO_THROW(x) x; +#else #define CHECK_THROW(x, what) try{ x; boost::math::test::report_non_throw(__FILE__, __LINE__); }catch(const what&){} catch(...){ boost::math::test::report_incorrect_throw(__FILE__, __LINE__); } +#define CHECK_NO_THROW(x) try{ x; }catch(...){ boost::math::test::report_unexpected_throw(__FILE__, __LINE__); } +#endif + #endif diff --git a/test/naive_monte_carlo_test.cpp b/test/naive_monte_carlo_test.cpp deleted file mode 100644 index b04952c2f0..0000000000 --- a/test/naive_monte_carlo_test.cpp +++ /dev/null @@ -1,671 +0,0 @@ -/* - * Copyright Nick Thompson, 2017 - * 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) - */ -#define BOOST_TEST_MODULE naive_monte_carlo_test -#define BOOST_NAIVE_MONTE_CARLO_DEBUG_FAILURES -#include -#include -#include -#include -#include - -#include -#include -#include - -#if __has_include() -# include -#endif - -using std::abs; -using std::vector; -using std::pair; -using boost::math::constants::pi; -using boost::math::quadrature::naive_monte_carlo; - - -template -void test_pi_multithreaded() -{ - std::cout << "Testing pi is calculated correctly (multithreaded) using Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [](std::vector const & x)->Real { - Real r = x[0]*x[0]+x[1]*x[1]; - if (r <= 1) { - return 4; - } - return 0; - }; - - std::vector> bounds{{Real(0), Real(1)}, {Real(0), Real(1)}}; - Real error_goal = 0.0002; - naive_monte_carlo mc(g, bounds, error_goal, - /*singular =*/ false,/* threads = */ 2, /* seed = */ 18012); - auto task = mc.integrate(); - Real pi_estimated = task.get(); - if (abs(pi_estimated - pi())/pi() > 0.005) { - std::cout << "Error in estimation of pi too high, function calls: " << mc.calls() << "\n"; - std::cout << "Final error estimate : " << mc.current_error_estimate() << "\n"; - std::cout << "Error goal : " << error_goal << "\n"; - BOOST_CHECK_CLOSE_FRACTION(pi_estimated, pi(), 0.005); - } -} - -template -void test_pi() -{ - std::cout << "Testing pi is calculated correctly using Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [](std::vector const & x)->Real - { - Real r = x[0]*x[0]+x[1]*x[1]; - if (r <= 1) - { - return 4; - } - return 0; - }; - - std::vector> bounds{{Real(0), Real(1)}, {Real(0), Real(1)}}; - Real error_goal = (Real) 0.0002; - naive_monte_carlo mc(g, bounds, error_goal, - /*singular =*/ false,/* threads = */ 1, /* seed = */ 128402); - auto task = mc.integrate(); - Real pi_estimated = task.get(); - if (abs(pi_estimated - pi())/pi() > 0.005) - { - std::cout << "Error in estimation of pi too high, function calls: " << mc.calls() << "\n"; - std::cout << "Final error estimate : " << mc.current_error_estimate() << "\n"; - std::cout << "Error goal : " << error_goal << "\n"; - BOOST_CHECK_CLOSE_FRACTION(pi_estimated, pi(), 0.005); - } - -} - -template -void test_constant() -{ - std::cout << "Testing constants are integrated correctly using Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [](std::vector const &)->Real - { - return 1; - }; - - std::vector> bounds{{Real(0), Real(1)}, { Real(0), Real(1)}}; - naive_monte_carlo mc(g, bounds, (Real) 0.0001, - /* singular = */ false, /* threads = */ 1, /* seed = */ 87); - - auto task = mc.integrate(); - Real one = task.get(); - BOOST_CHECK_CLOSE_FRACTION(one, 1, 0.001); - BOOST_CHECK_SMALL(mc.current_error_estimate(), std::numeric_limits::epsilon()); - BOOST_CHECK(mc.calls() > 1000); -} - - -template -void test_cancel_and_restart() -{ - std::cout << "Testing that cancellation and restarting works on naive Monte-Carlo integration on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real exact = BOOST_MATH_TEST_VALUE(Real, 1.3932039296856768591842462603255); - constexpr const Real A = 1.0 / (pi() * pi() * pi()); - auto g = [&](std::vector const & x)->Real - { - return A / (1.0 - cos(x[0])*cos(x[1])*cos(x[2])); - }; - vector> bounds{{ Real(0), pi()}, { Real(0), pi()}, { Real(0), pi()}}; - naive_monte_carlo mc(g, bounds, (Real) 0.05, true, 1, 888889); - - auto task = mc.integrate(); - mc.cancel(); - Real y = task.get(); - // Super low tolerance; because it got canceled so fast: - BOOST_CHECK_CLOSE_FRACTION(y, exact, static_cast(1.0)); - - mc.update_target_error((Real) 0.01); - task = mc.integrate(); - y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, exact, 0.1); -} - -template -void test_finite_singular_boundary() -{ - std::cout << "Testing that finite singular boundaries work on naive Monte-Carlo integration on type " << boost::typeindex::type_id().pretty_name() << "\n"; - using std::pow; - using std::log; - using std::log1p; - - auto g = [](std::vector const & x)->Real - { - // The first term is singular at x = 0. - // The second at x = 1: - return pow(log(Real(1)/x[0]), Real(2)) + log1p(-x[0]); - }; - vector> bounds{{Real(0), Real(1)}}; - naive_monte_carlo mc(g, bounds, (Real) 0.01, true, 1, 1922); - - auto task = mc.integrate(); - - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, Real(1), Real(0.1)); -} - -template -void test_multithreaded_variance() -{ - std::cout << "Testing that variance computed by naive Monte-Carlo integration converges to integral formula on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real exact_variance = (Real) 1/(Real) 12; - auto g = [&](std::vector const & x)->Real - { - return x[0]; - }; - vector> bounds{{ Real(0), Real(1)}}; - naive_monte_carlo mc(g, bounds, (Real) 0.001, false, 2, 12341); - - auto task = mc.integrate(); - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, 0.5, 0.01); - BOOST_CHECK_CLOSE_FRACTION(mc.variance(), exact_variance, 0.05); -} - -template -void test_variance() -{ - std::cout << "Testing that variance computed by naive Monte-Carlo integration converges to integral formula on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real exact_variance = (Real) 1/(Real) 12; - auto g = [&](std::vector const & x)->Real - { - return x[0]; - }; - vector> bounds{{ Real(0), Real(1)}}; - naive_monte_carlo mc(g, bounds, (Real) 0.001, false, 1, 12341); - - auto task = mc.integrate(); - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, static_cast(0.5), static_cast(0.01)); - BOOST_CHECK_CLOSE_FRACTION(mc.variance(), exact_variance, 0.05); -} - -template -void test_product() -{ - std::cout << "Testing that product functions are integrated correctly by naive Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [&](std::vector const & x)->Real - { - Real y = 1; - for (uint64_t i = 0; i < x.size(); ++i) - { - y *= 2*x[i]; - } - return y; - }; - - vector> bounds(dimension); - for (uint64_t i = 0; i < dimension; ++i) - { - bounds[i] = std::make_pair(0, 1); - } - naive_monte_carlo mc(g, bounds, (Real) 0.001, false, 1, 13999); - - auto task = mc.integrate(); - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, 1, 0.01); - using std::pow; - Real exact_variance = pow(4.0/3.0, dimension) - 1; - BOOST_CHECK_CLOSE_FRACTION(mc.variance(), exact_variance, 0.1); -} - -template -void test_alternative_rng_1() -{ - std::cout << "Testing that alternative RNGs work correctly using naive Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [&](std::vector const & x)->Real - { - Real y = 1; - for (uint64_t i = 0; i < x.size(); ++i) - { - y *= 2*x[i]; - } - return y; - }; - - vector> bounds(dimension); - for (uint64_t i = 0; i < dimension; ++i) - { - bounds[i] = std::make_pair(0, 1); - } - std::cout << "Testing std::mt19937" << std::endl; - - naive_monte_carlo mc1(g, bounds, (Real) 0.001, false, 1, 1882); - - auto task = mc1.integrate(); - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, 1, 0.01); - using std::pow; - Real exact_variance = pow(4.0/3.0, dimension) - 1; - BOOST_CHECK_CLOSE_FRACTION(mc1.variance(), exact_variance, 0.05); - - std::cout << "Testing std::knuth_b" << std::endl; - naive_monte_carlo mc2(g, bounds, (Real) 0.001, false, 1, 1883); - task = mc2.integrate(); - y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, 1, 0.01); - - std::cout << "Testing std::ranlux48" << std::endl; - naive_monte_carlo mc3(g, bounds, (Real) 0.001, false, 1, 1884); - task = mc3.integrate(); - y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, 1, 0.01); -} - -template -void test_alternative_rng_2() -{ - std::cout << "Testing that alternative RNGs work correctly using naive Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [&](std::vector const & x)->Real - { - Real y = 1; - for (uint64_t i = 0; i < x.size(); ++i) - { - y *= 2*x[i]; - } - return y; - }; - - vector> bounds(dimension); - for (uint64_t i = 0; i < dimension; ++i) - { - bounds[i] = std::make_pair(0, 1); - } - - std::cout << "Testing std::default_random_engine" << std::endl; - naive_monte_carlo mc4(g, bounds, (Real) 0.001, false, 1, 1884); - auto task = mc4.integrate(); - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, 1, 0.01); - - std::cout << "Testing std::minstd_rand" << std::endl; - naive_monte_carlo mc5(g, bounds, (Real) 0.001, false, 1, 1887); - task = mc5.integrate(); - y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, 1, 0.01); - - std::cout << "Testing std::minstd_rand0" << std::endl; - naive_monte_carlo mc6(g, bounds, (Real) 0.001, false, 1, 1889); - task = mc6.integrate(); - y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, 1, 0.01); - -} - -template -void test_upper_bound_infinite() -{ - std::cout << "Testing that infinite upper bounds are integrated correctly by naive Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [](std::vector const & x)->Real - { - return 1.0/(x[0]*x[0] + 1.0); - }; - - vector> bounds(1); - for (uint64_t i = 0; i < bounds.size(); ++i) - { - bounds[i] = std::make_pair(0, std::numeric_limits::infinity()); - } - naive_monte_carlo mc(g, bounds, (Real) 0.001, true, 1, 8765); - auto task = mc.integrate(); - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, boost::math::constants::half_pi(), 0.01); -} - -template -void test_lower_bound_infinite() -{ - std::cout << "Testing that infinite lower bounds are integrated correctly by naive Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [](std::vector const & x)->Real - { - return 1.0/(x[0]*x[0] + 1.0); - }; - - vector> bounds(1); - for (uint64_t i = 0; i < bounds.size(); ++i) - { - bounds[i] = std::make_pair(-std::numeric_limits::infinity(), 0); - } - naive_monte_carlo mc(g, bounds, (Real) 0.001, true, 1, 1208); - - auto task = mc.integrate(); - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, boost::math::constants::half_pi(), 0.01); -} - -template -void test_lower_bound_infinite2() -{ - std::cout << "Testing that infinite lower bounds (2) are integrated correctly by naive Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [](std::vector const & x)->Real - { - // If x[0] = inf, this should blow up: - return (x[0]*x[0])/(x[0]*x[0]*x[0]*x[0] + 1.0); - }; - - vector> bounds(1); - for (uint64_t i = 0; i < bounds.size(); ++i) - { - bounds[i] = std::make_pair(-std::numeric_limits::infinity(), 0); - } - naive_monte_carlo mc(g, bounds, (Real) 0.001, true, 1, 1208); - auto task = mc.integrate(); - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, boost::math::constants::half_pi()/boost::math::constants::root_two(), 0.01); -} - -template -void test_double_infinite() -{ - std::cout << "Testing that double infinite bounds are integrated correctly by naive Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [](std::vector const & x)->Real - { - return 1.0/(x[0]*x[0] + 1.0); - }; - - vector> bounds(1); - for (uint64_t i = 0; i < bounds.size(); ++i) - { - bounds[i] = std::make_pair(-std::numeric_limits::infinity(), std::numeric_limits::infinity()); - } - naive_monte_carlo mc(g, bounds, (Real) 0.001, true, 1, 1776); - - auto task = mc.integrate(); - Real y = task.get(); - BOOST_CHECK_CLOSE_FRACTION(y, boost::math::constants::pi(), 0.01); -} - -template -void test_radovic() -{ - // See: Generalized Halton Sequences in 2008: A Comparative Study, function g1: - std::cout << "Testing that the Radovic function is integrated correctly by naive Monte-Carlo on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto g = [](std::vector const & x)->Real - { - using std::abs; - Real alpha = (Real)0.01; - Real z = 1; - for (uint64_t i = 0; i < dimension; ++i) - { - z *= (abs(4*x[i]-2) + alpha)/(1+alpha); - } - return z; - }; - - vector> bounds(dimension); - for (uint64_t i = 0; i < bounds.size(); ++i) - { - bounds[i] = std::make_pair(0, 1); - } - Real error_goal = (Real) 0.001; - naive_monte_carlo mc(g, bounds, error_goal, false, 1, 1982); - - auto task = mc.integrate(); - Real y = task.get(); - if (abs(y - 1) > 0.01) - { - std::cout << "Error in estimation of Radovic integral too high, function calls: " << mc.calls() << "\n"; - std::cout << "Final error estimate: " << mc.current_error_estimate() << std::endl; - std::cout << "Error goal : " << error_goal << std::endl; - std::cout << "Variance estimate : " << mc.variance() << std::endl; - BOOST_CHECK_CLOSE_FRACTION(y, 1, 0.01); - } -} - - -BOOST_AUTO_TEST_CASE(naive_monte_carlo_test) -{ - std::cout << "Default hardware concurrency = " << std::thread::hardware_concurrency() << std::endl; -#if !defined(TEST) || TEST == 1 - -#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) - test_finite_singular_boundary(); - test_finite_singular_boundary(); -#else - test_finite_singular_boundary(); - test_finite_singular_boundary(); -#endif - -#endif -#if !defined(TEST) || TEST == 2 - -#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) - test_pi(); - test_pi(); -#else - test_pi(); - test_pi(); -#endif - -#endif -#if !defined(TEST) || TEST == 3 - -#ifdef __STDCPP_FLOAT32_T__ - test_pi_multithreaded(); - test_constant(); -#else - test_pi_multithreaded(); - test_constant(); -#endif - -#endif - //test_pi(); -#if !defined(TEST) || TEST == 4 - -#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) - test_constant(); - test_cancel_and_restart(); -#else - test_constant(); - //test_constant(); - test_cancel_and_restart(); -#endif - -#endif -#if !defined(TEST) || TEST == 5 - -#ifdef __STDCPP_FLOAT32_T__ - test_variance(); -#else - test_variance(); -#endif - -#endif -#if !defined(TEST) || TEST == 6 - -#ifdef __STDCPP_FLOAT64_T__ - test_variance(); - test_multithreaded_variance(); -#else - test_variance(); - test_multithreaded_variance(); -#endif - -#endif -#if !defined(TEST) || TEST == 7 - -#ifdef __STDCPP_FLOAT32_T__ - test_product(); - test_product(); -#else - test_product(); - test_product(); -#endif - -#endif -#if !defined(TEST) || TEST == 8 - -#ifdef __STDCPP_FLOAT32_T__ - test_product(); - test_product(); - test_product(); -#else - test_product(); - test_product(); - test_product(); -#endif - -#endif -#if !defined(TEST) || TEST == 9 - -#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) - test_product(); - test_product(); -#else - test_product(); - test_product(); -#endif - -#endif -#if !defined(TEST) || TEST == 10 - -#ifdef __STDCPP_FLOAT64_T__ - test_product(); -#else - test_product(); -#endif - -#endif -#if !defined(TEST) || TEST == 11 - -#ifdef __STDCPP_FLOAT64_T__ - test_product(); - test_product(); -#else - test_product(); - test_product(); -#endif - -#endif -#if !defined(TEST) || TEST == 12 - -#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) - test_upper_bound_infinite(); - test_upper_bound_infinite(); -#else - test_upper_bound_infinite(); - test_upper_bound_infinite(); -#endif - -#endif -#if !defined(TEST) || TEST == 13 - -#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) - test_lower_bound_infinite(); - test_lower_bound_infinite(); -#else - test_lower_bound_infinite(); - test_lower_bound_infinite(); -#endif - -#endif -#if !defined(TEST) || TEST == 14 - -#ifdef __STDCPP_FLOAT32_T__ - test_lower_bound_infinite2(); -#else - test_lower_bound_infinite2(); -#endif - -#endif -#if !defined(TEST) || TEST == 15 - -#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) - test_double_infinite(); - test_double_infinite(); -#else - test_double_infinite(); - test_double_infinite(); -#endif - -#endif -#if !defined(TEST) || TEST == 16 - -#ifdef __STDCPP_FLOAT32_T__ - test_radovic(); - test_radovic(); -#else - test_radovic(); - test_radovic(); -#endif - -#endif -#if !defined(TEST) || TEST == 17 - -#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) - test_radovic(); - test_radovic(); -#else - test_radovic(); - test_radovic(); -#endif - -#endif -#if !defined(TEST) || TEST == 18 - -#ifdef __STDCPP_FLOAT64_T__ - test_radovic(); - test_radovic(); -#else - test_radovic(); - test_radovic(); -#endif - -#endif -#if !defined(TEST) || TEST == 19 - -#ifdef __STDCPP_FLOAT64_T__ - test_radovic(); - test_radovic(); -#else - test_radovic(); - test_radovic(); -#endif - -#endif -#if !defined(TEST) || TEST == 20 - -#ifdef __STDCPP_FLOAT32_T__ - test_alternative_rng_1(); -#else - test_alternative_rng_1(); -#endif - -#endif -#if !defined(TEST) || TEST == 21 - -#ifdef __STDCPP_FLOAT64_T__ - test_alternative_rng_1(); -#else - test_alternative_rng_1(); -#endif - -#endif -#if !defined(TEST) || TEST == 22 - -#ifdef __STDCPP_FLOAT32_T__ - test_alternative_rng_2(); -#else - test_alternative_rng_2(); -#endif - -#endif -#if !defined(TEST) || TEST == 23 - -#ifdef __STDCPP_FLOAT64_T__ - test_alternative_rng_2(); -#else - test_alternative_rng_2(); -#endif - -#endif - -} diff --git a/test/nvrtc_jamfile b/test/nvrtc_jamfile index e049a24d2b..d455d60553 100644 --- a/test/nvrtc_jamfile +++ b/test/nvrtc_jamfile @@ -386,3 +386,5 @@ run test_trigamma_nvrtc_double.cpp ; run test_trigamma_nvrtc_float.cpp ; run test_trunc_nvrtc_double.cpp ; +run test_pow1p_nvrtc_double.cpp ; +run test_pow1p_nvrtc_float.cpp ; diff --git a/test/octonion_test_simple.cpp b/test/octonion_test_simple.cpp index 53a9fc3d9e..59ab12e364 100644 --- a/test/octonion_test_simple.cpp +++ b/test/octonion_test_simple.cpp @@ -4,12 +4,29 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_MATH_STANDALONE #include +#endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import std; +import boost.math; +#endif +#ifndef BOOST_MATH_STANDALONE #include - +#else +// Standalone/module builds cannot use Boost.Core; map lightweight_test onto math_unit_test.hpp. +#include "math_unit_test.hpp" +#define BOOST_TEST(expr) CHECK_TRUE((expr)) +namespace boost { inline int report_errors() { return ::boost::math::test::report_errors(); } } +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include #include #include +#endif // test file for octonion.hpp diff --git a/test/ooura_fourier_integral_test.cpp b/test/ooura_fourier_integral_test.cpp deleted file mode 100644 index 59dd9eb602..0000000000 --- a/test/ooura_fourier_integral_test.cpp +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright Nick Thompson, 2019 -// 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) -#define BOOST_TEST_MODULE test_ooura_fourier_transform - -#include -#include -#include -#include -#include -#include -#include - -using boost::math::quadrature::ooura_fourier_sin; -using boost::math::quadrature::ooura_fourier_cos; -using boost::math::constants::pi; - - -float float_tol = 10*std::numeric_limits::epsilon(); -ooura_fourier_sin float_sin_integrator(float_tol); - -double double_tol = 10*std::numeric_limits::epsilon(); -ooura_fourier_sin double_sin_integrator(double_tol); - -long double long_double_tol = 10*std::numeric_limits::epsilon(); -ooura_fourier_sin long_double_sin_integrator(long_double_tol); - -template -auto get_sin_integrator() { - if constexpr (std::is_same_v) { - return float_sin_integrator; - } - if constexpr (std::is_same_v) { - return double_sin_integrator; - } - if constexpr (std::is_same_v) { - return long_double_sin_integrator; - } -} - -ooura_fourier_cos float_cos_integrator(float_tol); -ooura_fourier_cos double_cos_integrator(double_tol); -ooura_fourier_cos long_double_cos_integrator(long_double_tol); - -template -auto get_cos_integrator() { - if constexpr (std::is_same_v) { - return float_cos_integrator; - } - if constexpr (std::is_same_v) { - return double_cos_integrator; - } - if constexpr (std::is_same_v) { - return long_double_cos_integrator; - } -} - - -template -void test_ooura_eta() -{ - using boost::math::quadrature::detail::ooura_eta; - std::cout << "Testing eta function on type " << boost::typeindex::type_id().pretty_name() << "\n"; - { - Real x = 0; - Real alpha = 7; - auto [eta, eta_prime] = ooura_eta(x, alpha); - BOOST_CHECK_SMALL(eta, (std::numeric_limits::min)()); - BOOST_CHECK_CLOSE_FRACTION(eta_prime, 2 + alpha + Real(1)/Real(4), 10*std::numeric_limits::epsilon()); - } - - { - Real alpha = 4; - for (Real z = 0.125; z < 500; z += 0.125) { - Real x = std::log(z); - auto [eta, eta_prime] = ooura_eta(x, alpha); - BOOST_CHECK_CLOSE_FRACTION(eta, 2*x + alpha*(1-1/z) + (z-1)/4, 10*std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE_FRACTION(eta_prime, 2 + alpha/z + z/4, 10*std::numeric_limits::epsilon()); - } - } -} - -template -void test_ooura_sin_nodes_and_weights() -{ - using boost::math::quadrature::detail::ooura_sin_node_and_weight; - using boost::math::quadrature::detail::ooura_eta; - using std::exp; - std::cout << "Testing nodes and weights on type " << boost::typeindex::type_id().pretty_name() << "\n"; - { - long n = 1; - Real alpha = 1; - Real h = 1; - auto [node, weight] = ooura_sin_node_and_weight(n, h, alpha); - Real expected_node = pi()/(1-exp(-ooura_eta(n*h, alpha).first)); - BOOST_CHECK_CLOSE_FRACTION(node, expected_node,10*std::numeric_limits::epsilon()); - } -} - -template -void test_ooura_alpha() { - std::cout << "Testing Ooura alpha on type " << boost::typeindex::type_id().pretty_name() << "\n"; - using std::sqrt; - using std::log1p; - using boost::math::quadrature::detail::calculate_ooura_alpha; - Real alpha = calculate_ooura_alpha(Real(1)); - Real expected = 1/sqrt(16 + 4*log1p(pi())); - BOOST_CHECK_CLOSE_FRACTION(alpha, expected, 10*std::numeric_limits::epsilon()); -} - -void test_node_weight_precision_agreement() -{ - using std::abs; - using boost::math::quadrature::detail::ooura_sin_node_and_weight; - using boost::math::quadrature::detail::ooura_eta; - using boost::multiprecision::cpp_bin_float_quad; - std::cout << "Testing agreement in two different precisions of nodes and weights\n"; - cpp_bin_float_quad alpha_quad = 1; - long int_max = 128; - cpp_bin_float_quad h_quad = 1/cpp_bin_float_quad(int_max); - double alpha_dbl = 1; - double h_dbl = static_cast(h_quad); - std::cout << std::fixed; - for (long n = -1; n > -6*int_max; --n) { - auto [node_dbl, weight_dbl] = ooura_sin_node_and_weight(n, h_dbl, alpha_dbl); - auto p = ooura_sin_node_and_weight(n, h_quad, alpha_quad); - double node_quad = static_cast(p.first); - double weight_quad = static_cast(p.second); - auto node_dist = abs(boost::math::float_distance(node_quad, node_dbl)); - if ( (weight_quad < 0 && weight_dbl > 0) || (weight_dbl < 0 && weight_quad > 0) ){ - std::cout << "Weights at different precisions have different signs!\n"; - } else { - auto weight_dist = abs(boost::math::float_distance(weight_quad, weight_dbl)); - if (weight_dist > 100) { - std::cout << std::fixed; - std::cout <<"n =" << n << ", x = " << n*h_dbl << ", node distance = " << node_dist << ", weight distance = " << weight_dist << "\n"; - std::cout << std::scientific; - std::cout << "computed weight = " << weight_dbl << ", actual weight = " << weight_quad << "\n"; - } - } - } - -} - -template -void test_sinc() -{ - std::cout << "Testing sinc integral on type " << boost::typeindex::type_id().pretty_name() << "\n"; - using std::numeric_limits; - Real tol = 50*numeric_limits::epsilon(); - auto integrator = get_sin_integrator(); - auto f = [](Real x)->Real { return 1/x; }; - Real omega = 1; - while (omega < 10) - { - auto [Is, err] = integrator.integrate(f, omega); - BOOST_CHECK_CLOSE_FRACTION(Is, pi()/2, tol); - - auto [Isn, errn] = integrator.integrate(f, -omega); - BOOST_CHECK_CLOSE_FRACTION(Isn, -pi()/2, tol); - omega += 1; - } -} - - -template -void test_exp() -{ - std::cout << "Testing exponential integral on type " << boost::typeindex::type_id().pretty_name() << "\n"; - using std::exp; - using std::numeric_limits; - Real tol = 50*numeric_limits::epsilon(); - auto integrator = get_sin_integrator(); - auto f = [](Real x)->Real {return exp(-x);}; - Real omega = 1; - while (omega < 5) - { - auto [Is, err] = integrator.integrate(f, omega); - Real exact = omega/(1+omega*omega); - BOOST_CHECK_CLOSE_FRACTION(Is, exact, tol); - omega += 1; - } -} - - -template -void test_root() -{ - std::cout << "Testing integral of sin(kx)/sqrt(x) on type " << boost::typeindex::type_id().pretty_name() << "\n"; - using std::sqrt; - using std::numeric_limits; - Real tol = 10*numeric_limits::epsilon(); - auto integrator = get_sin_integrator(); - auto f = [](Real x)->Real { return 1/sqrt(x);}; - Real omega = 1; - while (omega < 5) { - auto [Is, err] = integrator.integrate(f, omega); - Real exact = sqrt(pi()/(2*omega)); - BOOST_CHECK_CLOSE_FRACTION(Is, exact, 10*tol); - omega += 1; - } -} - -// See: https://scicomp.stackexchange.com/questions/32790/numerical-evaluation-of-highly-oscillatory-integral/32799#32799 -template -Real asymptotic(Real lambda) { - using std::sin; - using std::cos; - using boost::math::constants::pi; - Real I1 = cos(lambda - pi()/4)*sqrt(2*pi()/lambda); - Real I2 = sin(lambda - pi()/4)*sqrt(2*pi()/(lambda*lambda*lambda))/8; - return I1 + I2; -} - -template -void test_double_osc() -{ - std::cout << "Testing double oscillation on type " << boost::typeindex::type_id().pretty_name() << "\n"; - using std::sqrt; - using std::numeric_limits; - auto integrator = get_sin_integrator(); - Real lambda = 7; - auto f = [&lambda](Real x)->Real { return cos(lambda*cos(x))/x; }; - Real omega = 1; - auto [Is, err] = integrator.integrate(f, omega); - Real exact = asymptotic(lambda); - BOOST_CHECK_CLOSE_FRACTION(2*Is, exact, 0.05); -} - -template -void test_zero_integrand() -{ - // Make sure relative error tolerance doesn't break on zero integrand: - std::cout << "Testing zero integrand on type " << boost::typeindex::type_id().pretty_name() << "\n"; - using std::sqrt; - using std::numeric_limits; - auto integrator = get_sin_integrator(); - auto f = [](Real /* x */)->Real { return Real(0); }; - Real omega = 1; - auto [Is, err] = integrator.integrate(f, omega); - Real exact = 0; - BOOST_CHECK_EQUAL(Is, exact); -} - - -// This works, but doesn't recover the precision you want in a unit test: -// template -// void test_log() -// { -// std::cout << "Testing integral of log(x)sin(x) on type " << boost::typeindex::type_id().pretty_name() << "\n"; -// using std::log; -// using std::exp; -// using std::numeric_limits; -// using boost::math::constants::euler; -// Real tol = 1000*numeric_limits::epsilon(); -// auto f = [](Real x)->Real { return exp(-100*numeric_limits::epsilon()*x)*log(x);}; -// Real omega = 1; -// Real Is = ooura_fourier_sin(f, omega, sqrt(numeric_limits::epsilon())/100); -// BOOST_CHECK_CLOSE_FRACTION(Is, -euler(), tol); -// } - - -template -void test_cos_integral1() -{ - std::cout << "Testing integral of cos(x)/(x*x+1) on type " << boost::typeindex::type_id().pretty_name() << "\n"; - using std::exp; - using boost::math::constants::half_pi; - using boost::math::constants::e; - using std::numeric_limits; - Real tol = 10*numeric_limits::epsilon(); - - auto integrator = get_cos_integrator(); - auto f = [](Real x)->Real { return 1/(x*x+1);}; - Real omega = 1; - auto [Is, err] = integrator.integrate(f, omega); - Real exact = half_pi()/e(); - BOOST_CHECK_CLOSE_FRACTION(Is, exact, tol); -} - -template -void test_cos_integral2() -{ - std::cout << "Testing integral of exp(-a*x) on type " << boost::typeindex::type_id().pretty_name() << "\n"; - using std::exp; - using boost::math::constants::half_pi; - using boost::math::constants::e; - using std::numeric_limits; - Real tol = 10*numeric_limits::epsilon(); - - auto integrator = get_cos_integrator(); - for (Real a = 1; a < 5; ++a) { - auto f = [&a](Real x)->Real { return exp(-a*x);}; - for(Real omega = 1; omega < 3; ++omega) { - auto [Is, err] = integrator.integrate(f, omega); - Real exact = a/(a*a+omega*omega); - BOOST_CHECK_CLOSE_FRACTION(Is, exact, 50*tol); - } - } -} - -template -void test_nodes() -{ - std::cout << "Testing nodes and weights on type " << boost::typeindex::type_id().pretty_name() << "\n"; - auto sin_integrator = get_sin_integrator(); - - auto const & big_nodes = sin_integrator.big_nodes(); - for (auto & node_row : big_nodes) { - Real t0 = node_row[0]; - for (size_t i = 1; i < node_row.size(); ++i) { - Real t1 = node_row[i]; - BOOST_CHECK(t1 > t0); - t0 = t1; - } - } - - auto const & little_nodes = sin_integrator.little_nodes(); - for (auto & node_row : little_nodes) { - Real t0 = node_row[0]; - for (size_t i = 1; i < node_row.size(); ++i) { - Real t1 = node_row[i]; - BOOST_CHECK(t1 < t0); - t0 = t1; - } - } -} - - -BOOST_AUTO_TEST_CASE(ooura_fourier_transform_test) -{ - test_cos_integral1(); - test_cos_integral1(); - test_cos_integral1(); - - test_cos_integral2(); - test_cos_integral2(); - test_cos_integral2(); - - //test_node_weight_precision_agreement(); - test_zero_integrand(); - test_zero_integrand(); - - test_ooura_eta(); - test_ooura_eta(); - test_ooura_eta(); - - test_ooura_sin_nodes_and_weights(); - test_ooura_sin_nodes_and_weights(); - test_ooura_sin_nodes_and_weights(); - - test_ooura_alpha(); - test_ooura_alpha(); - test_ooura_alpha(); - - test_sinc(); - test_sinc(); - test_sinc(); - - test_exp(); - test_exp(); - test_exp(); - - test_root(); - test_root(); - - test_double_osc(); - test_double_osc(); - // Takes too long! - //test_double_osc(); - - // This test should be last: - test_nodes(); - test_nodes(); - test_nodes(); -} diff --git a/test/pchip_test.cpp b/test/pchip_test.cpp deleted file mode 100644 index 5e8fb3c2ac..0000000000 --- a/test/pchip_test.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright Nick Thompson, 2020 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#include -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - -#if __has_include() -# include -#endif - -using boost::math::interpolators::pchip; - -template -void test_constant() -{ - - std::vector x{0,1,2,3, 9, 22, 81}; - std::vector y(x.size()); - for (auto & t : y) { - t = 7; - } - - auto x_copy = x; - auto y_copy = y; - auto pchip_spline = pchip(std::move(x_copy), std::move(y_copy)); - //std::cout << "Constant value pchip spline = " << pchip_spline << "\n"; - - auto [lo, hi] = pchip_spline.domain(); - CHECK_ULP_CLOSE(lo, 0, 1); - CHECK_ULP_CLOSE(hi, 81, 1); - - for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { - CHECK_ULP_CLOSE(Real(7), pchip_spline(t), 2); - CHECK_ULP_CLOSE(Real(0), pchip_spline.prime(t), 2); - } - - boost::circular_buffer x_buf(x.size()); - for (auto & t : x) { - x_buf.push_back(t); - } - - boost::circular_buffer y_buf(x.size()); - for (auto & t : y) { - y_buf.push_back(t); - } - - auto circular_pchip_spline = pchip(std::move(x_buf), std::move(y_buf)); - - for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { - CHECK_ULP_CLOSE(Real(7), circular_pchip_spline(t), 2); - CHECK_ULP_CLOSE(Real(0), pchip_spline.prime(t), 2); - } - - circular_pchip_spline.push_back(x.back() + 1, 7); - CHECK_ULP_CLOSE(Real(0), circular_pchip_spline.prime(x.back()+1), 2); - -} - -template -void test_linear() -{ - std::vector x{0,1,2,3}; - std::vector y{0,1,2,3}; - - auto x_copy = x; - auto y_copy = y; - auto pchip_spline = pchip(std::move(x_copy), std::move(y_copy)); - - CHECK_ULP_CLOSE(y[0], pchip_spline(x[0]), 0); - CHECK_ULP_CLOSE(Real(1)/Real(2), pchip_spline(Real(1)/Real(2)), 10); - CHECK_ULP_CLOSE(y[1], pchip_spline(x[1]), 0); - CHECK_ULP_CLOSE(Real(3)/Real(2), pchip_spline(Real(3)/Real(2)), 10); - CHECK_ULP_CLOSE(y[2], pchip_spline(x[2]), 0); - CHECK_ULP_CLOSE(Real(5)/Real(2), pchip_spline(Real(5)/Real(2)), 10); - CHECK_ULP_CLOSE(y[3], pchip_spline(x[3]), 0); - - x.resize(45); - y.resize(45); - for (size_t i = 0; i < x.size(); ++i) { - x[i] = i; - y[i] = i; - } - - x_copy = x; - y_copy = y; - pchip_spline = pchip(std::move(x_copy), std::move(y_copy)); - for (Real t = 0; t < x.back(); t += Real(0.5)) { - CHECK_ULP_CLOSE(t, pchip_spline(t), 0); - CHECK_ULP_CLOSE(Real(1), pchip_spline.prime(t), 0); - } - - x_copy = x; - y_copy = y; - // Test endpoint derivatives: - pchip_spline = pchip(std::move(x_copy), std::move(y_copy), Real(1), Real(1)); - for (Real t = 0; t < x.back(); t += Real(0.5)) { - CHECK_ULP_CLOSE(t, pchip_spline(t), 0); - CHECK_ULP_CLOSE(Real(1), pchip_spline.prime(t), 0); - } - - - boost::circular_buffer x_buf(x.size()); - for (auto & t : x) { - x_buf.push_back(t); - } - - boost::circular_buffer y_buf(x.size()); - for (auto & t : y) { - y_buf.push_back(t); - } - - auto circular_pchip_spline = pchip(std::move(x_buf), std::move(y_buf)); - - for (Real t = x[0]; t <= x.back(); t += Real(0.25)) { - CHECK_ULP_CLOSE(t, circular_pchip_spline(t), 2); - CHECK_ULP_CLOSE(Real(1), circular_pchip_spline.prime(t), 2); - } - - circular_pchip_spline.push_back(x.back() + 1, y.back()+1); - - CHECK_ULP_CLOSE(Real(y.back() + 1), circular_pchip_spline(Real(x.back()+1)), 2); - CHECK_ULP_CLOSE(Real(1), circular_pchip_spline.prime(Real(x.back()+1)), 2); - -} - -template -void test_interpolation_condition() -{ - for (size_t n = 4; n < 50; ++n) { - std::vector x(n); - std::vector y(n); - std::default_random_engine rd; - std::uniform_real_distribution dis(0,1); - Real x0 = dis(rd); - x[0] = x0; - y[0] = dis(rd); - for (size_t i = 1; i < n; ++i) { - x[i] = x[i-1] + dis(rd); - y[i] = dis(rd); - } - - auto x_copy = x; - auto y_copy = y; - auto s = pchip(std::move(x_copy), std::move(y_copy)); - //std::cout << "s = " << s << "\n"; - for (size_t i = 0; i < x.size(); ++i) { - CHECK_ULP_CLOSE(y[i], s(x[i]), 2); - } - - x_copy = x; - y_copy = y; - // The interpolation condition is not affected by the endpoint derivatives, even though these derivatives might be super weird: - s = pchip(std::move(x_copy), std::move(y_copy), Real(0), Real(0)); - //std::cout << "s = " << s << "\n"; - for (size_t i = 0; i < x.size(); ++i) { - CHECK_ULP_CLOSE(y[i], s(x[i]), 2); - } - - } -} - -template -void test_monotonicity() -{ - for (size_t n = 4; n < 50; ++n) { - std::vector x(n); - std::vector y(n); - std::default_random_engine rd; - std::uniform_real_distribution dis(0,1); - Real x0 = dis(rd); - x[0] = x0; - y[0] = dis(rd); - // Monotone increasing: - for (size_t i = 1; i < n; ++i) { - x[i] = x[i-1] + dis(rd); - y[i] = y[i-1] + dis(rd); - } - - auto x_copy = x; - auto y_copy = y; - auto s = pchip(std::move(x_copy), std::move(y_copy)); - //std::cout << "s = " << s << "\n"; - for (size_t i = 0; i < x.size() - 1; ++i) { - Real tmin = x[i]; - Real tmax = x[i+1]; - Real val = y[i]; - CHECK_ULP_CLOSE(y[i], s(x[i]), 2); - for (Real t = tmin; t < tmax; t += (tmax-tmin)/16) { - Real greater_val = s(t); - BOOST_ASSERT(val <= greater_val); - val = greater_val; - } - } - - - x[0] = dis(rd); - y[0] = dis(rd); - // Monotone decreasing: - for (size_t i = 1; i < n; ++i) { - x[i] = x[i-1] + dis(rd); - y[i] = y[i-1] - dis(rd); - } - - x_copy = x; - y_copy = y; - s = pchip(std::move(x_copy), std::move(y_copy)); - //std::cout << "s = " << s << "\n"; - for (size_t i = 0; i < x.size() - 1; ++i) { - Real tmin = x[i]; - Real tmax = x[i+1]; - Real val = y[i]; - CHECK_ULP_CLOSE(y[i], s(x[i]), 2); - for (Real t = tmin; t < tmax; t += (tmax-tmin)/16) { - Real lesser_val = s(t); - BOOST_ASSERT(val >= lesser_val); - val = lesser_val; - } - } - - } -} - - -int main() -{ -#if (__GNUC__ > 7) || defined(_MSC_VER) || defined(__clang__) - - #ifdef __STDCPP_FLOAT32_T__ - test_constant(); - test_linear(); - test_interpolation_condition(); - test_monotonicity(); - #else - test_constant(); - test_linear(); - test_interpolation_condition(); - test_monotonicity(); - #endif - - #ifdef __STDCPP_FLOAT64_T__ - test_constant(); - test_linear(); - test_interpolation_condition(); - test_monotonicity(); - #else - test_constant(); - test_linear(); - test_interpolation_condition(); - test_monotonicity(); - #endif - - test_constant(); - test_linear(); - test_interpolation_condition(); - test_monotonicity(); - - #ifdef BOOST_HAS_FLOAT128 - test_constant(); - test_linear(); - #endif -#endif - return boost::math::test::report_errors(); -} diff --git a/test/pow_test.cpp b/test/pow_test.cpp deleted file mode 100644 index 52e86b0844..0000000000 --- a/test/pow_test.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// Boost pow_test.cpp test file -// Tests the pow function - -// (C) Copyright Bruno Lalande 2008. -// (C) Copyright Matt Borland 2024. -// 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) - -#include -#include -#include - -#include -#include "../include_private/boost/math/tools/test.hpp" -#define BOOST_TEST_MAIN - -#ifdef BOOST_MATH_ENABLE_SYCL -#include "sycl/sycl.hpp" -#endif - -#include -#include - -#include -#include - -#include - -#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() -BOOST_TYPEOF_REGISTER_TYPE(boost::math::concepts::real_concept) - -using namespace boost; -using namespace boost::math; - -template -void test_pow(T base) -{ - typedef typename tools::promote_args::type result_type; - - BOOST_MATH_STD_USING - - if ((base == 0) && N < 0) - { - #ifndef BOOST_MATH_NO_EXCEPTIONS - BOOST_MATH_CHECK_THROW(math::pow(base), std::overflow_error); - #endif - } - else - { - BOOST_CHECK_CLOSE(math::pow(base), - pow(static_cast(base), static_cast(N)), - boost::math::tools::epsilon() * 100 * 400); // 400 eps as a % - } -} - -template -void test_with_big_bases() -{ - for (T base = T(); base < T(1000); ++base) - test_pow(base); -} - -template -void test_with_small_bases() -{ - T base = 0.9f; - for (int i = 0; i < 10; ++i) - { - base += base/50; - test_pow(base); - } -} - -template -void test_with_small_exponents() -{ - test_with_big_bases<0, T>(); - test_with_big_bases(); - test_with_big_bases(); - test_with_big_bases(); - test_with_big_bases(); - test_with_big_bases(); - test_with_big_bases(); - test_with_big_bases(); - test_with_big_bases(); - test_with_big_bases(); - test_with_big_bases(); - test_with_big_bases(); -} - -template -void test_with_big_exponents() -{ - test_with_small_bases(); - test_with_small_bases(); - test_with_small_bases(); - test_with_small_bases(); - test_with_small_bases(); - test_with_small_bases(); - test_with_small_bases(); - test_with_small_bases(); - test_with_small_bases(); - test_with_small_bases(); -} - - -void test_return_types() -{ - static_assert((boost::math::is_same('\1')), double>::value), "Return type mismatch"); - static_assert((boost::math::is_same(L'\2')), double>::value), "Return type mismatch"); - static_assert((boost::math::is_same(3)), double>::value), "Return type mismatch"); - static_assert((boost::math::is_same(4u)), double>::value), "Return type mismatch"); - static_assert((boost::math::is_same(5ul)), double>::value), "Return type mismatch"); - static_assert((boost::math::is_same(6.0f)), float>::value), "Return type mismatch"); - static_assert((boost::math::is_same(7.0)), double>::value), "Return type mismatch"); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - static_assert((boost::math::is_same(7.0l)), long double>::value), "Return type mismatch"); -#endif -} - - -namespace boost { namespace math { namespace policies { -template -T user_overflow_error(const char*, const char*, const T&) -{ return T(123.45); } -}}} - -namespace boost { namespace math { namespace policies { -template -T user_indeterminate_result_error(const char*, const char*, const T&) -{ return T(456.78); } -}}} - - -void test_error_policy() -{ - using namespace policies; - - BOOST_CHECK(pow<-2>( - 0.0, - policy< ::boost::math::policies::overflow_error >() - ) - == 123.45); - - BOOST_CHECK(pow<0>( - 0.0, - policy< ::boost::math::policies::indeterminate_result_error >() - ) - == 456.78); -} - -BOOST_AUTO_TEST_CASE( test_main ) -{ - using namespace std; - - cout << "Testing with integral bases and positive small exponents" << endl; - test_with_small_exponents(); - cout << "Testing with integral bases and negative small exponents" << endl; - test_with_small_exponents(); - - cout << "Testing with float precision bases and positive small exponents" << endl; - test_with_small_exponents(); - cout << "Testing with float precision bases and negative small exponents" << endl; - test_with_small_exponents(); - - cout << "Testing with float precision bases and positive big exponents" << endl; - test_with_big_exponents(); - cout << "Testing with float precision bases and negative big exponents" << endl; - test_with_big_exponents(); - - cout << "Testing with double precision bases and positive small exponents" << endl; - test_with_small_exponents(); - cout << "Testing with double precision bases and negative small exponents" << endl; - test_with_small_exponents(); - - cout << "Testing with double precision bases and positive big exponents" << endl; - test_with_big_exponents(); - cout << "Testing with double precision bases and negative big exponents" << endl; - test_with_big_exponents(); - -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - cout << "Testing with long double precision bases and positive small exponents" << endl; - test_with_small_exponents(); - cout << "Testing with long double precision bases and negative small exponents" << endl; - test_with_small_exponents(); - - cout << "Testing with long double precision bases and positive big exponents" << endl; - test_with_big_exponents(); - cout << "Testing with long double precision bases and negative big exponents" << endl; - test_with_big_exponents(); - - cout << "Testing with concepts::real_concept precision bases and positive small exponents" << endl; - test_with_small_exponents(); - cout << "Testing with concepts::real_concept precision bases and negative small exponents" << endl; - test_with_small_exponents(); - - cout << "Testing with concepts::real_concept precision bases and positive big exponents" << endl; - test_with_big_exponents(); - cout << "Testing with concepts::real_concept precision bases and negative big exponents" << endl; - test_with_big_exponents(); -#endif - - #ifndef BOOST_NO_CXX14_CONSTEXPR - static_assert(boost::math::pow<8>(2)==256, "Pow is not constexpr"); - static_assert(boost::math::pow<9>(2)==512, "Pow is not constexpr"); - static_assert(boost::math::pow<2>(2)==4, "Pow is not constexpr"); - static_assert(boost::math::pow<1>(2)==2, "Pow is not constexpr"); - static_assert(boost::math::pow<0>(2)==1, "Pow is not constexpr"); - #endif - - test_return_types(); - - test_error_policy(); -} - -/* - - Running 1 test case... - Testing with integral bases and positive small exponents - Testing with integral bases and negative small exponents - Testing with float precision bases and positive small exponents - Testing with float precision bases and negative small exponents - Testing with float precision bases and positive big exponents - Testing with float precision bases and negative big exponents - Testing with double precision bases and positive small exponents - Testing with double precision bases and negative small exponents - Testing with double precision bases and positive big exponents - Testing with double precision bases and negative big exponents - Testing with long double precision bases and positive small exponents - Testing with long double precision bases and negative small exponents - Testing with long double precision bases and positive big exponents - Testing with long double precision bases and negative big exponents - Testing with concepts::real_concept precision bases and positive small exponents - Testing with concepts::real_concept precision bases and negative small exponents - Testing with concepts::real_concept precision bases and positive big exponents - Testing with concepts::real_concept precision bases and negative big exponents - - *** No errors detected - - */ diff --git a/test/powm1_sqrtp1m1_test.cpp b/test/powm1_sqrtp1m1_test.cpp deleted file mode 100644 index c3a60b4c74..0000000000 --- a/test/powm1_sqrtp1m1_test.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// (C) Copyright John Maddock 2006. -// 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) - -#include - -#include -#define BOOST_TEST_MAIN -#include -#include -#include -#include -#include "powm1_sqrtp1m1_test.hpp" - -// -// DESCRIPTION: -// ~~~~~~~~~~~~ -// -// This file tests the functions powm1 and sqrt1pm1. -// The accuracy tests -// use values generated with NTL::RR at 1000-bit precision -// and our generic versions of these functions. -// -// Note that when this file is first run on a new platform many of -// these tests will fail: the default accuracy is 1 epsilon which -// is too tight for most platforms. In this situation you will -// need to cast a human eye over the error rates reported and make -// a judgement as to whether they are acceptable. Either way please -// report the results to the Boost mailing list. Acceptable rates of -// error are marked up below as a series of regular expressions that -// identify the compiler/stdlib/platform/data-type/test-data/test-function -// along with the maximum expected peek and RMS mean errors for that -// test. -// - -void expected_results() -{ - // - // Define the max and mean errors expected for - // various compilers and platforms. - // - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*", // test type(s) - ".*", // test data group - ".*", 5, 2); // test function - - // - // Finish off by printing out the compiler/stdlib/platform names, - // we do this to make it easier to mark up expected error rates. - // - std::cout << "Tests run with " << BOOST_COMPILER << ", " - << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; -} - -BOOST_AUTO_TEST_CASE( test_main ) -{ - expected_results(); - BOOST_MATH_CONTROL_FP; - test_powm1_sqrtp1m1(1.0F, "float"); - test_powm1_sqrtp1m1(1.0, "double"); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_powm1_sqrtp1m1(1.0L, "long double"); -#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS - test_powm1_sqrtp1m1(boost::math::concepts::real_concept(), "real_concept"); -#endif -#else - std::cout << "The long double tests have been disabled on this platform " - "either because the long double overloads of the usual math functions are " - "not available at all, or because they are too inaccurate for these tests " - "to pass." << std::endl; -#endif -} - - diff --git a/test/quartic_roots_test.cpp b/test/quartic_roots_test.cpp deleted file mode 100644 index f46330e3d1..0000000000 --- a/test/quartic_roots_test.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright Nick Thompson, 2021 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - -using boost::math::tools::quartic_roots; -using std::cbrt; -using std::sqrt; - -template -void test_zero_coefficients() -{ - Real a = 0; - Real b = 0; - Real c = 0; - Real d = 0; - Real e = 0; - auto roots = quartic_roots(a,b,c,d,e); - CHECK_EQUAL(roots[0], Real(0)); - CHECK_EQUAL(roots[1], Real(0)); - CHECK_EQUAL(roots[2], Real(0)); - CHECK_EQUAL(roots[3], Real(0)); - - b = 1; - e = 1; - // x^3 + 1 = 0: - roots = quartic_roots(a,b,c,d,e); - CHECK_EQUAL(roots[0], Real(-1)); - CHECK_NAN(roots[1]); - CHECK_NAN(roots[2]); - CHECK_NAN(roots[3]); - e = -1; - // x^3 - 1 = 0: - roots = quartic_roots(a,b,c,d,e); - CHECK_EQUAL(roots[0], Real(1)); - CHECK_NAN(roots[1]); - CHECK_NAN(roots[2]); - CHECK_NAN(roots[3]); - - e = -2; - // x^3 - 2 = 0 - roots = quartic_roots(a,b,c,d,e); - CHECK_ULP_CLOSE(roots[0], cbrt(Real(2)), 2); - CHECK_NAN(roots[1]); - CHECK_NAN(roots[2]); - CHECK_NAN(roots[3]); - - // x^4 -1 = 0 - // x = \pm 1: - roots = quartic_roots(1, 0, 0, 0, -1); - CHECK_ULP_CLOSE(Real(-1), roots[0], 3); - CHECK_ULP_CLOSE(Real(1), roots[1], 3); - CHECK_NAN(roots[2]); - CHECK_NAN(roots[3]); - - // x^4 - 2 = 0 \implies x = \pm sqrt(sqrt(2)) - roots = quartic_roots(1,0,0,0,-2); - CHECK_ULP_CLOSE(-sqrt(sqrt(Real(2))), roots[0], 3); - CHECK_ULP_CLOSE(sqrt(sqrt(Real(2))), roots[1], 3); - CHECK_NAN(roots[2]); - CHECK_NAN(roots[3]); - - - // x(x-1)(x-2)(x-3) = x^4 - 6x^3 + 11x^2 - 6x - roots = quartic_roots(Real(1), Real(-6), Real(11), Real(-6), Real(0)); - CHECK_ULP_CLOSE(roots[0], Real(0), 2); - CHECK_ULP_CLOSE(roots[1], Real(1), 2); - CHECK_ULP_CLOSE(roots[2], Real(2), 2); - CHECK_ULP_CLOSE(roots[3], Real(3), 2); - - // (x-1)(x-2)(x-3)(x-4) = x^4 - 10x^3 + 35x^2 - (2*3*4 + 1*3*4 + 1*2*4 + 1*2*3)x + 1*2*3*4 - roots = quartic_roots(1, -10, 35, -24 - 12 - 8 - 6, 1*2*3*4); - CHECK_ULP_CLOSE(Real(1), roots[0], 2); - CHECK_ULP_CLOSE(Real(2), roots[1], 2); - CHECK_ULP_CLOSE(Real(3), roots[2], 2); - CHECK_ULP_CLOSE(Real(4), roots[3], 2); - - // Double root: - // (x+1)^2(x-2)(x-3) = x^4 - 3x^3 -3x^2 + 7x + 6 - // Note: This test is unstable wrt to perturbations! - roots = quartic_roots(Real(1), Real(-3), Real(-3), Real(7), Real(6)); - CHECK_ULP_CLOSE(Real(-1), roots[0], 2); - CHECK_ULP_CLOSE(Real(-1), roots[1], 2); - CHECK_ULP_CLOSE(Real(2), roots[2], 2); - CHECK_ULP_CLOSE(Real(3), roots[3], 2); - - - std::uniform_real_distribution dis(-2,2); - std::mt19937 gen(12343); - // Expected roots - std::array r; - int trials = 10; - for (int i = 0; i < trials; ++i) { - // Mathematica: - // Expand[(x - r0)*(x - r1)*(x - r2)*(x-r3)] - // r0 r1 r2 r3 - (r0 r1 r2 + r0 r1 r3 + r0 r2 r3 + r1r2r3)x - // + (r0 r1 + r0 r2 + r0 r3 + r1 r2 + r1r3 + r2 r3)x^2 - (r0 + r1 + r2 + r3) x^3 + x^4 - for (auto & root : r) { - root = static_cast(dis(gen)); - } - std::sort(r.begin(), r.end()); - a = 1; - b = -(r[0] + r[1] + r[2] + r[3]); - c = r[0]*r[1] + r[0]*r[2] + r[0]*r[3] + r[1]*r[2] + r[1]*r[3] + r[2]*r[3]; - d = -(r[0]*r[1]*r[2] + r[0]*r[1]*r[3] + r[0]*r[2]*r[3] + r[1]*r[2]*r[3]); - e = r[0]*r[1]*r[2]*r[3]; - - roots = quartic_roots(a, b, c, d, e); - // I could check the condition number here, but this is fine right? - CHECK_ULP_CLOSE(r[0], roots[0], 340); - CHECK_ULP_CLOSE(r[1], roots[1], 440); - CHECK_ULP_CLOSE(r[2], roots[2], 220); - CHECK_ULP_CLOSE(r[3], roots[3], 160); - } -} - -void issue_825() { - using std::sqrt; - using std::cbrt; - double a = 1; - double b = 1; - double c = 1; - double d = 1; - double e = -4; - std::array roots = boost::math::tools::quartic_roots(a, b, c, d, e); - // The real roots are 1 and -1.6506 - // Wolfram alpha: Roots[x^4 + x^3 + x^2 + x == 4] - double expected = (-2 - cbrt(25/(3*sqrt(6.0) - 7)) + cbrt(5*(3*sqrt(6.0) - 7)))/3; - CHECK_ULP_CLOSE(expected, roots[0], 5); - CHECK_ULP_CLOSE(1.0, roots[1], 5); - CHECK_NAN(roots[2]); - CHECK_NAN(roots[3]); -} - -void issue_1055() { - double a = 1.0; - double b = -547.5045576653938; - double c = 75042.069484941996; - double d = 273.7522788326969; - double e = 0.24965766552610175; - std::array roots = boost::math::tools::quartic_roots(a, b, c, d, e); - // This is accurate to 1e-9 on every platform *except* cygwin/g++11/c++17: - CHECK_ABSOLUTE_ERROR(-0.00182420203946279, roots[0], 1e-6); - CHECK_ABSOLUTE_ERROR(-0.00182370927680797, roots[1], 1e-6); - CHECK_NAN(roots[2]); - CHECK_NAN(roots[3]); -} - - -int main() -{ - test_zero_coefficients(); - test_zero_coefficients(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_zero_coefficients(); -#endif - issue_825(); - issue_1055(); - return boost::math::test::report_errors(); -} diff --git a/test/quaternion_constexpr_test.cpp b/test/quaternion_constexpr_test.cpp deleted file mode 100644 index d212abe2ff..0000000000 --- a/test/quaternion_constexpr_test.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// test file for quaternion.hpp - -// (C) Copyright Hubert Holin 2001. -// 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) - - -#include - -typedef boost::math::quaternion qt; -typedef std::complex ct; - -#ifndef BOOST_NO_CXX14_CONSTEXPR - -constexpr qt full_constexpr_test(qt a, qt b, double d, ct c) -{ - a.swap(b); - qt result(a), t; - result += d; - result += c; - result += b; - t = result; - t = d; - t = c; - result -= d; - result -= c; - result -= a; - result *= d; - result *= c; - result *= a; - result /= d; - result /= c; - result /= b; - - result += a + d; - result += d + a; - result += a + c; - result += c + a; - result += a + b; - - result += a - d; - result += d - a; - result += a - c; - result += c - a; - result += a - b; - - result += a * d; - result += d * a; - result += a * c; - result += c * a; - result += a * b; - - result += a / d; - result += d / a; - result += a / c; - result += c / a; - result += a / b; - - result += norm(a); - result += conj(a); - - return result; -} - -#endif - -int main() -{ -#ifndef BOOST_NO_CXX11_CONSTEXPR - - constexpr qt q1; - constexpr qt q2(2.0); - constexpr qt q3(2.0, 3.0); - constexpr qt q4(2.0, 3.9, 3.0); - constexpr qt q5(2.0, 3.9, 3.0, 5.); - - constexpr ct c1(2., 3.); - constexpr qt q6(c1); - constexpr qt q7(c1, c1); - constexpr qt q8(q1); - - constexpr double d1 = q5.real(); - constexpr qt q9 = q1.unreal(); - constexpr double d2 = q1.R_component_1(); - constexpr double d3 = q1.R_component_2(); - constexpr double d4 = q1.R_component_3(); - constexpr double d5 = q1.R_component_4(); - constexpr ct c2 = q1.C_component_1(); - constexpr ct c3 = q1.C_component_1(); - - constexpr qt q10 = q1 + d1; - constexpr qt q11 = d1 + q1; - constexpr qt q14 = q1 + q2; - - constexpr qt q15 = q1 - d1; - constexpr qt q16 = d1 - q1; - constexpr qt q19 = q1 - q2; - - constexpr qt q20 = q1 * d1; - constexpr qt q21 = d1 * q1; - constexpr qt q22 = q5 / d1; - - constexpr double d6 = real(q5); - constexpr qt q23 = unreal(q1); - - constexpr bool b1 = q1 == d1; - constexpr bool b2 = d1 == q1; - constexpr bool b3 = q1 != d1; - constexpr bool b4 = d1 != q1; - - constexpr bool b5 = q1 == c2; - constexpr bool b6 = c2 == q1; - constexpr bool b7 = q1 != c2; - constexpr bool b8 = c2 != q1; - constexpr bool b9 = q2 == q1; - constexpr bool b10 = q1 != q2; - - (void)q9; - (void)d2; - (void)d3; - (void)d4; - (void)d6; - (void)d5; - (void)c3; - (void)q10; - (void)q11; - (void)q14; - (void)q15; - (void)q16; - (void)q19; - (void)q20; - (void)q21; - (void)q22; - (void)q23; - (void)b1; - (void)b2; - (void)b3; - (void)b4; - (void)b5; - (void)b6; - (void)b7; - (void)b8; - (void)b9; - (void)b10; - (void)q3; - (void)q4; - (void)q6; - (void)q7; - (void)q8; - -#endif - -#ifndef BOOST_NO_CXX14_CONSTEXPR - - constexpr qt q12 = c2 + q1; - constexpr qt q13 = q1 + c2; - - constexpr qt q17 = c2 - q1; - constexpr qt q18 = q1 - c2; - - constexpr qt q24 = full_constexpr_test(q5, q5 + 1, 3.2, q5.C_component_1()); - - (void)q12; - (void)q13; - (void)q17; - (void)q18; - (void)q24; - -#endif - - return 0; -} diff --git a/test/quintic_hermite_test.cpp b/test/quintic_hermite_test.cpp deleted file mode 100644 index d2deec7709..0000000000 --- a/test/quintic_hermite_test.cpp +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Copyright Nick Thompson, 2020 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - -#if __has_include() -# include -#endif - -using boost::math::interpolators::quintic_hermite; -using boost::math::interpolators::cardinal_quintic_hermite; -using boost::math::interpolators::cardinal_quintic_hermite_aos; - -template -void test_constant() -{ - std::vector x{0,1,2,3, 9, 22, 81}; - std::vector y(x.size()); - std::vector dydx(x.size(), 0); - std::vector d2ydx2(x.size(), 0); - for (auto & t : y) - { - t = 7; - } - - auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - for (Real t = 0; t <= 81; t += Real(0.25)) - { - CHECK_ULP_CLOSE(Real(7), qh(t), 24); - CHECK_ULP_CLOSE(Real(0), qh.prime(t), 24); - CHECK_ULP_CLOSE(Real(0), qh.double_prime(t), 24); - } -} - - -template -void test_linear() -{ - std::vector x{0,1,2,3, 4,5,6,7,8,9}; - std::vector y = x; - std::vector dydx(x.size(), 1); - std::vector d2ydx2(x.size(), 0); - - auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - - for (Real t = 0; t <= 9; t += Real(0.25)) - { - CHECK_ULP_CLOSE(Real(t), qh(t), 2); - CHECK_ULP_CLOSE(Real(1), qh.prime(t), 2); - CHECK_ULP_CLOSE(Real(0), qh.double_prime(t), 2); - } - - boost::random::mt19937 rng; - boost::random::uniform_real_distribution dis(Real(0.5), Real(1)); - x.resize(512); - x[0] = dis(rng); - Real xmin = x[0]; - for (size_t i = 1; i < x.size(); ++i) - { - x[i] = x[i-1] + dis(rng); - } - Real xmax = x.back(); - - y = x; - dydx.resize(x.size(), 1); - d2ydx2.resize(x.size(), 0); - - qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - - for (Real t = xmin; t <= xmax; t += Real(0.125)) - { - CHECK_ULP_CLOSE(t, qh(t), 2); - CHECK_ULP_CLOSE(Real(1), qh.prime(t), 100); - CHECK_MOLLIFIED_CLOSE(Real(0), qh.double_prime(t), 200*std::numeric_limits::epsilon()); - } -} - -template -void test_quadratic() -{ - - std::vector x{0,1,2,3, 4,5,6,7,8,9}; - std::vector y(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = x[i]*x[i]/2; - } - - std::vector dydx(x.size()); - for (size_t i = 0; i < y.size(); ++i) { - dydx[i] = x[i]; - } - - std::vector d2ydx2(x.size(), 1); - - auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - - for (Real t = 0; t <= 9; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(Real(t*t)/2, qh(t), 2); - CHECK_ULP_CLOSE(t, qh.prime(t), 12); - CHECK_ULP_CLOSE(Real(1), qh.double_prime(t), 32); - } - - boost::random::mt19937 rng; - boost::random::uniform_real_distribution dis(Real(0.5), Real(1)); - x.resize(8); - x[0] = dis(rng); - Real xmin = x[0]; - for (size_t i = 1; i < x.size(); ++i) - { - x[i] = x[i-1] + dis(rng); - } - Real xmax = x.back(); - - y.resize(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = x[i]*x[i]/2; - } - - dydx.resize(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - dydx[i] = x[i]; - } - - d2ydx2.resize(x.size(), 1); - - qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - - for (Real t = xmin; t <= xmax; t += Real(0.125)) - { - CHECK_ULP_CLOSE(Real(t*t)/2, qh(t), 4); - CHECK_ULP_CLOSE(t, qh.prime(t), 53); - CHECK_ULP_CLOSE(Real(1), qh.double_prime(t), 700); - } -} - -template -void test_cubic() -{ - - std::vector x{0,1,2,3, 4,5,6,7,8,9}; - std::vector y(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = x[i]*x[i]*x[i]; - } - - std::vector dydx(x.size()); - for (size_t i = 0; i < y.size(); ++i) { - dydx[i] = 3*x[i]*x[i]; - } - - std::vector d2ydx2(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - d2ydx2[i] = 6*x[i]; - } - - auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - - for (Real t = 0; t <= 9; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(t*t*t, qh(t), 10); - CHECK_ULP_CLOSE(3*t*t, qh.prime(t), 15); - CHECK_ULP_CLOSE(6*t, qh.double_prime(t), 20); - } -} - -template -void test_quartic() -{ - - std::vector x{0,1,2,3, 4,5,6,7,8,9, 10, 11}; - std::vector y(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = x[i]*x[i]*x[i]*x[i]; - } - - std::vector dydx(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - dydx[i] = 4*x[i]*x[i]*x[i]; - } - - std::vector d2ydx2(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - d2ydx2[i] = 12*x[i]*x[i]; - } - - auto qh = quintic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2)); - - for (Real t = 1; t <= 11; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(t*t*t*t, qh(t), 100); - CHECK_ULP_CLOSE(4*t*t*t, qh.prime(t), 100); - CHECK_ULP_CLOSE(12*t*t, qh.double_prime(t), 100); - } -} - - -template -void test_interpolation_condition() -{ - for (size_t n = 4; n < 50; ++n) { - std::vector x(n); - std::vector y(n); - std::vector dydx(n); - std::vector d2ydx2(n); - boost::random::mt19937 rd; - boost::random::uniform_real_distribution dis(0,1); - Real x0 = dis(rd); - x[0] = x0; - y[0] = dis(rd); - for (size_t i = 1; i < n; ++i) { - x[i] = x[i-1] + dis(rd); - y[i] = dis(rd); - dydx[i] = dis(rd); - d2ydx2[i] = dis(rd); - } - - auto x_copy = x; - auto y_copy = y; - auto dydx_copy = dydx; - auto d2ydx2_copy = d2ydx2; - auto s = quintic_hermite(std::move(x_copy), std::move(y_copy), std::move(dydx_copy), std::move(d2ydx2_copy)); - //std::cout << "s = " << s << "\n"; - for (size_t i = 0; i < x.size(); ++i) { - CHECK_ULP_CLOSE(y[i], s(x[i]), 2); - CHECK_ULP_CLOSE(dydx[i], s.prime(x[i]), 2); - CHECK_ULP_CLOSE(d2ydx2[i], s.double_prime(x[i]), 2); - } - } -} - -template -void test_cardinal_constant() -{ - - std::vector y(25); - std::vector dydx(y.size(), 0); - std::vector d2ydx2(y.size(), 0); - for (auto & t : y) { - t = 7; - } - Real x0 = 4; - Real dx = Real(1)/Real(8); - - auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - - for (Real t = x0; t <= x0 + 24*dx; t += Real(0.25)) - { - CHECK_ULP_CLOSE(Real(7), qh(t), 24); - CHECK_ULP_CLOSE(Real(0), qh.prime(t), 24); - CHECK_ULP_CLOSE(Real(0), qh.double_prime(t), 24); - } - - std::vector> data(25); - for (size_t i = 0; i < data.size(); ++i) - { - data[i][0] = 7; - data[i][1] = 0; - data[i][2] = 0; - } - - auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - for (Real t = x0; t <= x0 + 24*dx; t += Real(0.25)) - { - CHECK_ULP_CLOSE(Real(7), qh_aos(t), 24); - CHECK_ULP_CLOSE(Real(0), qh_aos.prime(t), 24); - CHECK_ULP_CLOSE(Real(0), qh_aos.double_prime(t), 24); - } - - // Now check the boundaries: - auto [tlo, thi] = qh.domain(); - int samples = 5000; - int i = 0; - while (i++ < samples) - { - CHECK_ULP_CLOSE(Real(7), qh(tlo), 2); - CHECK_ULP_CLOSE(Real(7), qh(thi), 2); - CHECK_ULP_CLOSE(Real(7), qh_aos(tlo), 2); - CHECK_ULP_CLOSE(Real(7), qh_aos(thi), 2); - CHECK_ULP_CLOSE(Real(0), qh.prime(tlo), 2); - CHECK_ULP_CLOSE(Real(0), qh.prime(thi), 2); - CHECK_ULP_CLOSE(Real(0), qh_aos.prime(tlo), 2); - CHECK_ULP_CLOSE(Real(0), qh_aos.prime(thi), 2); - - tlo = boost::math::nextafter(tlo, (std::numeric_limits::max)()); - thi = boost::math::nextafter(thi, std::numeric_limits::lowest()); - } -} - - -template -void test_cardinal_linear() -{ - std::vector y{0,1,2,3,4,5,6,7,8,9}; - Real x0 = 0; - Real dx = 1; - std::vector dydx(y.size(), 1); - std::vector d2ydx2(y.size(), 0); - - auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - - for (Real t = 0; t <= 9; t += Real(0.25)) { - CHECK_ULP_CLOSE(Real(t), qh(t), 2); - CHECK_ULP_CLOSE(Real(1), qh.prime(t), 2); - CHECK_ULP_CLOSE(Real(0), qh.double_prime(t), 2); - } - - std::vector> data(10); - for (size_t i = 0; i < data.size(); ++i) { - data[i][0] = i; - data[i][1] = 1; - data[i][2] = 0; - } - - auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - - for (Real t = 0; t <= 9; t += Real(0.25)) { - CHECK_ULP_CLOSE(Real(t), qh_aos(t), 2); - CHECK_ULP_CLOSE(Real(1), qh_aos.prime(t), 2); - CHECK_ULP_CLOSE(Real(0), qh_aos.double_prime(t), 2); - } - - // Now check the boundaries: - auto [tlo, thi] = qh.domain(); - int samples = 5000; - int i = 0; - while (i++ < samples) - { - CHECK_ULP_CLOSE(Real(tlo), qh(tlo), 2); - CHECK_ULP_CLOSE(Real(thi), qh(thi), 2); - CHECK_ULP_CLOSE(Real(tlo), qh_aos(tlo), 2); - CHECK_ULP_CLOSE(Real(thi), qh_aos(thi), 2); - CHECK_ULP_CLOSE(Real(1), qh.prime(tlo), 2); - CHECK_ULP_CLOSE(Real(1), qh.prime(thi), 128); - CHECK_ULP_CLOSE(Real(1), qh_aos.prime(tlo), 2); - CHECK_ULP_CLOSE(Real(1), qh_aos.prime(thi), 128); - - tlo = boost::math::nextafter(tlo, (std::numeric_limits::max)()); - thi = boost::math::nextafter(thi, std::numeric_limits::lowest()); - } -} - -template -void test_cardinal_quadratic() -{ - Real x0 = 0; - Real dx = 1; - std::vector y(10); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = i*i/Real(2); - } - - std::vector dydx(y.size()); - for (size_t i = 0; i < y.size(); ++i) { - dydx[i] = i; - } - - std::vector d2ydx2(y.size(), 1); - - auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - - for (Real t = 0; t <= 9; t += Real(0.0078125)) { - Real computed = qh(t); - CHECK_ULP_CLOSE(Real(t*t)/2, computed, 2); - CHECK_ULP_CLOSE(t, qh.prime(t), 15); - CHECK_ULP_CLOSE(Real(1), qh.double_prime(t), 32); - } - - std::vector> data(10); - for (size_t i = 0; i < data.size(); ++i) { - data[i][0] = i*i/Real(2); - data[i][1] = i; - data[i][2] = 1; - } - auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - - for (Real t = 0; t <= 9; t += Real(0.0078125)) - { - Real computed = qh_aos(t); - CHECK_ULP_CLOSE(Real(t*t)/2, computed, 2); - CHECK_ULP_CLOSE(t, qh_aos.prime(t), 12); - CHECK_ULP_CLOSE(Real(1), qh_aos.double_prime(t), 64); - } - - // Now check the boundaries: - auto [tlo, thi] = qh.domain(); - int samples = 5000; - int i = 0; - while (i++ < samples) - { - CHECK_ULP_CLOSE(tlo*tlo/2, qh(tlo), 16); - CHECK_ULP_CLOSE(thi*thi/2, qh(thi), 16); - CHECK_ULP_CLOSE(tlo*tlo/2, qh_aos(tlo), 16); - CHECK_ULP_CLOSE(thi*thi/2, qh_aos(thi), 16); - CHECK_ULP_CLOSE(tlo, qh.prime(tlo), 16); - CHECK_ULP_CLOSE(thi, qh.prime(thi), 64); - CHECK_ULP_CLOSE(tlo, qh_aos.prime(tlo), 16); - CHECK_ULP_CLOSE(thi, qh_aos.prime(thi), 64); - - tlo = boost::math::nextafter(tlo, (std::numeric_limits::max)()); - thi = boost::math::nextafter(thi, std::numeric_limits::lowest()); - } -} - -template -void test_cardinal_cubic() -{ - Real x0 = 0; - Real dx = 1; - std::vector y(10); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = i*i*i; - } - - std::vector dydx(y.size()); - for (size_t i = 0; i < y.size(); ++i) { - dydx[i] = 3*i*i; - } - - std::vector d2ydx2(y.size()); - for (size_t i = 0; i < y.size(); ++i) { - d2ydx2[i] = 6*i; - } - - auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - - for (Real t = 0; t <= 9; t += Real(0.0078125)) - { - Real computed = qh(t); - CHECK_ULP_CLOSE(t*t*t, computed, 10); - CHECK_ULP_CLOSE(3*t*t, qh.prime(t), 15); - CHECK_ULP_CLOSE(6*t, qh.double_prime(t), 39); - } - - std::vector> data(10); - for (size_t i = 0; i < data.size(); ++i) { - data[i][0] = i*i*i; - data[i][1] = 3*i*i; - data[i][2] = 6*i; - } - - auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t <= 9; t += Real(0.0078125)) - { - Real computed = qh_aos(t); - CHECK_ULP_CLOSE(t*t*t, computed, 10); - CHECK_ULP_CLOSE(3*t*t, qh_aos.prime(t), 15); - CHECK_ULP_CLOSE(6*t, qh_aos.double_prime(t), 30); - } -} - -template -void test_cardinal_quartic() -{ - Real x0 = 0; - Real dx = 1; - std::vector y(7); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = i*i*i*i; - } - - std::vector dydx(y.size()); - for (size_t i = 0; i < y.size(); ++i) { - dydx[i] = 4*i*i*i; - } - - std::vector d2ydx2(y.size()); - for (size_t i = 0; i < y.size(); ++i) { - d2ydx2[i] = 12*i*i; - } - - auto qh = cardinal_quintic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); - - for (Real t = 0; t <= 6; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(Real(t*t*t*t), qh(t), 250); - CHECK_ULP_CLOSE(4*t*t*t, qh.prime(t), 250); - CHECK_ULP_CLOSE(12*t*t, qh.double_prime(t), 250); - } - - std::vector> data(7); - for (size_t i = 0; i < data.size(); ++i) { - data[i][0] = i*i*i*i; - data[i][1] = 4*i*i*i; - data[i][2] = 12*i*i; - } - - auto qh_aos = cardinal_quintic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t <= 6; t += Real(0.0078125)) - { - Real computed = qh_aos(t); - CHECK_ULP_CLOSE(t*t*t*t, computed, 10); - CHECK_ULP_CLOSE(4*t*t*t, qh_aos.prime(t), 64); - CHECK_ULP_CLOSE(12*t*t, qh_aos.double_prime(t), 128); - } -} - - -int main() -{ - #ifdef __STDCPP_FLOAT32_T__ - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - - test_cardinal_constant(); - test_cardinal_linear(); - test_cardinal_quadratic(); - test_cardinal_cubic(); - test_cardinal_quartic(); - #else - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - - test_cardinal_constant(); - test_cardinal_linear(); - test_cardinal_quadratic(); - test_cardinal_cubic(); - test_cardinal_quartic(); - #endif - - #ifdef __STDCPP_FLOAT64_T__ - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - - test_cardinal_constant(); - test_cardinal_linear(); - test_cardinal_quadratic(); - test_cardinal_cubic(); - test_cardinal_quartic(); - #else - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - - test_cardinal_constant(); - test_cardinal_linear(); - test_cardinal_quadratic(); - test_cardinal_cubic(); - test_cardinal_quartic(); - #endif - - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - - test_cardinal_constant(); - test_cardinal_linear(); - test_cardinal_quadratic(); - test_cardinal_cubic(); - test_cardinal_quartic(); - - #ifdef BOOST_HAS_FLOAT128 - test_constant(); - //test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - test_cardinal_constant(); - test_cardinal_linear(); - test_cardinal_quadratic(); - test_cardinal_cubic(); - test_cardinal_quartic(); - #endif - - return boost::math::test::report_errors(); -} diff --git a/test/random_search_test.cpp b/test/random_search_test.cpp deleted file mode 100644 index 51eccf7450..0000000000 --- a/test/random_search_test.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright Nick Thompson, 2024 - * 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) - */ - -#include "math_unit_test.hpp" -#include "test_functions_for_optimization.hpp" -#include -#include -#include -using boost::math::optimization::random_search; -using boost::math::optimization::random_search_parameters; - - -template void test_ackley() { - std::cout << "Testing random search on Ackley function . . .\n"; - using ArgType = std::array; - auto rs_params = random_search_parameters(); - rs_params.lower_bounds = {-5, -5}; - rs_params.upper_bounds = {5, 5}; - // This makes the CI a bit more robust; - // the computation is only deterministic with a deterministic number of threads: - rs_params.threads = 2; - rs_params.max_function_calls *= 10; - std::mt19937_64 gen(12345); - auto local_minima = random_search(ackley, rs_params, gen); - CHECK_LE(std::abs(local_minima[0]), Real(0.2)); - CHECK_LE(std::abs(local_minima[1]), Real(0.2)); - - // Does it work with a lambda? - auto ack = [](std::array const &x) { return ackley(x); }; - local_minima = random_search(ack, rs_params, gen); - CHECK_LE(std::abs(local_minima[0]), Real(0.2)); - CHECK_LE(std::abs(local_minima[1]), Real(0.2)); - - // Test that if an intial guess is the exact solution, the returned solution is the exact solution: - std::array initial_guess{0, 0}; - rs_params.initial_guess = &initial_guess; - local_minima = random_search(ack, rs_params, gen); - CHECK_EQUAL(local_minima[0], Real(0)); - CHECK_EQUAL(local_minima[1], Real(0)); - - std::atomic cancel = false; - Real target_value = 0.0; - std::atomic current_minimum_cost = std::numeric_limits::quiet_NaN(); - // Test query storage: - std::vector> queries; - local_minima = random_search(ack, rs_params, gen, target_value, &cancel, ¤t_minimum_cost, &queries); - CHECK_EQUAL(local_minima[0], Real(0)); - CHECK_EQUAL(local_minima[1], Real(0)); - CHECK_LE(size_t(1), queries.size()); - for (auto const & q : queries) { - auto expected = ackley(q.first); - CHECK_EQUAL(expected, q.second); - } -} - - -template void test_rosenbrock_saddle() { - std::cout << "Testing random search on Rosenbrock saddle . . .\n"; - using ArgType = std::array; - auto rs_params = random_search_parameters(); - rs_params.lower_bounds = {0.5, 0.5}; - rs_params.upper_bounds = {2.048, 2.048}; - rs_params.max_function_calls = 20000; - rs_params.threads = 2; - std::mt19937_64 gen(234568); - auto local_minima = random_search(rosenbrock_saddle, rs_params, gen); - - CHECK_ABSOLUTE_ERROR(Real(1), local_minima[0], Real(0.05)); - CHECK_ABSOLUTE_ERROR(Real(1), local_minima[1], Real(0.05)); - - // Does cancellation work? - std::atomic cancel = true; - gen.seed(12345); - local_minima = - random_search(rosenbrock_saddle, rs_params, gen, std::numeric_limits::quiet_NaN(), &cancel); - CHECK_GE(std::abs(local_minima[0] - Real(1)), std::sqrt(std::numeric_limits::epsilon())); -} - - -template void test_rastrigin() { - std::cout << "Testing random search on Rastrigin function (global minimum = (0,0,...,0))\n"; - using ArgType = std::vector; - auto rs_params = random_search_parameters(); - rs_params.lower_bounds.resize(3, static_cast(-5.12)); - rs_params.upper_bounds.resize(3, static_cast(5.12)); - rs_params.max_function_calls = 1000000; - rs_params.threads = 2; - std::mt19937_64 gen(34567); - - // By definition, the value of the function which a target value is provided must be <= target_value. - Real target_value = 2.0; - auto local_minima = random_search(rastrigin, rs_params, gen, target_value); - CHECK_LE(rastrigin(local_minima), target_value); -} - - -// Tests NaN return types and return type != input type: -void test_sphere() { - std::cout << "Testing random search on sphere . . .\n"; - using ArgType = std::vector; - auto rs_params = random_search_parameters(); - rs_params.lower_bounds.resize(4, -1); - rs_params.upper_bounds.resize(4, 1); - rs_params.max_function_calls = 100000; - rs_params.threads = 2; - std::mt19937_64 gen(56789); - auto local_minima = random_search(sphere, rs_params, gen); - for (auto x : local_minima) { - CHECK_ABSOLUTE_ERROR(0.0f, x, 0.5f); - } -} - - -template -void test_three_hump_camel() { - std::cout << "Testing random search on three hump camel . . .\n"; - using ArgType = std::array; - auto rs_params = random_search_parameters(); - rs_params.lower_bounds[0] = -5.0; - rs_params.lower_bounds[1] = -5.0; - rs_params.upper_bounds[0] = 5.0; - rs_params.upper_bounds[1] = 5.0; - rs_params.threads = 2; - rs_params.max_function_calls *= 10; - std::mt19937_64 gen(56789); - auto local_minima = random_search(three_hump_camel, rs_params, gen); - for (auto x : local_minima) { - CHECK_ABSOLUTE_ERROR(0.0f, x, 0.2f); - } -} - - -template -void test_beale() { - std::cout << "Testing random search on the Beale function . . .\n"; - using ArgType = std::array; - auto rs_params = random_search_parameters(); - rs_params.lower_bounds[0] = -5.0; - rs_params.lower_bounds[1] = -5.0; - rs_params.upper_bounds[0]= 5.0; - rs_params.upper_bounds[1]= 5.0; - rs_params.threads = 2; - rs_params.max_function_calls *= 10; - std::mt19937_64 gen(56789); - auto local_minima = random_search(beale, rs_params, gen); - CHECK_ABSOLUTE_ERROR(Real(3), local_minima[0], Real(0.1)); - CHECK_ABSOLUTE_ERROR(Real(1)/Real(2), local_minima[1], Real(0.1)); -} - -int main() { -#if defined(__clang__) || defined(_MSC_VER) - test_ackley(); - test_ackley(); - test_rosenbrock_saddle(); - test_rastrigin(); - test_three_hump_camel(); - test_beale(); -#endif - test_sphere(); - return boost::math::test::report_errors(); -} diff --git a/test/scipy_issue_14901_ncf.cpp b/test/scipy_issue_14901_ncf.cpp index 0be7382695..97394c1972 100644 --- a/test/scipy_issue_14901_ncf.cpp +++ b/test/scipy_issue_14901_ncf.cpp @@ -5,13 +5,27 @@ // // See: https://github.com/scipy/scipy/issues/14901 -#include +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + +// FE_* are macros, so they must come from a textual C header even in module +// mode (import std cannot export macros); is safe to leave unguarded. +#include + +// std::fetestexcept comes from import std in module mode; the non-module build +// gets it from the wrapper. +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif + #include "math_unit_test.hpp" #pragma STDC FENV_ACCESS ON -int main() +int main() { auto ncf1 = boost::math::non_central_f(1, 1, 1); const auto cdf1 = boost::math::cdf(ncf1, 2); diff --git a/test/scipy_issue_15101.cpp b/test/scipy_issue_15101.cpp index b3bf01a4fd..f85d5c85ea 100644 --- a/test/scipy_issue_15101.cpp +++ b/test/scipy_issue_15101.cpp @@ -7,10 +7,18 @@ #define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error #define BOOST_MATH_PROMOTE_DOUBLE_POLICY false +#ifndef BOOST_MATH_BUILD_MODULE +#include #include +#else +import boost.math; +#include +#endif + +#ifndef BOOST_MATH_BUILD_MODULE #include #include -#include +#endif #include "math_unit_test.hpp" #pragma STDC FENV_ACCESS ON diff --git a/test/scipy_issue_17146.cpp b/test/scipy_issue_17146.cpp index b14d8b0f2e..c715b7095d 100644 --- a/test/scipy_issue_17146.cpp +++ b/test/scipy_issue_17146.cpp @@ -3,9 +3,16 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE #include #include -#include +#endif #include "math_unit_test.hpp" int main() @@ -15,7 +22,7 @@ int main() const auto binom_dist = boost::math::binomial_distribution(n, p); std::array vals {}; - for (size_t i = 0; i < 2; ++i) + for (std::size_t i = 0; i < 2; ++i) { vals[i] = boost::math::pdf(binom_dist, i); } diff --git a/test/scipy_issue_17388.cpp b/test/scipy_issue_17388.cpp index 5b56b4c72a..fec300aa56 100644 --- a/test/scipy_issue_17388.cpp +++ b/test/scipy_issue_17388.cpp @@ -6,9 +6,16 @@ // See: https://github.com/boostorg/math/issues/889 // See: https://github.com/scipy/scipy/issues/17388 +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE #include #include -#include +#endif #include "math_unit_test.hpp" int main(void) diff --git a/test/scipy_issue_17916.cpp b/test/scipy_issue_17916.cpp index d3b769fb3d..7d224c8ffd 100644 --- a/test/scipy_issue_17916.cpp +++ b/test/scipy_issue_17916.cpp @@ -5,7 +5,12 @@ // // See: https://github.com/scipy/scipy/issues/17916 +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + #include "math_unit_test.hpp" int main(void) diff --git a/test/scipy_issue_17916_nct.cpp b/test/scipy_issue_17916_nct.cpp index 24f87cfdd1..d8f5b1c8bd 100644 --- a/test/scipy_issue_17916_nct.cpp +++ b/test/scipy_issue_17916_nct.cpp @@ -5,7 +5,12 @@ // // See: https://github.com/scipy/scipy/issues/17916#issuecomment-1437826800 +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + #include "math_unit_test.hpp" int main(void) diff --git a/test/scipy_issue_18302.cpp b/test/scipy_issue_18302.cpp index b3acef4f31..f6282cefda 100644 --- a/test/scipy_issue_18302.cpp +++ b/test/scipy_issue_18302.cpp @@ -5,9 +5,16 @@ // // See: https://github.com/scipy/scipy/issues/17916 +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE #include #include +#endif #include "math_unit_test.hpp" int main(void) diff --git a/test/scipy_issue_18511.cpp b/test/scipy_issue_18511.cpp index 46c74aa3e9..f76d80bab3 100644 --- a/test/scipy_issue_18511.cpp +++ b/test/scipy_issue_18511.cpp @@ -5,10 +5,18 @@ // // https://github.com/scipy/scipy/issues/18511 +#ifndef BOOST_MATH_BUILD_MODULE #include #include #include #include +#else +import boost.math; +// UINT64_C is a preprocessor macro and is not provided by import std, so pull +// it from the pure-C header (not the wrapper) in module mode. +#include +#endif + #include "math_unit_test.hpp" template @@ -29,7 +37,6 @@ int main() { test(); test(); - test(); return boost::math::test::report_errors(); } diff --git a/test/septic_hermite_test.cpp b/test/septic_hermite_test.cpp deleted file mode 100644 index 119e626191..0000000000 --- a/test/septic_hermite_test.cpp +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright Nick Thompson, 2020 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#include -#include -#include -#include -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif - -#if __has_include() -# include -#endif - -using boost::math::interpolators::septic_hermite; -using boost::math::interpolators::cardinal_septic_hermite; -using boost::math::interpolators::cardinal_septic_hermite_aos; - -template -void test_constant() -{ - - std::vector x{0,1,2,3, 9, 22, 81}; - std::vector y(x.size()); - std::vector dydx(x.size(), 0); - std::vector d2ydx2(x.size(), 0); - std::vector d3ydx3(x.size(), 0); - for (auto & t : y) - { - t = 7; - } - - auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - - for (Real t = 0; t <= 81; t += Real(0.25)) - { - CHECK_ULP_CLOSE(Real(7), sh(t), 24); - CHECK_ULP_CLOSE(Real(0), sh.prime(t), 24); - } - - Real x0 = 0; - Real dx = 1; - y.resize(128, 7); - dydx.resize(128, 0); - d2ydx2.resize(128, 0); - d3ydx3.resize(128, 0); - auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); - for (Real t = x0; t <= 127; t += Real(0.25)) - { - CHECK_ULP_CLOSE(Real(7), csh(t), 24); - CHECK_ULP_CLOSE(Real(0), csh.prime(t), 24); - CHECK_ULP_CLOSE(Real(0), csh.double_prime(t), 24); - } - - std::vector> data(128); - for (size_t i = 0; i < data.size(); ++i) - { - data[i][0] = 7; - data[i][1] = 0; - data[i][2] = 0; - data[i][3] = 0; - } - auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx); - for (Real t = x0; t <= 127; t += Real(0.25)) - { - CHECK_ULP_CLOSE(Real(7), csh_aos(t), 24); - CHECK_ULP_CLOSE(Real(0), csh_aos.prime(t), 24); - CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(t), 24); - } - - // Now check the boundaries: - auto [tlo, thi] = csh.domain(); - int samples = 5000; - int i = 0; - while (i++ < samples) - { - CHECK_ULP_CLOSE(Real(7), csh(tlo), 2); - CHECK_ULP_CLOSE(Real(7), csh(thi), 2); - CHECK_ULP_CLOSE(Real(7), csh_aos(tlo), 2); - CHECK_ULP_CLOSE(Real(7), csh_aos(thi), 2); - CHECK_ULP_CLOSE(Real(0), csh.prime(tlo), 2); - CHECK_ULP_CLOSE(Real(0), csh.prime(thi), 2); - CHECK_ULP_CLOSE(Real(0), csh_aos.prime(tlo), 2); - CHECK_ULP_CLOSE(Real(0), csh_aos.prime(thi), 2); - CHECK_ULP_CLOSE(Real(0), csh.double_prime(tlo), 2); - CHECK_ULP_CLOSE(Real(0), csh.double_prime(thi), 2); - CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(tlo), 2); - CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(thi), 2); - - tlo = boost::math::nextafter(tlo, (std::numeric_limits::max)()); - thi = boost::math::nextafter(thi, std::numeric_limits::lowest()); - } - -} - - -template -void test_linear() -{ - std::vector x{0,1,2,3,4,5,6,7,8,9}; - std::vector y = x; - std::vector dydx(x.size(), 1); - std::vector d2ydx2(x.size(), 0); - std::vector d3ydx3(x.size(), 0); - - auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - - for (Real t = 0; t <= 9; t += Real(0.25)) - { - CHECK_ULP_CLOSE(Real(t), sh(t), 2); - CHECK_ULP_CLOSE(Real(1), sh.prime(t), 2); - } - - boost::random::mt19937 rng; - boost::random::uniform_real_distribution dis(Real(0.5), Real(1)); - x.resize(512); - x[0] = dis(rng); - Real xmin = x[0]; - for (size_t i = 1; i < x.size(); ++i) - { - x[i] = x[i-1] + dis(rng); - } - Real xmax = x.back(); - - y = x; - dydx.resize(x.size(), 1); - d2ydx2.resize(x.size(), 0); - d3ydx3.resize(x.size(), 0); - - sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - - for (Real t = xmin; t <= xmax; t += Real(0.125)) - { - CHECK_ULP_CLOSE(t, sh(t), 25); - CHECK_ULP_CLOSE(Real(1), sh.prime(t), 850); - } - - Real x0 = 0; - Real dx = 1; - y.resize(10); - dydx.resize(10, 1); - d2ydx2.resize(10, 0); - d3ydx3.resize(10, 0); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = i; - } - auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); - for (Real t = 0; t <= 9; t += Real(0.125)) - { - CHECK_ULP_CLOSE(t, csh(t), 15); - CHECK_ULP_CLOSE(Real(1), csh.prime(t), 15); - CHECK_ULP_CLOSE(Real(0), csh.double_prime(t), 15); - } - - std::vector> data(10); - for (size_t i = 0; i < data.size(); ++i) - { - data[i][0] = i; - data[i][1] = 1; - data[i][2] = 0; - data[i][3] = 0; - } - auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx); - for (Real t = 0; t <= 9; t += Real(0.125)) - { - CHECK_ULP_CLOSE(t, csh_aos(t), 15); - CHECK_ULP_CLOSE(Real(1), csh_aos.prime(t), 15); - CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(t), 15); - } - - // Now check the boundaries: - auto [tlo, thi] = csh.domain(); - int samples = 5000; - int i = 0; - while (i++ < samples) - { - CHECK_ULP_CLOSE(Real(tlo), csh(tlo), 2); - CHECK_ULP_CLOSE(Real(thi), csh(thi), 8); - CHECK_ULP_CLOSE(Real(tlo), csh_aos(tlo), 2); - CHECK_ULP_CLOSE(Real(thi), csh_aos(thi), 8); - CHECK_ULP_CLOSE(Real(1), csh.prime(tlo), 2); - CHECK_ULP_CLOSE(Real(1), csh.prime(thi), 700); - CHECK_ULP_CLOSE(Real(1), csh_aos.prime(tlo), 2); - CHECK_ULP_CLOSE(Real(1), csh_aos.prime(thi), 700); - CHECK_MOLLIFIED_CLOSE(Real(0), csh.double_prime(tlo), std::numeric_limits::epsilon()); - CHECK_MOLLIFIED_CLOSE(Real(0), csh.double_prime(thi), 1200*std::numeric_limits::epsilon()); - CHECK_MOLLIFIED_CLOSE(Real(0), csh_aos.double_prime(tlo), std::numeric_limits::epsilon()); - CHECK_MOLLIFIED_CLOSE(Real(0), csh_aos.double_prime(thi), 1200*std::numeric_limits::epsilon()); - - tlo = boost::math::nextafter(tlo, (std::numeric_limits::max)()); - thi = boost::math::nextafter(thi, std::numeric_limits::lowest()); - } - -} - -template -void test_quadratic() -{ - std::vector x{0,1,2,3,4,5,6,7,8,9}; - std::vector y(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = x[i]*x[i]/2; - } - - std::vector dydx(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - dydx[i] = x[i]; - } - - std::vector d2ydx2(x.size(), 1); - std::vector d3ydx3(x.size(), 0); - - auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - - for (Real t = 0; t <= 9; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(t*t/2, sh(t), 100); - CHECK_ULP_CLOSE(t, sh.prime(t), 32); - } - - boost::random::mt19937 rng; - boost::random::uniform_real_distribution dis(Real(0.5), Real(1)); - x.resize(8); - x[0] = dis(rng); - Real xmin = x[0]; - for (size_t i = 1; i < x.size(); ++i) - { - x[i] = x[i-1] + dis(rng); - } - Real xmax = x.back(); - - y.resize(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = x[i]*x[i]/2; - } - - dydx.resize(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - dydx[i] = x[i]; - } - - d2ydx2.resize(x.size(), 1); - d3ydx3.resize(x.size(), 0); - - sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - - for (Real t = xmin; t <= xmax; t += Real(0.125)) - { - CHECK_ULP_CLOSE(t*t/2, sh(t), 50); - CHECK_ULP_CLOSE(t, sh.prime(t), 300); - } - - y.resize(10); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = i*i/Real(2); - } - - dydx.resize(y.size()); - for (size_t i = 0; i < y.size(); ++i) - { - dydx[i] = i; - } - - d2ydx2.resize(y.size(), 1); - d3ydx3.resize(y.size(), 0); - - Real x0 = 0; - Real dx = 1; - auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); - for (Real t = x0; t <= 9; t += Real(0.125)) - { - CHECK_ULP_CLOSE(t*t/2, csh(t), 24); - CHECK_ULP_CLOSE(t, csh.prime(t), 24); - CHECK_ULP_CLOSE(Real(1), csh.double_prime(t), 24); - } - - std::vector> data(10); - for (size_t i = 0; i < data.size(); ++i) - { - data[i][0] = i*i/Real(2); - data[i][1] = i; - data[i][2] = 1; - data[i][3] = 0; - } - auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx); - for (Real t = x0; t <= 9; t += Real(0.125)) - { - CHECK_ULP_CLOSE(t*t/2, csh_aos(t), 24); - CHECK_ULP_CLOSE(t, csh_aos.prime(t), 24); - CHECK_ULP_CLOSE(Real(1), csh_aos.double_prime(t), 24); - } -} - - - -template -void test_cubic() -{ - - std::vector x{0,1,2,3,4,5,6,7}; - Real xmax = x.back(); - std::vector y(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = x[i]*x[i]*x[i]; - } - - std::vector dydx(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - dydx[i] = 3*x[i]*x[i]; - } - - std::vector d2ydx2(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - d2ydx2[i] = 6*x[i]; - } - std::vector d3ydx3(x.size(), 6); - - auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - - for (Real t = 0; t <= xmax; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(t*t*t, sh(t), 151); - CHECK_ULP_CLOSE(3*t*t, sh.prime(t), 151); - } - - Real x0 = 0; - Real dx = 1; - y.resize(8); - dydx.resize(8); - d2ydx2.resize(8); - d3ydx3.resize(8,6); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = i*i*i; - dydx[i] = 3*i*i; - d2ydx2[i] = 6*i; - } - - auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); - - for (Real t = 0; t <= xmax; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(t*t*t, csh(t), 151); - CHECK_ULP_CLOSE(3*t*t, csh.prime(t), 151); - CHECK_ULP_CLOSE(6*t, csh.double_prime(t), 151); - } - - std::vector> data(8); - for (size_t i = 0; i < data.size(); ++i) { - data[i][0] = i*i*i; - data[i][1] = 3*i*i; - data[i][2] = 6*i; - data[i][3] = 6; - } - - auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx); - - for (Real t = 0; t <= xmax; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(t*t*t, csh_aos(t), 151); - CHECK_ULP_CLOSE(3*t*t, csh_aos.prime(t), 151); - CHECK_ULP_CLOSE(6*t, csh_aos.double_prime(t), 151); - } -} - -template -void test_quartic() -{ - - std::vector x{0,1,2,3,4,5,6,7,8,9}; - Real xmax = x.back(); - std::vector y(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = x[i]*x[i]*x[i]*x[i]; - } - - std::vector dydx(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - dydx[i] = 4*x[i]*x[i]*x[i]; - } - - std::vector d2ydx2(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - d2ydx2[i] = 12*x[i]*x[i]; - } - - std::vector d3ydx3(x.size()); - for (size_t i = 0; i < y.size(); ++i) - { - d3ydx3[i] = 24*x[i]; - } - - auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); - - for (Real t = 1; t <= xmax; t += Real(0.0078125)) { - CHECK_ULP_CLOSE(t*t*t*t, sh(t), 117); - CHECK_ULP_CLOSE(4*t*t*t, sh.prime(t), 117); - } - - y.resize(10); - dydx.resize(10); - d2ydx2.resize(10); - d3ydx3.resize(10); - for (size_t i = 0; i < y.size(); ++i) - { - y[i] = i*i*i*i; - dydx[i] = 4*i*i*i; - d2ydx2[i] = 12*i*i; - d3ydx3[i] = 24*i; - } - - auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), Real(0), Real(1)); - - for (Real t = 1; t <= xmax; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(t*t*t*t, csh(t), 117); - CHECK_ULP_CLOSE(4*t*t*t, csh.prime(t), 117); - CHECK_ULP_CLOSE(12*t*t, csh.double_prime(t), 117); - } - - std::vector> data(10); - for (size_t i = 0; i < data.size(); ++i) - { - data[i][0] = i*i*i*i; - data[i][1] = 4*i*i*i; - data[i][2] = 12*i*i; - data[i][3] = 24*i; - } - - auto csh_aos = cardinal_septic_hermite_aos(std::move(data), Real(0), Real(1)); - for (Real t = 1; t <= xmax; t += Real(0.0078125)) - { - CHECK_ULP_CLOSE(t*t*t*t, csh_aos(t), 117); - CHECK_ULP_CLOSE(4*t*t*t, csh_aos.prime(t), 117); - CHECK_ULP_CLOSE(12*t*t, csh_aos.double_prime(t), 117); - } -} - - -template -void test_interpolation_condition() -{ - for (size_t n = 4; n < 50; ++n) { - std::vector x(n); - std::vector y(n); - std::vector dydx(n); - std::vector d2ydx2(n); - std::vector d3ydx3(n); - boost::random::mt19937 rd; - boost::random::uniform_real_distribution dis(0,1); - Real x0 = dis(rd); - x[0] = x0; - y[0] = dis(rd); - for (size_t i = 1; i < n; ++i) { - x[i] = x[i-1] + dis(rd); - y[i] = dis(rd); - dydx[i] = dis(rd); - d2ydx2[i] = dis(rd); - d3ydx3[i] = dis(rd); - } - - auto x_copy = x; - auto y_copy = y; - auto dydx_copy = dydx; - auto d2ydx2_copy = d2ydx2; - auto d3ydx3_copy = d3ydx3; - auto s = septic_hermite(std::move(x_copy), std::move(y_copy), std::move(dydx_copy), std::move(d2ydx2_copy), std::move(d3ydx3_copy)); - - for (size_t i = 0; i < x.size(); ++i) - { - CHECK_ULP_CLOSE(y[i], s(x[i]), 2); - CHECK_ULP_CLOSE(dydx[i], s.prime(x[i]), 2); - } - } -} - - -int main() -{ - #ifdef __STDCPP_FLOAT32_T__ - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - #else - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - #endif - - #ifdef __STDCPP_FLOAT64_T__ - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - #else - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - #endif - - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - - #ifdef BOOST_HAS_FLOAT128 - test_constant(); - test_linear(); - test_quadratic(); - test_cubic(); - test_quartic(); - test_interpolation_condition(); - #endif - - return boost::math::test::report_errors(); -} diff --git a/test/simple_continued_fraction_test.cpp b/test/simple_continued_fraction_test.cpp deleted file mode 100644 index fedb4e5a30..0000000000 --- a/test/simple_continued_fraction_test.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright Nick Thompson, 2020 - * 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) - */ - -#include "math_unit_test.hpp" -#include -#include -#include -#ifdef BOOST_HAS_FLOAT128 -#include -using boost::multiprecision::float128; -#endif -#include - -using boost::math::tools::simple_continued_fraction; -using boost::multiprecision::cpp_bin_float_100; -using boost::math::constants::pi; - -template -void test_integral() -{ - for (int64_t i = -20; i < 20; ++i) { - Real ii = i; - auto cfrac = simple_continued_fraction(ii); - auto const & a = cfrac.partial_denominators(); - CHECK_EQUAL(size_t(1), a.size()); - CHECK_EQUAL(i, a.front()); - } -} - -template -void test_halves() -{ - for (int64_t i = -20; i < 20; ++i) { - Real x = i + Real(1)/Real(2); - auto cfrac = simple_continued_fraction(x); - auto const & a = cfrac.partial_denominators(); - CHECK_EQUAL(size_t(2), a.size()); - CHECK_EQUAL(i, a.front()); - CHECK_EQUAL(int64_t(2), a.back()); - } - - // We'll also test quarters; why not? - for (int64_t i = -20; i < 20; ++i) { - Real x = i + Real(1)/Real(4); - auto cfrac = simple_continued_fraction(x); - auto const & a = cfrac.partial_denominators(); - CHECK_EQUAL(size_t(2), a.size()); - CHECK_EQUAL(i, a.front()); - CHECK_EQUAL(int64_t(4), a.back()); - } - - for (int64_t i = -20; i < 20; ++i) { - Real x = i + Real(1)/Real(8); - auto cfrac = simple_continued_fraction(x); - auto const & a = cfrac.partial_denominators(); - CHECK_EQUAL(size_t(2), a.size()); - CHECK_EQUAL(i, a.front()); - CHECK_EQUAL(int64_t(8), a.back()); - } - - for (int64_t i = -20; i < 20; ++i) { - Real x = i + Real(3)/Real(4); - auto cfrac = simple_continued_fraction(x); - auto const & a = cfrac.partial_denominators(); - CHECK_EQUAL(size_t(3), a.size()); - CHECK_EQUAL(i, a.front()); - CHECK_EQUAL(int64_t(1), a[1]); - CHECK_EQUAL(int64_t(3), a.back()); - } - - for (int64_t i = -20; i < 20; ++i) { - Real x = i + Real(7)/Real(8); - auto cfrac = simple_continued_fraction(x); - auto const & a = cfrac.partial_denominators(); - CHECK_EQUAL(size_t(3), a.size()); - CHECK_EQUAL(i, a.front()); - CHECK_EQUAL(int64_t(1), a[1]); - CHECK_EQUAL(int64_t(7), a.back()); - } -} - -template -void test_simple() -{ - std::cout << "Testing rational numbers on type " << boost::core::demangle(typeid(Real).name()) << "\n"; - { - Real x = Real(649)/200; - // ContinuedFraction[649/200] = [3; 4, 12, 4] - auto cfrac = simple_continued_fraction(x); - auto const & a = cfrac.partial_denominators(); - CHECK_EQUAL(size_t(4), a.size()); - CHECK_EQUAL(int64_t(3), a[0]); - CHECK_EQUAL(int64_t(4), a[1]); - CHECK_EQUAL(int64_t(12), a[2]); - CHECK_EQUAL(int64_t(4), a[3]); - } - - { - Real x = Real(415)/Real(93); - // [4; 2, 6, 7]: - auto cfrac = simple_continued_fraction(x); - auto const & a = cfrac.partial_denominators(); - CHECK_EQUAL(size_t(4), a.size()); - CHECK_EQUAL(int64_t(4), a[0]); - CHECK_EQUAL(int64_t(2), a[1]); - CHECK_EQUAL(int64_t(6), a[2]); - CHECK_EQUAL(int64_t(7), a[3]); - } - -} - -template -void test_khinchin() -{ - // These are simply sanity checks; the convergence is too slow otherwise: - auto cfrac = simple_continued_fraction(pi()); - auto K0 = cfrac.khinchin_geometric_mean(); - CHECK_MOLLIFIED_CLOSE(Real(2.6854520010), K0, 0.1); - auto Km1 = cfrac.khinchin_harmonic_mean(); - CHECK_MOLLIFIED_CLOSE(Real(1.74540566240), Km1, 0.1); - - using std::sqrt; - auto rt_cfrac = simple_continued_fraction(sqrt(static_cast(2))); - K0 = rt_cfrac.khinchin_geometric_mean(); - CHECK_ULP_CLOSE(Real(2), K0, 10); - Km1 = rt_cfrac.khinchin_harmonic_mean(); - CHECK_ULP_CLOSE(Real(2), Km1, 10); -} - - -int main() -{ - test_integral(); - test_integral(); - test_integral(); - test_integral(); - - test_halves(); - test_halves(); - test_halves(); - test_halves(); - - test_simple(); - test_simple(); - test_simple(); - test_simple(); - - test_khinchin(); - - #ifdef BOOST_HAS_FLOAT128 - test_integral(); - test_halves(); - test_simple(); - test_khinchin(); - #endif - return boost::math::test::report_errors(); -} diff --git a/test/sinh_sinh_quadrature_test.cpp b/test/sinh_sinh_quadrature_test.cpp deleted file mode 100644 index 820ad96787..0000000000 --- a/test/sinh_sinh_quadrature_test.cpp +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright Nick Thompson, 2017 -// 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) - -#define BOOST_TEST_MODULE sinh_sinh_quadrature_test -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900) -// MSVC-12 has problems if we include 2 different multiprecision types in the same program, -// basically random things stop compiling, even though they work fine in isolation :( -#include -#endif - -using std::expm1; -using std::exp; -using std::sin; -using std::cos; -using std::atan; -using std::tan; -using std::log; -using std::log1p; -using std::asinh; -using std::atanh; -using std::sqrt; -using std::isnormal; -using std::abs; -using std::sinh; -using std::tanh; -using std::cosh; -using std::pow; -using std::string; -using boost::multiprecision::cpp_bin_float_quad; -using boost::math::quadrature::sinh_sinh; -using boost::math::constants::pi; -using boost::math::constants::pi_sqr; -using boost::math::constants::half_pi; -using boost::math::constants::two_div_pi; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::catalan; -using boost::math::constants::ln_two; -using boost::math::constants::root_two; -using boost::math::constants::root_two_pi; -using boost::math::constants::root_pi; -// -// Code for generating the coefficients: -// -template -void print_levels(const T& v, const char* suffix) -{ - std::cout << "{\n"; - for (unsigned i = 0; i < v.size(); ++i) - { - std::cout << " { "; - for (unsigned j = 0; j < v[i].size(); ++j) - { - std::cout << v[i][j] << suffix << ", "; - } - std::cout << "},\n"; - } - std::cout << " };\n"; -} - -template -void print_levels(const std::pair& p, const char* suffix = "") -{ - std::cout << " static const std::vector > abscissa = "; - print_levels(p.first, suffix); - std::cout << " static const std::vector > weights = "; - print_levels(p.second, suffix); -} - -template -std::pair>, std::vector> > generate_constants(unsigned max_rows) -{ - using boost::math::constants::half_pi; - using boost::math::constants::two_div_pi; - using boost::math::constants::pi; - auto g = [](Real t) { return sinh(half_pi()*sinh(t)); }; - auto w = [](Real t) { return cosh(t)*half_pi()*cosh(half_pi()*sinh(t)); }; - - std::vector> abscissa, weights; - - std::vector temp; - - Real t_max = log(2 * two_div_pi()*log(2 * two_div_pi()*sqrt(boost::math::tools::max_value()))); - - std::cout << "m_t_max = " << t_max << ";\n"; - - Real h = 1; - for (Real t = 1; t < t_max; t += h) - { - temp.push_back(g(t)); - } - abscissa.push_back(temp); - temp.clear(); - - for (Real t = 1; t < t_max; t += h) - { - temp.push_back(w(t * h)); - } - weights.push_back(temp); - temp.clear(); - - for (unsigned row = 1; row < max_rows; ++row) - { - h /= 2; - for (Real t = h; t < t_max; t += 2 * h) - temp.push_back(g(t)); - abscissa.push_back(temp); - temp.clear(); - } - h = 1; - for (unsigned row = 1; row < max_rows; ++row) - { - h /= 2; - for (Real t = h; t < t_max; t += 2 * h) - temp.push_back(w(t)); - weights.push_back(temp); - temp.clear(); - } - - return std::make_pair(abscissa, weights); -} - -template -void test_nr_examples() -{ - std::cout << "Testing type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real integration_limit = sqrt(boost::math::tools::epsilon()); - Real tol = 10 * boost::math::tools::epsilon(); - std::cout << std::setprecision(std::numeric_limits::digits10); - Real Q; - Real Q_expected; - Real L1; - Real error; - const sinh_sinh integrator(10); - - auto f0 = [](Real)->Real { return (Real) 0; }; - Q = integrator.integrate(f0, integration_limit, &error, &L1); - Q_expected = 0; - BOOST_CHECK_SMALL(Q, tol); - BOOST_CHECK_SMALL(L1, tol); - - // In spite of the poles at \pm i, we still get a doubling of the correct digits at each level of refinement. - auto f1 = [](const Real& t)->Real { return 1/(1+t*t); }; - Q = integrator.integrate(f1, integration_limit, &error, &L1); - Q_expected = pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); -#if defined(BOOST_MSVC) && (BOOST_MSVC < 1900) - auto f2 = [](const Real& x)->Real { return fabs(x) > boost::math::tools::log_max_value() ? 0 : exp(-x*x); }; -#else - auto f2 = [](const Real& x)->Real { return exp(-x*x); }; -#endif - Q = integrator.integrate(f2, integration_limit, &error, &L1); - Q_expected = root_pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - auto f5 = [](const Real& t)->Real { return 1/cosh(t);}; - Q = integrator.integrate(f5, integration_limit, &error, &L1); - Q_expected = pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - // This oscillatory integral has rapid convergence because the oscillations get swamped by the exponential growth of the denominator, - // none the less the error is slightly higher than for the other cases: - tol *= 10; - auto f8 = [](const Real& t)->Real { return cos(t)/cosh(t);}; - Q = integrator.integrate(f8, integration_limit, &error, &L1); - Q_expected = pi()/cosh(half_pi()); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - // Try again with progressively fewer arguments: - Q = integrator.integrate(f8, integration_limit); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - Q = integrator.integrate(f8); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); -} - -// Test formulas for in the CRC Handbook of Mathematical functions, 32nd edition. -template -void test_crc() -{ - std::cout << "Testing CRC formulas on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real integration_limit = sqrt(boost::math::tools::epsilon()); - Real tol = 10 * boost::math::tools::epsilon(); - std::cout << std::setprecision(std::numeric_limits::digits10); - Real Q; - Real Q_expected; - Real L1; - Real error; - const sinh_sinh integrator(10); - - // CRC Definite integral 698: - auto f0 = [](Real x)->Real { - using std::sinh; - if(x == 0) { - return (Real) 1; - } - return x/sinh(x); - }; - Q = integrator.integrate(f0, integration_limit, &error, &L1); - Q_expected = pi_sqr()/2; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - - // CRC Definite integral 695: - auto f1 = [](Real x)->Real { - using std::sin; using std::sinh; - if(x == 0) { - return (Real) 1; - } - return (Real) sin(x)/sinh(x); - }; - Q = integrator.integrate(f1, integration_limit, &error, &L1); - Q_expected = pi()*tanh(half_pi()); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); -} - -template -void test_dirichlet_eta() -{ - typedef typename Complex::value_type Real; - std::cout << "Testing Dirichlet eta function on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Complex Q; - const sinh_sinh integrator(10); - - //https://en.wikipedia.org/wiki/Dirichlet_eta_function, integral representations: - Complex z = {1,1}; - auto eta = [&z](Real t)->Complex { - using std::exp; - using std::pow; - using boost::math::constants::pi; - Complex i = {0,1}; - Complex num = pow((Real)1/ (Real)2 + i*t, -z); - Real denom = exp(pi()*t) + exp(-pi()*t); - Complex res = num/denom; - return res; - }; - Q = integrator.integrate(eta); - // N[DirichletEta[1 + I], 150] - { - Complex Q_expected = { BOOST_MATH_TEST_VALUE(Real, 0.7265597750624632632014957285472413863111295027357257871), BOOST_MATH_TEST_VALUE(Real, 0.158095863901207324355426285544321998253687969756843115) }; - - BOOST_CHECK_CLOSE_FRACTION(Q.real(), Q_expected.real(), tol); - BOOST_CHECK_CLOSE_FRACTION(Q.imag(), Q_expected.imag(), tol); - } -} - - -BOOST_AUTO_TEST_CASE(sinh_sinh_quadrature_test) -{ - // - // Uncomment the following to print out the coefficients: - // - /* - std::cout << std::scientific << std::setprecision(8); - print_levels(generate_constants(8), "f"); - std::cout << std::setprecision(18); - print_levels(generate_constants(8), ""); - std::cout << std::setprecision(35); - print_levels(generate_constants(8), "L"); - */ - test_nr_examples(); - test_nr_examples(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_nr_examples(); -#endif - test_nr_examples(); -#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) - test_nr_examples(); -#endif -#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900) && defined(BOOST_MATH_RUN_MP_TESTS) - test_nr_examples(); -#endif - - test_crc(); - test_crc(); - test_dirichlet_eta>(); -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - test_crc(); - test_dirichlet_eta>(); -#endif -#ifdef BOOST_MATH_RUN_MP_TESTS - test_crc(); - test_dirichlet_eta(); -#endif -#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) - test_crc(); -#endif -#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900) && defined(BOOST_MATH_RUN_MP_TESTS) - test_crc(); -#endif - - -} diff --git a/test/special_functions_test.cpp b/test/special_functions_test.cpp deleted file mode 100644 index 8ea88c193c..0000000000 --- a/test/special_functions_test.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// test file for special functions. - -// (C) Copyright Hubert Holin 2003. -// 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) - - -#include - - -#include - -#include -#include -#include -#include - - -template -struct string_type_name; - -#define DEFINE_TYPE_NAME(Type) \ -template<> struct string_type_name \ -{ \ - static char const * _() \ - { \ - return #Type; \ - } \ -} - -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS -DEFINE_TYPE_NAME(float); -DEFINE_TYPE_NAME(double); -DEFINE_TYPE_NAME(long double); - -typedef boost::mpl::list test_types; -#else -DEFINE_TYPE_NAME(float); -DEFINE_TYPE_NAME(double); - -typedef boost::mpl::list test_types; -#endif - -// Apple GCC 4.0 uses the "double double" format for its long double, -// which means that epsilon is VERY small but useless for -// comparisons. So, don't do those comparisons. -#if (defined(__APPLE_CC__) && defined(__GNUC__) && __GNUC__ == 4) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) -typedef boost::mpl::list near_eps_test_types; -#else -typedef boost::mpl::list near_eps_test_types; -#endif - -#include "sinc_test.hpp" -#include "sinhc_test.hpp" -#include "atanh_test.hpp" -#include "asinh_test.hpp" -#include "acosh_test.hpp" - - - -boost::unit_test::test_suite * init_unit_test_suite(int, char *[]) -{ - ::boost::unit_test::unit_test_log. - set_threshold_level(::boost::unit_test::log_messages); - - boost::unit_test::test_suite * test = - BOOST_TEST_SUITE("special_functions_test"); - - BOOST_TEST_MESSAGE("Results of special functions test."); - BOOST_TEST_MESSAGE(" "); - BOOST_TEST_MESSAGE("(C) Copyright Hubert Holin 2003-2005."); - BOOST_TEST_MESSAGE("Distributed under the Boost Software License, Version 1.0."); - BOOST_TEST_MESSAGE("(See accompanying file LICENSE_1_0.txt or copy at"); - BOOST_TEST_MESSAGE("http://www.boost.org/LICENSE_1_0.txt)"); - BOOST_TEST_MESSAGE(" "); - -#define BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR(fct) \ - test->add(BOOST_TEST_CASE_TEMPLATE(fct##_test, test_types)); - -#define BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR_NEAR_EPS(fct) \ - test->add(BOOST_TEST_CASE_TEMPLATE(fct##_test, near_eps_test_types)); - - -#define BOOST_SPECIAL_FUNCTIONS_COMMON_TEST \ - BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR(atanh) \ - BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR(asinh) \ - BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR(acosh) \ - BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR(sinc_pi) \ - BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR(sinhc_pi) - -#define BOOST_SPECIAL_FUNCTIONS_TEMPLATE_TEMPLATE_TEST \ - BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR_NEAR_EPS(sinc_pi_complex) \ - BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR_NEAR_EPS(sinhc_pi_complex) - - -#ifdef BOOST_NO_TEMPLATE_TEMPLATES - -#define BOOST_SPECIAL_FUNCTIONS_TEST \ - BOOST_SPECIAL_FUNCTIONS_COMMON_TEST \ - BOOST_TEST_MESSAGE("Warning: no template templates; curtailed functionality."); - -#else /* BOOST_NO_TEMPLATE_TEMPLATES */ - -#define BOOST_SPECIAL_FUNCTIONS_TEST \ - BOOST_SPECIAL_FUNCTIONS_COMMON_TEST \ - BOOST_SPECIAL_FUNCTIONS_TEMPLATE_TEMPLATE_TEST - -#endif /* BOOST_NO_TEMPLATE_TEMPLATES */ - - - BOOST_SPECIAL_FUNCTIONS_TEST - - -#undef BOOST_SPECIAL_FUNCTIONS_TEST - -#undef BOOST_SPECIAL_FUNCTIONS_TEMPLATE_TEMPLATE_TEST - -#undef BOOST_SPECIAL_FUNCTIONS_COMMON_TEST - -#undef BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR - -#undef BOOST_SPECIAL_FUNCTIONS_COMMON_GENERATOR_NEAR_EPS - -#ifdef BOOST_SPECIAL_FUNCTIONS_TEST_VERBOSE - - using ::std::numeric_limits; - - BOOST_TEST_MESSAGE("epsilon"); - - BOOST_TEST_MESSAGE( ::std::setw(15) << numeric_limits::epsilon() - << ::std::setw(15) << numeric_limits::epsilon() - << ::std::setw(15) << numeric_limits::epsilon()); - - BOOST_TEST_MESSAGE(" "); - - test->add(BOOST_TEST_CASE(atanh_manual_check)); - test->add(BOOST_TEST_CASE(asinh_manual_check)); - test->add(BOOST_TEST_CASE(acosh_manual_check)); - test->add(BOOST_TEST_CASE(sinc_pi_manual_check)); - test->add(BOOST_TEST_CASE(sinhc_pi_manual_check)); - -#endif /* BOOST_SPECIAL_FUNCTIONS_TEST_VERBOSE */ - - return test; -} - -#undef DEFINE_TYPE_NAME diff --git a/test/sycl_jamfile b/test/sycl_jamfile index 2c550757e5..d72a75efec 100644 --- a/test/sycl_jamfile +++ b/test/sycl_jamfile @@ -44,7 +44,7 @@ run test_uniform.cpp ; run test_weibull.cpp ; # Special Functions -run pow_test.cpp ; +run test_pow.cpp ; run test_airy.cpp ; @@ -78,7 +78,7 @@ run test_expint.cpp ; run test_expm1_simple.cpp ; -run gegenbauer_test.cpp ; +run test_gegenbauer.cpp ; run test_hankel.cpp ; @@ -98,3 +98,5 @@ run test_igamma_inva.cpp ; run test_hermite.cpp ; run git_issue_695_mp.cpp ; + +run test_pow1p.cpp ; diff --git a/test/tanh_sinh_quadrature_test.cpp b/test/tanh_sinh_quadrature_test.cpp deleted file mode 100644 index ffd55352b1..0000000000 --- a/test/tanh_sinh_quadrature_test.cpp +++ /dev/null @@ -1,1100 +0,0 @@ -// Copyright Nick Thompson, 2017 -// 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) - -#define BOOST_TEST_MODULE tanh_sinh_quadrature_test - -#include -#include - -#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && !defined(BOOST_NO_SFINAE_EXPR) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -#ifdef BOOST_HAS_FLOAT128 -#include -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4127) // Conditional expression is constant -#endif - -#if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) && !defined(TEST4) && !defined(TEST5) && !defined(TEST6) && !defined(TEST7) && !defined(TEST8)\ - && !defined(TEST1A) && !defined(TEST1B) && !defined(TEST2A) && !defined(TEST3A) && !defined(TEST6A) && !defined(TEST9) -# define TEST1 -# define TEST2 -# define TEST3 -# define TEST4 -# define TEST5 -# define TEST6 -# define TEST7 -# define TEST8 -# define TEST1A -# define TEST1B -# define TEST2A -# define TEST3A -# define TEST6A -# define TEST9 -#endif - -using std::expm1; -using std::atan; -using std::tan; -using std::log; -using std::log1p; -using std::asinh; -using std::atanh; -using std::sqrt; -using std::isnormal; -using std::abs; -using std::sinh; -using std::tanh; -using std::cosh; -using std::pow; -using std::exp; -using std::sin; -using std::cos; -using std::string; -using boost::multiprecision::cpp_bin_float_50; -using boost::multiprecision::cpp_bin_float_100; -using boost::multiprecision::cpp_dec_float_50; -using boost::multiprecision::cpp_dec_float_100; -using boost::multiprecision::cpp_bin_float_quad; -using boost::math::sinc_pi; -using boost::math::quadrature::tanh_sinh; -using boost::math::quadrature::detail::tanh_sinh_detail; -using boost::math::constants::pi; -using boost::math::constants::half_pi; -using boost::math::constants::two_div_pi; -using boost::math::constants::two_pi; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::half; -using boost::math::constants::third; -using boost::math::constants::catalan; -using boost::math::constants::ln_two; -using boost::math::constants::root_two; -using boost::math::constants::root_two_pi; -using boost::math::constants::root_pi; - -template -inline Real cast_mp_to_real(const cpp_bin_float_100& arg) -{ - return static_cast(arg); -} -template <> -inline boost::math::concepts::real_concept cast_mp_to_real(const cpp_bin_float_100& arg) -{ - return static_cast(static_cast(arg)); -} - -template -void print_levels(const T& v, const char* suffix) -{ - std::cout << "{\n"; - for (unsigned i = 0; i < v.size(); ++i) - { - std::cout << " { "; - for (unsigned j = 0; j < v[i].size(); ++j) - { - std::cout << v[i][j] << suffix << ", "; - } - std::cout << "},\n"; - } - std::cout << " };\n"; -} - -template -void print_complement_indexes(const T& v) -{ - std::cout << "\n {"; - for (unsigned i = 0; i < v.size(); ++i) - { - unsigned index = 0; - while (v[i][index] >= 0) - ++index; - std::cout << index << ", "; - } - std::cout << "};\n"; -} - -template -void print_levels(const std::pair& p, const char* suffix = "") -{ - std::cout << " static const std::vector > abscissa = "; - print_levels(p.first, suffix); - std::cout << " static const std::vector > weights = "; - print_levels(p.second, suffix); - std::cout << " static const std::vector indexes = "; - print_complement_indexes(p.first); -} - -template -std::pair>, std::vector> > generate_constants(unsigned max_index, unsigned max_rows) -{ - using boost::math::constants::half_pi; - using boost::math::constants::two_div_pi; - using boost::math::constants::pi; - auto g = [](Real t) { return tanh(half_pi()*sinh(t)); }; - auto w = [](Real t) { Real cs = cosh(half_pi() * sinh(t)); return half_pi() * cosh(t) / (cs * cs); }; - auto gc = [](Real t) { Real u2 = half_pi() * sinh(t); return 1 / (exp(u2) *cosh(u2)); }; - auto g_inv = [](float x)->float { return asinh(two_div_pi()*atanh(x)); }; - auto gc_inv = [](float x) - { - float l = log(sqrt((2 - x) / x)); - return log((sqrt(4 * l * l + pi() * pi()) + 2 * l) / pi()); - }; - - std::vector> abscissa, weights; - - std::vector temp; - - float t_crossover = gc_inv(0.5f); - - Real h = 1; - for (unsigned i = 0; i < max_index; ++i) - { - temp.push_back((i < t_crossover) ? g(i * h) : -gc(i * h)); - } - abscissa.push_back(temp); - temp.clear(); - - for (unsigned i = 0; i < max_index; ++i) - { - temp.push_back(w(i * h)); - } - weights.push_back(temp); - temp.clear(); - - for (unsigned row = 1; row < max_rows; ++row) - { - h /= 2; - for (Real t = h; t < max_index - 1; t += 2 * h) - temp.push_back((t < t_crossover) ? g(t) : -gc(t)); - abscissa.push_back(temp); - temp.clear(); - } - h = 1; - for (unsigned row = 1; row < max_rows; ++row) - { - h /= 2; - for (Real t = h; t < max_index - 1; t += 2 * h) - temp.push_back(w(t)); - weights.push_back(temp); - temp.clear(); - } - - return std::make_pair(abscissa, weights); -} - -template -const tanh_sinh& get_integrator() -{ - static const tanh_sinh integrator(15); - return integrator; -} - -template -Real get_convergence_tolerance() -{ - return boost::math::tools::root_epsilon(); -} - - -template -void test_linear() -{ - std::cout << "Testing linear functions are integrated properly by tanh_sinh on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10*boost::math::tools::epsilon(); - auto integrator = get_integrator(); - auto f = [](const Real& x) - { - return 5*x + 7; - }; - Real error; - Real L1; - Real Q = integrator.integrate(f, (Real) 0, (Real) 1, get_convergence_tolerance(), &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, static_cast(9.5), tol); - BOOST_CHECK_CLOSE_FRACTION(L1, static_cast(9.5), tol); - Q = integrator.integrate(f, static_cast(1), static_cast(0), get_convergence_tolerance(), &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, static_cast(-9.5), tol); - BOOST_CHECK_CLOSE_FRACTION(L1, static_cast(9.5), tol); - Q = integrator.integrate(f, static_cast(1), static_cast(1), get_convergence_tolerance(), &error, &L1); - BOOST_CHECK_EQUAL(Q, Real(0)); -} - - -template -void test_quadratic() -{ - std::cout << "Testing quadratic functions are integrated properly by tanh_sinh on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10*boost::math::tools::epsilon(); - auto integrator = get_integrator(); - auto f = [](const Real& x) { return 5*x*x + 7*x + 12; }; - Real error; - Real L1; - Real Q = integrator.integrate(f, (Real) 0, (Real) 1, get_convergence_tolerance(), &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, (Real) 17 + half()*third(), tol); - BOOST_CHECK_CLOSE_FRACTION(L1, (Real) 17 + half()*third(), tol); -} - - -template -void test_singular() -{ - std::cout << "Testing integration of endpoint singularities on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10*boost::math::tools::epsilon(); - Real error; - Real L1; - auto integrator = get_integrator(); - auto f = [](const Real& x) { return log(x)*log(1-x); }; - Real Q = integrator.integrate(f, (Real) 0, (Real) 1, get_convergence_tolerance(), &error, &L1); - Real Q_expected = 2 - pi()*pi()*half()*third(); - - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); -} - - -// Examples taken from -//http://crd-legacy.lbl.gov/~dhbailey/dhbpapers/quadrature.pdf -template -void test_ca() -{ - std::cout << "Testing integration of C(a) on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real error; - Real L1; - - auto integrator = get_integrator(); - auto f1 = [](const Real& x) { return atan(x)/(x*(x*x + 1)) ; }; - Real Q = integrator.integrate(f1, (Real) 0, (Real) 1, get_convergence_tolerance(), &error, &L1); - Real Q_expected = pi()*ln_two()/8 + catalan()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - auto f2 = [](Real x)->Real { Real t0 = x*x + 1; Real t1 = sqrt(t0); return atan(t1)/(t0*t1); }; - Q = integrator.integrate(f2, (Real) 0 , (Real) 1, get_convergence_tolerance(), &error, &L1); - Q_expected = pi()/4 - pi()/root_two() + 3*atan(root_two())/root_two(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - auto f5 = [](Real t)->Real { return t*t*log(t)/((t*t - 1)*(t*t*t*t + 1)); }; - Q = integrator.integrate(f5, (Real) 0 , (Real) 1); - Q_expected = pi()*pi()*(2 - root_two())/32; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - - // Oh it suffers on this one. - auto f6 = [](Real t)->Real { Real x = log(t); return x*x; }; - Q = integrator.integrate(f6, (Real) 0 , (Real) 1, get_convergence_tolerance(), &error, &L1); - Q_expected = 2; - - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 50*tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, 50*tol); - - - // Although it doesn't get to the requested tolerance on this integral, the error bounds can be queried and are reasonable: - tol = sqrt(boost::math::tools::epsilon()); - auto f7 = [](const Real& t) { return sqrt(tan(t)); }; - Q = integrator.integrate(f7, (Real) 0 , (Real) half_pi(), get_convergence_tolerance(), &error, &L1); - Q_expected = pi()/root_two(); - // - // Slightly higher tolerance for type float, this marginal change was - // caused by no more than changing the order in which the terms are summed: - // - BOOST_IF_CONSTEXPR (std::is_same::value - #ifdef __STDCPP_FLOAT32_T__ - || std::is_same::value - #endif - ) - { - tol *= static_cast(1.5); - } - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - auto f8 = [](const Real& t) { return log(cos(t)); }; - Q = integrator.integrate(f8, (Real) 0 , half_pi(), get_convergence_tolerance(), &error, &L1); - Q_expected = -pi()*ln_two()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, -Q_expected, tol); -} - - -template -void test_three_quadrature_schemes_examples() -{ - std::cout << "Testing integral in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real Q; - Real Q_expected; - - auto integrator = get_integrator(); - // Example 1: - auto f1 = [](const Real& t) { return t*boost::math::log1p(t); }; - Q = integrator.integrate(f1, (Real) 0 , (Real) 1); - Q_expected = half()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - - // Example 2: - auto f2 = [](const Real& t) { return t*t*atan(t); }; - Q = integrator.integrate(f2, (Real) 0 , (Real) 1); - Q_expected = (pi() -2 + 2*ln_two())/12; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 2 * tol); - - // Example 3: - auto f3 = [](const Real& t) { return exp(t)*cos(t); }; - Q = integrator.integrate(f3, (Real) 0, half_pi()); - Q_expected = boost::math::expm1(half_pi())*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Example 4: - auto f4 = [](Real x)->Real { Real t0 = sqrt(x*x + 2); return atan(t0)/(t0*(x*x+1)); }; - Q = integrator.integrate(f4, (Real) 0 , (Real) 1); - Q_expected = 5*pi()*pi()/96; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Example 5: - auto f5 = [](const Real& t) { return sqrt(t)*log(t); }; - Q = integrator.integrate(f5, (Real) 0 , (Real) 1); - Q_expected = -4/ (Real) 9; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // Example 6: - auto f6 = [](const Real& t) { return sqrt(1 - t*t); }; - Q = integrator.integrate(f6, (Real) 0 , (Real) 1); - Q_expected = pi()/4; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); -} - - -template -void test_integration_over_real_line() -{ - std::cout << "Testing integrals over entire real line in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real Q; - Real Q_expected; - Real error; - Real L1; - auto integrator = get_integrator(); - - auto f1 = [](const Real& t) { return 1/(1+t*t);}; - Q = integrator.integrate(f1, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - auto f2 = [](const Real& t) { return exp(-t*t*half()); }; - Q = integrator.integrate(f2, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = root_two_pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol * 2); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol * 2); - - // This test shows how oscillatory integrals are approximated very poorly by this method: - //std::cout << "Testing sinc integral: \n"; - //Q = integrator.integrate(boost::math::sinc_pi, -std::numeric_limits::infinity(), std::numeric_limits::infinity(), &error, &L1); - //std::cout << "Error estimate of sinc integral: " << error << std::endl; - //std::cout << "L1 norm of sinc integral " << L1 << std::endl; - //Q_expected = pi(); - //BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); - - auto f4 = [](const Real& t) { return 1/cosh(t);}; - Q = integrator.integrate(f4, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = pi(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - -} - -template -void test_right_limit_infinite() -{ - std::cout << "Testing right limit infinite for tanh_sinh in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real Q; - Real Q_expected; - Real error; - Real L1; - const auto& integrator = get_integrator(); - - // Example 11: - auto f1 = [](const Real& t) { return 1/(1+t*t);}; - Q = integrator.integrate(f1, 0, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); - - // Example 12 - auto f2 = [](const Real& t) { return exp(-t)/sqrt(t); }; - Q = integrator.integrate(f2, 0, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = root_pi(); - BOOST_CHECK_CLOSE(Q, Q_expected, 1000*tol); - - auto f3 = [](const Real& t) { return exp(-t)*cos(t); }; - Q = integrator.integrate(f3, 0, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = half(); - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); - - auto f4 = [](const Real& t) { return 1/(1+t*t); }; - Q = integrator.integrate(f4, 1, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = pi()/4; - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); -} - -template -void test_left_limit_infinite() -{ - std::cout << "Testing left limit infinite for tanh_sinh in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real Q; - Real Q_expected; - const auto& integrator = get_integrator(); - - // Example 11: - auto f1 = [](const Real& t) { return 1/(1+t*t);}; - Q = integrator.integrate(f1, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), Real(0)); - Q_expected = half_pi(); - BOOST_CHECK_CLOSE(Q, Q_expected, 100*tol); -} - - -// A horrible function taken from -// http://www.chebfun.org/examples/quad/GaussClenCurt.html -template -void test_horrible() -{ - #ifdef BOOST_MATH_STANDALONE - BOOST_IF_CONSTEXPR (std::is_fundamental::value) - #endif - { - std::cout << "Testing Trefenthen's horrible integral on type " << boost::typeindex::type_id().pretty_name() << "\n"; - // We only know the integral to double precision, so requesting a higher tolerance doesn't make sense. - Real tol = 10 * std::numeric_limits::epsilon(); - Real Q; - Real Q_expected; - Real error; - Real L1; - const auto& integrator = get_integrator(); - - auto f = [](Real x)->Real { return x*sin(2*exp(2*sin(2*exp(2*x) ) ) ); }; - Q = integrator.integrate(f, (Real) -1, (Real) 1, get_convergence_tolerance(), &error, &L1); - // NIntegrate[x*Sin[2*Exp[2*Sin[2*Exp[2*x]]]], {x, -1, 1}, WorkingPrecision -> 130, MaxRecursion -> 100] - Q_expected = BOOST_MATH_TEST_VALUE(Real, 0.33673283478172753598559003181355241139806404130031017259552729882281); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - // Over again without specifying the bounds: - Q = integrator.integrate(f, get_convergence_tolerance(), &error, &L1); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - } -} - -// Some examples of tough integrals from NR, section 4.5.4: -template -void test_nr_examples() -{ - std::cout << "Testing singular integrals from NR 4.5.4 on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real Q; - Real Q_expected; - Real error; - Real L1; - const auto& integrator = get_integrator(); - - auto f1 = [](Real x)->Real - { - return (sin(x * half()) * exp(-x) / x) / sqrt(x); - }; - Q = integrator.integrate(f1, 0, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = sqrt(pi()*(sqrt((Real) 5) - 2)); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 25*tol); - - auto f2 = [](Real x)->Real { return pow(x, -(Real) 2/(Real) 7)*exp(-x*x); }; - Q = integrator.integrate(f2, 0, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value()); - Q_expected = half()*boost::math::tgamma((Real) 5/ (Real) 14); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol * 10); - -} - -// Test integrand known to fool some termination schemes: -template -void test_early_termination() -{ - std::cout << "Testing Clenshaw & Curtis's example of integrand which fools termination schemes on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real Q; - Real Q_expected; - Real error; - Real L1; - const auto& integrator = get_integrator(); - - auto f1 = [](Real x)->Real { return 23*cosh(x)/ (Real) 25 - cos(x) ; }; - Q = integrator.integrate(f1, (Real) -1, (Real) 1, get_convergence_tolerance(), &error, &L1); - Q_expected = 46*sinh((Real) 1)/(Real) 25 - 2*sin((Real) 1); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - // Over again with no bounds: - Q = integrator.integrate(f1); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); -} - -// Test some definite integrals from the CRC handbook, 32nd edition: -template -void test_crc() -{ - std::cout << "Testing CRC formulas on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - Real Q; - Real Q_expected; - Real error; - Real L1; - const auto& integrator = get_integrator(); - - // CRC Definite integral 585 - auto f1 = [](Real x)->Real { Real t = log(1/x); return x*x*t*t*t; }; - Q = integrator.integrate(f1, (Real) 0, (Real) 1, get_convergence_tolerance(), &error, &L1); - Q_expected = (Real) 2/ (Real) 27; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - // CRC 636: - #ifdef BOOST_MATH_STANDALONE - BOOST_IF_CONSTEXPR (std::is_fundamental::value) - #endif - { - auto f2 = [](Real x)->Real { return sqrt(cos(x)); }; - Q = integrator.integrate(f2, (Real) 0, (Real) half_pi(), get_convergence_tolerance(), &error, &L1); - //Q_expected = pow(two_pi(), 3*half())/pow(boost::math::tgamma((Real) 1/ (Real) 4), 2); - Q_expected = BOOST_MATH_TEST_VALUE(Real, 1.1981402347355922074399224922803238782272126632156515582636749529); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - - - // CRC Section 5.5, integral 585: - for (int n = 0; n < 3; ++n) { - for (int m = 0; m < 3; ++m) { - auto f = [&](Real x)->Real { return pow(x, Real(m))*pow(log(1/x), Real(n)); }; - Q = integrator.integrate(f, (Real) 0, (Real) 1, get_convergence_tolerance(), &error, &L1); - // Calculation of the tgamma function is not exact, giving spurious failures. - // Casting to cpp_bin_float_100 beforehand fixes most of them. - cpp_bin_float_100 np1 = n + 1; - cpp_bin_float_100 mp1 = m + 1; - Q_expected = cast_mp_to_real(tgamma(np1)/pow(mp1, np1)); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - } - } - } - // CRC Section 5.5, integral 591 - // The parameter p allows us to control the strength of the singularity. - // Rapid convergence is not guaranteed for this function, as the branch cut makes it non-analytic on a disk. - // This converges only when our test type has an extended exponent range as all the area of the integral - // occurs so close to 0 (or 1) that we need abscissa values exceptionally small to find it. - // "There's a lot of room at the bottom". - // We also use a 2 argument functor so that 1-x is evaluated accurately: - if (std::numeric_limits::max_exponent > std::numeric_limits::max_exponent) - { - for (Real p = Real (-0.99); p < 1; p += Real(0.1)) { - auto f = [&](Real x, Real cx)->Real - { - //return pow(x, p) / pow(1 - x, p); - return cx < 0 ? exp(p * (log(x) - boost::math::log1p(-x))) : pow(x, p) / pow(cx, p); - }; - Q = integrator.integrate(f, (Real)0, (Real)1, get_convergence_tolerance(), &error, &L1); - Q_expected = 1 / sinc_pi(p*pi()); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 10 * tol); - } - } - // There is an alternative way to evaluate the above integral: by noticing that all the area of the integral - // is near zero for p < 0 and near 1 for p > 0 we can substitute exp(-x) for x and remap the integral to the - // domain (0, INF). Internally we need to expand out the terms and evaluate using logs to avoid spurious overflow, - // this gives us - // for p > 0: - for (Real p = Real(0.99); p > 0; p -= Real(0.1)) { - auto f = [&](Real x)->Real - { - return exp(-x * (1 - p) + p * log(-boost::math::expm1(-x))); - }; - Q = integrator.integrate(f, 0, boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = 1 / sinc_pi(p*pi()); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 10 * tol); - } - // and for p < 1: - for (Real p = Real (-0.99); p < 0; p += Real(0.1)) { - auto f = [&](Real x)->Real - { - return exp(-p * log(-boost::math::expm1(-x)) - (1 + p) * x); - }; - Q = integrator.integrate(f, 0, boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = 1 / sinc_pi(p*pi()); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 10 * tol); - } - - // CRC Section 5.5, integral 635 - for (int m = 0; m < 10; ++m) { - auto f = [&](Real x)->Real { return Real(1)/(Real(1) + pow(tan(x), m)); }; - Q = integrator.integrate(f, (Real) 0, half_pi(), get_convergence_tolerance(), &error, &L1); - Q_expected = half_pi()/2; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - } - - // CRC Section 5.5, integral 637: - // - // When h gets very close to 1, the strength of the singularity gradually increases until we - // no longer have enough exponent range to evaluate the integral.... - // We also have to use the 2-argument functor version of the integrator to avoid - // cancellation error, since the singularity is near PI/2. - // - Real limit = std::numeric_limits::max_exponent > std::numeric_limits::max_exponent - ? .95f : .85f; - for (Real h = Real(0.01); h < limit; h += Real(0.1)) { - auto f = [&](Real x, Real xc)->Real { return xc > 0 ? pow(1/tan(xc), h) : pow(tan(x), h); }; - Q = integrator.integrate(f, (Real) 0, half_pi(), get_convergence_tolerance(), &error, &L1); - Q_expected = half_pi()/cos(h*half_pi()); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - } - // CRC Section 5.5, integral 637: - // - // Over again, but with argument transformation, we want: - // - // Integral of tan(x)^h over (0, PI/2) - // - // Note that the bulk of the area is next to the singularity at PI/2, - // so we'll start by replacing x by PI/2 - x, and that tan(PI/2 - x) == 1/tan(x) - // so we now have: - // - // Integral of 1/tan(x)^h over (0, PI/2) - // - // Which is almost the ideal form, except that when h is very close to 1 - // we run out of exponent range in evaluating the integral arbitrarily close to 0. - // So now we substitute exp(-x) for x: this stretches out the range of the - // integral to (-log(PI/2), +INF) with the singularity at +INF giving: - // - // Integral of exp(-x)/tan(exp(-x))^h over (-log(PI/2), +INF) - // - // We just need a way to evaluate the function without spurious under/overflow - // in the exp terms. Note that for small x: tan(x) ~= x, so making this - // substitution and evaluating by logs we have: - // - // exp(-x)/tan(exp(-x))^h ~= exp((h - 1) * x) for x > -log(epsilon); - // - // Here's how that looks in code: - // - for (Real i = 80; i < 100; ++i) { - Real h = i / 100; - auto f = [&](Real x)->Real - { - if (x > -log(boost::math::tools::epsilon())) - return exp((h - 1) * x); - else - { - Real et = exp(-x); - // Need to deal with numeric instability causing et to be greater than PI/2: - return et >= boost::math::constants::half_pi() ? 0 : et * pow(1 / tan(et), h); - } - }; - Q = integrator.integrate(f, -log(half_pi()), boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); - Q_expected = half_pi() / cos(h*half_pi()); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, 5 * tol); - } - - // CRC Section 5.5, integral 670: - - auto f3 = [](Real x)->Real { return sqrt(log(1/x)); }; - Q = integrator.integrate(f3, (Real) 0, (Real) 1, get_convergence_tolerance(), &error, &L1); - Q_expected = root_pi()/2; - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - -} - -template -void test_sf() -{ - using std::sqrt; - // Test some special functions that we already know how to evaluate: - std::cout << "Testing special functions on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - const auto& integrator = get_integrator(); - - // incomplete beta: - if (std::numeric_limits::digits10 < 37) // Otherwise too slow - { - Real a(100), b(15); - auto f = [&](Real x)->Real { return boost::math::ibeta_derivative(a, b, x); }; - BOOST_CHECK_CLOSE_FRACTION(integrator.integrate(f, 0, Real(0.25)), boost::math::ibeta(100, 15, Real(0.25)), tol * 10); - // Check some really extreme versions: - a = 1000; - b = 500; - BOOST_CHECK_CLOSE_FRACTION(integrator.integrate(f, 0, 1), Real(1), tol * 15); - // - // This is as extreme as we can get in this domain: otherwise the function has all it's - // area so close to zero we never get in there no matter how many levels we go down: - // - a = Real(1) / 15; - b = 30; - BOOST_CHECK_CLOSE_FRACTION(integrator.integrate(f, 0, 1), Real(1), tol * 25); - } - - Real x = 2, y = 3, z = 0.5, p = 0.25; - // Elliptic integral RC: - Real Q = integrator.integrate([&](const Real& t)->Real { return 1 / (sqrt(t + x) * (t + y)); }, 0, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value()) / 2; - BOOST_CHECK_CLOSE_FRACTION(Q, boost::math::ellint_rc(x, y), tol); - // Elliptic Integral RJ: - BOOST_CHECK_CLOSE_FRACTION(Real((Real(3) / 2) * integrator.integrate([&](Real t)->Real { return 1 / (sqrt((t + x) * (t + y) * (t + z)) * (t + p)); }, 0, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value())), boost::math::ellint_rj(x, y, z, p), tol); - - z = 5.5; - if (std::numeric_limits::digits10 > 40) - tol *= 200; - else if (!std::numeric_limits::is_specialized) - tol *= 3; - // tgamma expressed as an integral: - BOOST_CHECK_CLOSE_FRACTION(integrator.integrate([&](Real t)->Real { using std::pow; using std::exp; return t > 10000 ? Real(0) : Real(pow(t, z - 1) * exp(-t)); }, 0, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value()), - boost::math::tgamma(z), tol); - BOOST_CHECK_CLOSE_FRACTION(integrator.integrate([](const Real& t)->Real { using std::exp; return exp(-t*t); }, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value()), - boost::math::constants::root_pi(), tol); -} - -template -void test_2_arg() -{ - BOOST_MATH_STD_USING - std::cout << "Testing 2 argument functors on type " << boost::typeindex::type_id().pretty_name() << "\n"; - Real tol = 10 * boost::math::tools::epsilon(); - - const auto& integrator = get_integrator(); - - // - // There are a whole family of integrals of the general form - // x(1-x)^-N ; N < 1 - // which have all the interesting behaviour near the 2 singularities - // and all converge, see: http://www.wolframalpha.com/input/?i=integrate+(x+*+(1-x))%5E-1%2FN+from+0+to+1 - // - Real Q = integrator.integrate([&](const Real& t, const Real & tc)->Real - { - return tc < 0 ? 1 / sqrt(t * (1-t)) : 1 / sqrt(t * tc); - }, 0, 1); - BOOST_CHECK_CLOSE_FRACTION(Q, boost::math::constants::pi(), tol); - Q = integrator.integrate([&](const Real& t, const Real & tc)->Real - { - return tc < 0 ? 1 / boost::math::cbrt(t * (1-t)) : 1 / boost::math::cbrt(t * tc); - }, 0, 1); - BOOST_CHECK_CLOSE_FRACTION(Q, boost::math::pow<2>(boost::math::tgamma(Real(2) / 3)) / boost::math::tgamma(Real(4) / 3), tol * 20); - // - // We can do the same thing with ((1+x)(1-x))^-N ; N < 1 - // - Q = integrator.integrate([&](const Real& t, const Real & tc)->Real - { - return t < 0 ? 1 / sqrt(-tc * (1-t)) : 1 / sqrt((t + 1) * tc); - }, -1, 1); - BOOST_CHECK_CLOSE_FRACTION(Q, boost::math::constants::pi(), tol); - Q = integrator.integrate([&](const Real& t, const Real & tc)->Real - { - return t < 0 ? 1 / sqrt(-tc * (1-t)) : 1 / sqrt((t + 1) * tc); - }); - BOOST_CHECK_CLOSE_FRACTION(Q, boost::math::constants::pi(), tol); - Q = integrator.integrate([&](const Real& t, const Real & tc)->Real - { - return t < 0 ? 1 / boost::math::cbrt(-tc * (1-t)) : 1 / boost::math::cbrt((t + 1) * tc); - }, -1, 1); - BOOST_CHECK_CLOSE_FRACTION(Q, sqrt(boost::math::constants::pi()) * boost::math::tgamma(Real(2) / 3) / boost::math::tgamma(Real(7) / 6), tol * 10); - Q = integrator.integrate([&](const Real& t, const Real & tc)->Real - { - return t < 0 ? 1 / boost::math::cbrt(-tc * (1-t)) : 1 / boost::math::cbrt((t + 1) * tc); - }); - BOOST_CHECK_CLOSE_FRACTION(Q, sqrt(boost::math::constants::pi()) * boost::math::tgamma(Real(2) / 3) / boost::math::tgamma(Real(7) / 6), tol * 10); - // - // These are taken from above, and do not get to full precision via the single arg functor: - // - auto f7 = [](const Real& t, const Real& tc) { return t < 1 ? sqrt(tan(t)) : sqrt(1/tan(tc)); }; - Real error, L1; - Q = integrator.integrate(f7, (Real)0, (Real)half_pi(), get_convergence_tolerance(), &error, &L1); - Real Q_expected = pi() / root_two(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, Q_expected, tol); - - auto f8 = [](const Real& t, const Real& tc) { return t < 1 ? log(cos(t)) : log(sin(tc)); }; - Q = integrator.integrate(f8, (Real)0, half_pi(), get_convergence_tolerance(), &error, &L1); - Q_expected = -pi()*ln_two()*half(); - BOOST_CHECK_CLOSE_FRACTION(Q, Q_expected, tol); - BOOST_CHECK_CLOSE_FRACTION(L1, -Q_expected, tol); -} - -template -void test_complex() -{ - typedef typename Complex::value_type value_type; - // - // Integral version of the confluent hypergeometric function: - // https://dlmf.nist.gov/13.4#E1 - // - value_type tol = 10 * boost::math::tools::epsilon(); - Complex a(2, 3), b(3, 4), z(0.5, -2); - - auto f = [&](value_type t) - { - return exp(z * t) * pow(t, a - value_type(1)) * pow(value_type(1) - t, b - a - value_type(1)); - }; - - const auto& integrator = get_integrator(); - auto Q = integrator.integrate(f, value_type(0), value_type(1), get_convergence_tolerance()); - // - // Expected result computed from http://www.wolframalpha.com/input/?i=1F1%5B(2%2B3i),+(3%2B4i);+(0.5-2i)%5D+*+gamma(2%2B3i)+*+gamma(1%2Bi)+%2F+gamma(3%2B4i) - // - #ifdef BOOST_MATH_STANDALONE - BOOST_IF_CONSTEXPR (std::is_fundamental::value) - #endif - { - Complex expected(BOOST_MATH_TEST_VALUE(value_type, - 0.2911081612888249710582867318081776512805281815037891183828405999609246645054069649838607112484426042883371996), - BOOST_MATH_TEST_VALUE(value_type, 0.4507983563969959578849120188097153649211346293694903758252662015991543519595834937475296809912196906074655385)); - - value_type error = abs(expected - Q); - BOOST_CHECK_LE(error, tol); - - // - // Sin Integral https://dlmf.nist.gov/6.2#E9 - // - auto f2 = [z](value_type t) - { - return -exp(-z * cos(t)) * cos(z * sin(t)); - }; - Q = integrator.integrate(f2, value_type(0), boost::math::constants::half_pi(), get_convergence_tolerance()); - - expected = Complex(BOOST_MATH_TEST_VALUE(value_type, 0.8893822921008980697856313681734926564752476188106405688951257340480164694708337246829840859633322683740376134733), - -BOOST_MATH_TEST_VALUE(value_type, 2.381380802906111364088958767973164614925936185337231718483495612539455538280372745733208000514737758457795502168)); - expected -= boost::math::constants::half_pi(); - - error = abs(expected - Q); - BOOST_CHECK_LE(error, tol); - } -} - -template -void test_non_central_t() -{ - // - // Bug case from the non-central t distribution: - // - using std::pow; - using std::exp; - using std::sqrt; - - std::cout << "Testing non-central T PDF integral" << std::endl; - - T x = -1.882352352142334; - T v = 77.384613037109375; - T mu = 8.1538467407226562; - T expected = static_cast(4.5098555913703146875364186893655197e+49L); - - T left = 0; - T right = std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(); - - boost::math::quadrature::tanh_sinh integrator; - T err; - T L1; - std::size_t levels; - T integral = integrator.integrate([&x, v, mu](T y) - { - return pow(y, v) * exp(boost::math::pow<2>((y - mu * x / sqrt(x * x + v))) / -2); - }, - left, right, - boost::math::tools::root_epsilon(), &err, &L1, &levels); - - T tol = 100 * boost::math::tools::epsilon(); - BOOST_CHECK_CLOSE_FRACTION(integral, expected, tol); -} - - -BOOST_AUTO_TEST_CASE(tanh_sinh_quadrature_test) -{ -#ifdef GENERATE_CONSTANTS - // - // Generate pre-computed coefficients: - std::cout << std::setprecision(35); - print_levels(generate_constants(10, 8), "L"); - -#else - -#ifdef TEST1 - - test_right_limit_infinite(); - test_left_limit_infinite(); - test_linear(); - test_quadratic(); - test_singular(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_horrible(); - test_integration_over_real_line(); - test_nr_examples(); - - #ifdef __STDCPP_FLOAT32_T__ - test_right_limit_infinite(); - test_left_limit_infinite(); - test_linear(); - test_quadratic(); - test_singular(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_horrible(); - test_integration_over_real_line(); - test_nr_examples(); - #endif - -#endif -#ifdef TEST1A - test_early_termination(); - test_2_arg(); -#endif -#ifdef TEST1B - #ifndef BOOST_MATH_STANDALONE - test_crc(); - #endif -#endif -#ifdef TEST2 - test_right_limit_infinite(); - test_left_limit_infinite(); - test_linear(); - test_quadratic(); - test_singular(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_horrible(); - test_integration_over_real_line(); - test_nr_examples(); - test_early_termination(); - test_sf(); - test_2_arg(); - test_non_central_t(); -#endif -#ifdef TEST2A - #ifndef BOOST_MATH_STANDALONE - test_crc(); - #endif -#endif - -#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - -#ifdef TEST3 - test_right_limit_infinite(); - test_left_limit_infinite(); - test_linear(); - test_quadratic(); - test_singular(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_horrible(); - test_integration_over_real_line(); - test_nr_examples(); - test_early_termination(); - test_sf(); - test_2_arg(); - test_non_central_t(); -#endif -#ifdef TEST3A - #ifndef BOOST_MATH_STANDALONE - test_crc(); - #endif - -#endif -#endif - -#ifdef TEST4 - #ifdef BOOST_MATH_RUN_MP_TESTS - test_right_limit_infinite(); - test_left_limit_infinite(); - test_linear(); - test_quadratic(); - test_singular(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_horrible(); - test_nr_examples(); - test_early_termination(); - test_crc(); - test_sf(); - test_2_arg(); -#endif -#endif -#ifdef TEST5 - #ifdef BOOST_MATH_RUN_MP_TESTS - test_sf(); - test_sf(); - test_sf > >(); - #endif - -#endif -#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) -#ifdef TEST6 - - test_right_limit_infinite(); - test_left_limit_infinite(); - test_linear(); - test_quadratic(); - test_singular(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_horrible(); - test_integration_over_real_line(); - test_nr_examples(); - test_early_termination(); - test_sf(); - test_2_arg(); - test_non_central_t(); -#endif -#ifdef TEST6A - test_crc(); - -#endif -#endif -#ifdef TEST7 - #ifdef BOOST_MATH_RUN_MP_TESTS - test_sf(); - #endif -#endif -#if defined(TEST8) && defined(BOOST_HAS_FLOAT128) && !defined(BOOST_MATH_NO_MP_TESTS) - - test_right_limit_infinite(); - test_left_limit_infinite(); - test_linear(); - test_quadratic(); - test_singular(); - test_ca(); - test_three_quadrature_schemes_examples(); - test_horrible(); - test_integration_over_real_line(); - test_nr_examples(); - test_early_termination(); - test_crc(); - test_sf(); - test_2_arg(); - -#endif -#ifdef TEST9 - test_complex >(); - test_complex >(); -#endif - - -#endif -} - -#else - -int main() { return 0; } - -#endif diff --git a/test/test_0F1.cpp b/test/test_0F1.cpp index a5d79284c6..372e6bdb92 100644 --- a/test/test_0F1.cpp +++ b/test/test_0F1.cpp @@ -16,7 +16,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept|cpp_bin_float_quad|dec_40"; } diff --git a/test/test_0F1.hpp b/test/test_0F1.hpp index 160234a6a1..76e2717ebe 100644 --- a/test/test_0F1.hpp +++ b/test/test_0F1.hpp @@ -70,6 +70,19 @@ void test_spots(T, const char* type_name) BOOST_CHECK_THROW(boost::math::hypergeometric_0F1(T(-1), T(-1)), std::domain_error); BOOST_CHECK_THROW(boost::math::hypergeometric_0F1(T(-10), T(-5)), std::domain_error); + // + // Values from Arb: the continued fraction used for |z/b| < 4 loses digits as |z/b| increases: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + typedef boost::math::policies::policy, boost::math::policies::promote_double > no_promote; + T tol = boost::math::tools::epsilon() * 20; + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_0F1(T(4.1626372172798245), T(-15.278605051851581), no_promote()), static_cast(-0.02654682130764034819050775426638173461952L), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_0F1(T(6.7), T(-20.0), no_promote()), static_cast(0.012009242471182931317176314275578674493445L), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_0F1(T(12.5), T(-30.0), no_promote()), static_cast(0.068441050155700602021463722345924613949886L), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_0F1(T(3.3), T(-10.0), no_promote()), static_cast(-0.04255851577720615712187619528229191551525L), tol); + } + static const std::array, 50> hypergeometric_0F1_integer_data = { { { SC_(4.0), SC_(-20.0), SC_(-0.012889714201783047561923257996127233830940165138385) }, { SC_(8.0), SC_(-20.0), SC_(0.046498609282365144223175012935939437508273248399881) }, diff --git a/test/test_1F1.cpp b/test/test_1F1.cpp index 8ffd7aad40..3f070d7598 100644 --- a/test/test_1F1.cpp +++ b/test/test_1F1.cpp @@ -15,7 +15,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept|cpp_bin_float_quad|dec_40|cpp_bin_float_double_extended"; } @@ -71,6 +71,8 @@ void expected_results() "Small.*", // test data group ".*", 1000, 300); // test function + if(boost::math::policies::promote_double<>()) + { #if (LDBL_MANT_DIG < DBL_MANT_DIG * 2) && (LDBL_MANT_DIG != DBL_MANT_DIG) // // long double has only a little extra precision and errors may creep @@ -116,15 +118,21 @@ void expected_results() ".*", 10, 5); // test function #endif + } #if (defined(__aarch64__) && !defined(__APPLE__)) || defined(__s390__) - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - "double", // test type(s) - "Bug.*", // test data group - ".*", 10, 2); // test function + // + // Unpromoted double gets the largest type rows below: the worst bug case, + // 1F1(17955.56, -9.7e-9, -82.41) at 1.2e5 eps, has cond 4.5e4 in both a and z. + // + if(boost::math::policies::promote_double<>()) + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + "double", // test type(s) + "Bug.*", // test data group + ".*", 10, 2); // test function #endif add_expected_result( diff --git a/test/test_1F1.hpp b/test/test_1F1.hpp index b4c67faf1a..e9c4706772 100644 --- a/test/test_1F1.hpp +++ b/test/test_1F1.hpp @@ -420,6 +420,13 @@ void test_spots6(T, const char* type_name) T val = boost::math::hypergeometric_1F1(hypergeometric_1F1_big_bugs[i][0], hypergeometric_1F1_big_bugs[i][1], hypergeometric_1F1_big_bugs[i][2]); BOOST_CHECK((boost::math::isinf)(val)); } + // https://github.com/boostorg/math/issues/1288 + BOOST_CHECK_EQUAL(boost::math::hypergeometric_1F1(SC_(2.0), SC_(3.0), SC_(1e30)), + (std::numeric_limits::infinity)()); + // This is the largest log_hypergeometric_1F1 we can currently compute, beyond this the fix for the above + // bug causes premature overflow. However, there is no easy fix and Wolfram also fails in this case. It's **hard** :( + BOOST_CHECK_CLOSE_FRACTION(boost::math::log_hypergeometric_1F1(SC_(2.0), SC_(3.0), static_cast((std::numeric_limits::max)())), + SC_(9223372036854775765.02487480528339082), boost::math::tools::epsilon() * 10); } } @@ -432,7 +439,7 @@ void test_spots7(T, const char* type_name) } template -void test_spots8(T, const char* type_name) +void test_spots8(T, const char* /*type_name*/) { BOOST_CHECK_THROW(boost::math::hypergeometric_1F1(static_cast(2), static_cast(-100), static_cast(0.5)), std::domain_error); BOOST_CHECK_THROW(boost::math::hypergeometric_1F1(static_cast(-100.1), static_cast(-100), static_cast(0.5)), std::domain_error); @@ -440,6 +447,25 @@ void test_spots8(T, const char* type_name) BOOST_CHECK_THROW(boost::math::hypergeometric_1F1(static_cast(-50.25), static_cast(-100), static_cast(0.5)), std::domain_error); } +template +void test_spots9(T, const char* type_name) +{ + // + // Values from Arb: the Bessel function series (A&S 13.3.6) used when b - a is small relative to b + // was normalised using a Bessel I that is ill-conditioned, and used rounded orders. + // The inputs are exactly representable doubles, so we only test double, without promotion to long double: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + typedef boost::math::policies::policy, boost::math::policies::promote_double > no_promote; + T tol = boost::math::tools::epsilon() * 20; + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_1F1(T(2.5), T(2.6467452353166792), T(2.1236045729111082), no_promote()), static_cast(7.6229969267684479172456450199096452234456372656741L), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_1F1(T(2.5), T(3.1), T(7.0), no_promote()), static_cast(496.01424503510156054820225283083574607375L), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_1F1(T(0.3), T(5.0), T(-1.7), no_promote()), static_cast(0.91381409350285664938172257296860111244081L), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_1F1(T(0.3), T(10.0), T(-3.0), no_promote()), static_cast(0.92338769146325315656055820506546991002123L), tol); + } +} + template void test_spots(T z, const char* type_name) { @@ -463,6 +489,7 @@ void test_spots(T z, const char* type_name) test_spots6(z, type_name); test_spots7(z, type_name); test_spots8(z, type_name); + test_spots9(z, type_name); } diff --git a/test/test_1F1_log.cpp b/test/test_1F1_log.cpp index b0ea07332b..f9b16008ef 100644 --- a/test/test_1F1_log.cpp +++ b/test/test_1F1_log.cpp @@ -15,7 +15,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept|cpp_bin_float_quad|dec_40|cpp_bin_float_double_extended"; } @@ -72,6 +72,8 @@ void expected_results() ".*", 1000, 300); // test function #if (LDBL_MANT_DIG < DBL_MANT_DIG * 2) && (LDBL_MANT_DIG != DBL_MANT_DIG) + if(boost::math::policies::promote_double<>()) + { // // long double has only a little extra precision and errors may creep // into the double results: @@ -106,7 +108,7 @@ void expected_results() "double", // test type(s) "Bug.*", // test data group ".*", 300, 50); // test function - + } #endif add_expected_result( diff --git a/test/test_1F1_log.hpp b/test/test_1F1_log.hpp index 6a840cc8dd..3a9307be5a 100644 --- a/test/test_1F1_log.hpp +++ b/test/test_1F1_log.hpp @@ -78,7 +78,7 @@ void test_spots2(T, const char* type_name) } template -void test_sign(T, const char* type_name) +void test_sign(T, const char* /*type_name*/) { #include "hypergeometric_1F1_small_random.ipp" diff --git a/test/test_1F1_regularized.cpp b/test/test_1F1_regularized.cpp index f62e6f86fa..a9e7d25d54 100644 --- a/test/test_1F1_regularized.cpp +++ b/test/test_1F1_regularized.cpp @@ -17,7 +17,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept|cpp_bin_float_quad|dec_40|cpp_bin_float_double_extended"; } @@ -74,6 +74,8 @@ void expected_results() ".*", 1000, 300); // test function #if (LDBL_MANT_DIG < DBL_MANT_DIG * 2) && (LDBL_MANT_DIG != DBL_MANT_DIG) + if(boost::math::policies::promote_double<>()) + { // // long double has only a little extra precision and errors may creep // into the double results: @@ -108,7 +110,7 @@ void expected_results() "double", // test type(s) "Bug.*", // test data group ".*", 300, 50); // test function - + } #endif add_expected_result( diff --git a/test/test_2F0.cpp b/test/test_2F0.cpp index 4e5fe4bacf..1e8a1d25e1 100644 --- a/test/test_2F0.cpp +++ b/test/test_2F0.cpp @@ -16,7 +16,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept|cpp_bin_float_quad|dec_40"; } @@ -29,7 +29,7 @@ void expected_results() #endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if (boost::math::policies::digits >() != boost::math::policies::digits >()) + if (boost::math::policies::promote_double<>() && boost::math::policies::digits >() != boost::math::policies::digits >()) { add_expected_result( ".*", // compiler diff --git a/test/test_2F0.hpp b/test/test_2F0.hpp index 7a10f97c82..3214c7c6e5 100644 --- a/test/test_2F0.hpp +++ b/test/test_2F0.hpp @@ -105,4 +105,21 @@ void test_spots(T z, const char* type_name) BOOST_CHECK_EQUAL(boost::math::hypergeometric_2F0(T(0), T(20), T(2)), T(1)); BOOST_CHECK_EQUAL(boost::math::hypergeometric_2F0(T(20), T(0), T(2)), T(1)); BOOST_CHECK_EQUAL(boost::math::hypergeometric_2F0(T(20), T(10), T(0)), T(1)); + // + // Negative integer a1 with a2 > 0 and z > 0, where the series cancels: exact values, from the series + // in rational arithmetic. The last case may raise an evaluation_error rather than lose digits: + // + T tolerance = boost::math::tools::epsilon() * 4; + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_2F0(T(-20), T(7.5), T(0.0703125)), SC_(0.0009058711400604743835444245801821637120072), tolerance); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_2F0(T(7.5), T(-20), T(0.0703125)), SC_(0.0009058711400604743835444245801821637120072), tolerance); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_2F0(T(-50), T(1.25), T(0.03125)), SC_(0.3052122739096701050752227260666316776838), tolerance); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_2F0(T(-30), T(0.5), T(0.0625)), SC_(0.5866164156536446434351584193455355526903), tolerance); + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_2F0(T(-40), T(3), T(0.015625)), SC_(0.2278524180520048379881596526813574062803), tolerance); +#ifndef BOOST_NO_EXCEPTIONS + try + { + BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_2F0(T(-100), T(1.75), T(0.03125)), SC_(0.08262089934873659278920475540110746903509), tolerance); + } + catch (const boost::math::evaluation_error&) {} +#endif } diff --git a/test/acosh_test.hpp b/test/test_acosh.hpp similarity index 100% rename from test/acosh_test.hpp rename to test/test_acosh.hpp diff --git a/test/test_adaptive_gauss_kronrod_quadrature.cpp b/test/test_adaptive_gauss_kronrod_quadrature.cpp new file mode 100644 index 0000000000..d68b319ce5 --- /dev/null +++ b/test/test_adaptive_gauss_kronrod_quadrature.cpp @@ -0,0 +1,333 @@ +// Copyright Nick Thompson, 2017 +// 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) + +#include +#include +#include "math_unit_test.hpp" + +#if __has_include() +# include +#endif + +#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && !defined(BOOST_NO_SFINAE_EXPR) + +#include +#include +#include +#include +#include + +#if !defined(TEST1) && !defined(TEST1A) && !defined(TEST2) && !defined(TEST3) +# define TEST1 +# define TEST1A +# define TEST2 +# define TEST3 +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4127) // Conditional expression is constant +#endif + +using std::expm1; +using std::atan; +using std::tan; +using std::log; +using std::log1p; +using std::asinh; +using std::atanh; +using std::sqrt; +using std::isnormal; +using std::abs; +using std::sinh; +using std::tanh; +using std::cosh; +using std::pow; +using std::exp; +using std::sin; +using std::cos; +using std::string; +using boost::math::quadrature::gauss_kronrod; +using boost::math::constants::pi; +using boost::math::constants::half_pi; +using boost::math::constants::two_div_pi; +using boost::math::constants::two_pi; +using boost::math::constants::half; +using boost::math::constants::third; +using boost::math::constants::half; +using boost::math::constants::third; +using boost::math::constants::catalan; +using boost::math::constants::ln_two; +using boost::math::constants::root_two; +using boost::math::constants::root_two_pi; +using boost::math::constants::root_pi; +using boost::multiprecision::cpp_bin_float_quad; + +template +Real get_termination_condition() +{ + return boost::math::tools::epsilon() * 1000; +} + + +template +void test_linear() +{ + std::cout << "Testing linear functions are integrated properly by gauss_kronrod on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real error; + auto f = [](const Real& x) + { + return 5*x + 7; + }; + Real L1; + Real Q = gauss_kronrod::integrate(f, (Real) 0, (Real) 1, 15, get_termination_condition(), &error, &L1); + CHECK_ULP_CLOSE(Real(9.5), Q, 8); + CHECK_ULP_CLOSE(Real(9.5), L1, 8); + CHECK_LE(abs(error / Q), get_termination_condition()); + CHECK_GE(abs(error), abs(Q - Real(9.5))); +} + +template +void test_quadratic() +{ + std::cout << "Testing quadratic functions are integrated properly by gauss-kronrod on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real error; + + auto f = [](const Real& x) { return 5*x*x + 7*x + 12; }; + Real L1; + Real Q = gauss_kronrod::integrate(f, 0, 1, 15, get_termination_condition(), &error, &L1); + CHECK_ULP_CLOSE((Real) 17 + half()*third(), Q, 8); + CHECK_ULP_CLOSE((Real) 17 + half()*third(), L1, 8); + CHECK_LE(abs(error / Q), get_termination_condition()); + CHECK_GE(abs(error), abs(Q - ((Real)17 + half()*third()))); +} + +// Examples taken from +//http://crd-legacy.lbl.gov/~dhbailey/dhbpapers/quadrature.pdf +template +void test_ca() +{ + std::cout << "Testing integration of C(a) on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real L1; + Real error; + + auto f1 = [](const Real& x) { return atan(x)/(x*(x*x + 1)) ; }; + Real Q = gauss_kronrod::integrate(f1, 0, 1, 15, get_termination_condition(), &error, &L1); + Real Q_expected = pi()*ln_two()/8 + catalan()*half(); + CHECK_ULP_CLOSE(Q_expected, Q, 8); + CHECK_ULP_CLOSE(Q_expected, L1, 8); + CHECK_LE(abs(error / Q), get_termination_condition()); + CHECK_GE(abs(error), abs(Q - Q_expected)); + + auto f2 = [](Real x)->Real { Real t0 = x*x + 1; Real t1 = sqrt(t0); return atan(t1)/(t0*t1); }; + Q = gauss_kronrod::integrate(f2, 0 , 1, 15, get_termination_condition(), &error, &L1); + Q_expected = pi()/4 - pi()/root_two() + 3*atan(root_two())/root_two(); + CHECK_ULP_CLOSE(Q_expected, Q, 8); + CHECK_ULP_CLOSE(Q_expected, L1, 8); + CHECK_LE(abs(error / Q), get_termination_condition()); + CHECK_GE(abs(error), abs(Q - Q_expected)); + + auto f5 = [](Real t)->Real { return t*t*log(t)/((t*t - 1)*(t*t*t*t + 1)); }; + Q = gauss_kronrod::integrate(f5, 0, 1, 25); + Q_expected = pi()*pi()*(2 - root_two())/32; + CHECK_ULP_CLOSE(Q_expected, Q, 1192); +} + +template +void test_three_quadrature_schemes_examples() +{ + std::cout << "Testing integral in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real Q; + Real Q_expected; + + // Example 1: + auto f1 = [](const Real& t) { return t*boost::math::log1p(t); }; + Q = gauss_kronrod::integrate(f1, 0 , 1); + Q_expected = half()*half(); + CHECK_ULP_CLOSE(Q_expected, Q, 4); + + + // Example 2: + auto f2 = [](const Real& t) { return t*t*atan(t); }; + Q = gauss_kronrod::integrate(f2, 0, 1); + Q_expected = (pi() -2 + 2*ln_two())/12; + CHECK_ULP_CLOSE(Q_expected, Q, 40); + + // Example 3: + auto f3 = [](const Real& t) { return exp(t)*cos(t); }; + Q = gauss_kronrod::integrate(f3, 0, half_pi()); + Q_expected = boost::math::expm1(half_pi())*half(); + CHECK_ULP_CLOSE(Q_expected, Q, 12); + + // Example 4: + auto f4 = [](Real x)->Real { Real t0 = sqrt(x*x + 2); return atan(t0)/(t0*(x*x+1)); }; + Q = gauss_kronrod::integrate(f4, 0, 1); + Q_expected = 5*pi()*pi()/96; + CHECK_ULP_CLOSE(Q_expected, Q, 8); +} + + +template +void test_integration_over_real_line() +{ + std::cout << "Testing integrals over entire real line in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real Q; + Real Q_expected; + Real L1; + Real error; + + auto f1 = [](const Real& t) { return 1/(1+t*t);}; + Q = gauss_kronrod::integrate(f1, -boost::math::tools::max_value(), boost::math::tools::max_value(), 15, get_termination_condition(), &error, &L1); + Q_expected = pi(); + CHECK_ULP_CLOSE(Q_expected, Q, 8); + CHECK_ULP_CLOSE(Q_expected, L1, 8); + CHECK_LE(abs(error / Q), get_termination_condition()); + + auto f4 = [](const Real& t) { return 1/cosh(t);}; + Q = gauss_kronrod::integrate(f4, -boost::math::tools::max_value(), boost::math::tools::max_value(), 15, get_termination_condition(), &error, &L1); + Q_expected = pi(); + CHECK_ULP_CLOSE(Q_expected, Q, 4); + CHECK_ULP_CLOSE(Q_expected, L1, 4); + CHECK_LE(abs(error / Q), get_termination_condition()); + +} + +template +void test_right_limit_infinite() +{ + std::cout << "Testing right limit infinite for Gauss-Kronrod in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real Q; + Real Q_expected; + Real L1; + Real error; + + // Example 11: + auto f1 = [](const Real& t) { return 1/(1+t*t);}; + Q = gauss_kronrod::integrate(f1, 0, boost::math::tools::max_value(), 15, get_termination_condition(), &error, &L1); + Q_expected = half_pi(); + CHECK_ULP_CLOSE(Q_expected, Q, 8); + CHECK_LE(abs(error / Q), get_termination_condition()); + + auto f4 = [](const Real& t) { return 1/(1+t*t); }; + Q = gauss_kronrod::integrate(f4, 1, boost::math::tools::max_value(), 15, get_termination_condition(), &error, &L1); + Q_expected = pi()/4; + CHECK_ULP_CLOSE(Q_expected, Q, 4); + CHECK_LE(abs(error / Q), get_termination_condition()); +} + +template +void test_left_limit_infinite() +{ + std::cout << "Testing left limit infinite for Gauss-Kronrod in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real Q; + Real Q_expected; + + // Example 11: + auto f1 = [](const Real& t) { return 1/(1+t*t);}; + Q = gauss_kronrod::integrate(f1, -boost::math::tools::max_value(), 0); + Q_expected = half_pi(); + CHECK_ULP_CLOSE(Q_expected, Q, 60); +} + +void gauss_quadrature_test() +{ +#ifdef TEST1 + std::cout << "Testing with 15 point Gauss-Kronrod rule:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + // test one case where we do not have pre-computed constants: + std::cout << "Testing with 17 point Gauss-Kronrod rule:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + #ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + #endif + +#endif +#ifdef TEST1A +#if LDBL_MANT_DIG < 100 // If we have too many digits in a long double, we get build errors due to a constexpr issue. + std::cout << "Testing with 21 point Gauss-Kronrod rule:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + std::cout << "Testing with 31 point Gauss-Kronrod rule:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#endif +#endif +#ifdef TEST2 +#if LDBL_MANT_DIG < 100 // If we have too many digits in a long double, we get build errors due to a constexpr issue. + std::cout << "Testing with 41 point Gauss-Kronrod rule:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + std::cout << "Testing with 51 point Gauss-Kronrod rule:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#endif +#endif +#ifdef TEST3 +#if LDBL_MANT_DIG < 100 // If we have too many digits in a long double, we get build errors due to a constexpr issue. + std::cout << "Testing with 61 point Gauss-Kronrod rule:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#endif +#endif +} + +int main() +{ + gauss_quadrature_test(); + return boost::math::test::report_errors(); +} + +#else + +int main() { return 0; } + +#endif diff --git a/test/agm_test.cpp b/test/test_agm.cpp similarity index 100% rename from test/agm_test.cpp rename to test/test_agm.cpp diff --git a/test/test_agm_module.cpp b/test/test_agm_module.cpp new file mode 100644 index 0000000000..0096a3f515 --- /dev/null +++ b/test/test_agm_module.cpp @@ -0,0 +1,74 @@ +/* + * Copyright Nick Thompson, 2019 + * Copyright Matt Borland, 2026 + * 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) + * + * Module build check for boost::math::tools::agm. It exercises the exported + * arithmetic-geometric mean entry point when the test is built against the + * boost.math module. The double and float expected values mirror the + * assertions in test_agm.cpp. + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif +#include "math_unit_test.hpp" + +using boost::math::tools::agm; +using std::sqrt; + +// Gauss's constant G = 1/agm(sqrt(2), 1). http://oeis.org/A014549/constant +template +void test_gauss_constant() +{ + const double G_expected = 0.83462684167407318628142973279904680899399301349034700244982737010368199270952641186969116035127532412906785; + Real G_computed = 1 / agm(Real(sqrt(Real(2))), Real(1)); + CHECK_ULP_CLOSE(G_expected, G_computed, 2); +} + +// All of these are mathematically-exact properties of the agm. +template +void test_scaling() +{ + Real a = 2; + Real g = 1; + Real scale = 7; + + // Homogeneity: agm(k*x, k*y) = k*agm(x, y). + Real expected = agm(scale * a, scale * g); + Real computed = scale * agm(a, g); + CHECK_ULP_CLOSE(expected, computed, 2); + + // agm(a, 0) = 0 and agm(0, 0) = 0. + CHECK_ULP_CLOSE(Real(0), agm(a, Real(0)), 0); + CHECK_ULP_CLOSE(Real(0), agm(Real(0), Real(0)), 0); + + // agm(x, x) = x. + CHECK_ULP_CLOSE(Real(1), agm(Real(1), Real(1)), 0); + CHECK_ULP_CLOSE(Real(7), agm(Real(7), Real(7)), 0); + + // Composition identity: agm(x, y) = agm((x+y)/2, sqrt(x*y)). + // With x = 3, y = 1: (x+y)/2 = 2, sqrt(x*y) = sqrt(3). + expected = agm(Real(3), Real(1)); + computed = agm(Real(2), Real(sqrt(Real(3)))); + CHECK_ULP_CLOSE(expected, computed, 0); +} + +int main() +{ + test_gauss_constant(); + test_scaling(); + + test_gauss_constant(); + test_scaling(); + + return boost::math::test::report_errors(); +} diff --git a/test/test_airy.cpp b/test/test_airy.cpp index f5f0900c45..458e39a2f1 100644 --- a/test/test_airy.cpp +++ b/test/test_airy.cpp @@ -20,6 +20,9 @@ #include #endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT +#include +#endif #include #include #include @@ -73,8 +76,40 @@ void test_airy(T, const char* name) if(boost::math::isfinite(data[i][4])) BOOST_CHECK_CLOSE_FRACTION(data[i][4], boost::math::airy_bi_prime(data[i][0]), tol); } + // + // Tiny x, where the constant term alone is not enough: the linear term Ai'(0) x (Bi'(0) x) is + // larger than epsilon even though x^3 / 6 < epsilon. Values calculated with Arb. + // x is 2^-8, 2^-17 or 2^-21 so that it falls in the small x branch for float, double and long double. + // + static const std::array, 3> tiny_data = + {{ + {{ static_cast(0.00390625L), static_cast(0.3540170441136166768862928636689060871265703L), static_cast(0.6166777599593592690509375843380791217066058L) }}, + {{ static_cast(7.62939453125e-06L), static_cast(0.3550260792524733873116489237624088683003536L), static_cast(0.6149300476147427989932986279340157797699888L) }}, + {{ static_cast(4.76837158203125e-07L), static_cast(0.3550279304731082468773725646572280145097495L), static_cast(0.6149268412065471113075676385395360226412311L) }}, + }}; + const unsigned row = boost::math::tools::digits() <= 24 ? 0 : boost::math::tools::digits() <= 53 ? 1 : 2; + BOOST_CHECK_CLOSE_FRACTION(tiny_data[row][1], boost::math::airy_ai(tiny_data[row][0]), 4 * boost::math::tools::epsilon()); + BOOST_CHECK_CLOSE_FRACTION(tiny_data[row][2], boost::math::airy_bi(tiny_data[row][0]), 4 * boost::math::tools::epsilon()); } +#ifndef BOOST_MATH_HAS_GPU_SUPPORT +// +// A type wider than the 113-bit constants: the values at zero, and at x = 2^-40, where the linear +// term Ai'(0) x is far larger than epsilon. Values calculated with Arb. +// +void test_airy_multiprecision() +{ + using T = boost::multiprecision::cpp_bin_float_50; + T tol = 4 * boost::math::tools::epsilon(); + T x = ldexp(T(1), -40); + BOOST_CHECK_CLOSE_FRACTION(boost::math::airy_ai(T(0)), T("0.355028053887817239260063186004183176397979174199177240583"), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::airy_bi(T(0)), T("0.614926627446000735150922369093613553594728188648596505041"), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::airy_ai_prime(T(0)), T("-0.258819403792806798405183560189203963479091138354934582210"), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::airy_bi_prime(T(0)), T("0.448288357353826357914823710398828390866226799212262061083"), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::airy_ai(x), T("0.355028053887581844383597600093405091606994037136788370360"), tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::airy_bi(x), T("0.614926627446408451036802163278338535596058257122885820486"), tol); +} +#endif BOOST_AUTO_TEST_CASE( test_main ) { @@ -87,6 +122,9 @@ BOOST_AUTO_TEST_CASE( test_main ) test_airy(0.1F, "float"); #endif test_airy(0.1, "double"); +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + test_airy_multiprecision(); +#endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_airy(0.1L, "long double"); #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS diff --git a/test/anderson_darling_test.cpp b/test/test_anderson_darling.cpp similarity index 100% rename from test/anderson_darling_test.cpp rename to test/test_anderson_darling.cpp diff --git a/test/test_anderson_darling_module.cpp b/test/test_anderson_darling_module.cpp new file mode 100644 index 0000000000..d786b7ca01 --- /dev/null +++ b/test/test_anderson_darling_module.cpp @@ -0,0 +1,76 @@ +/* + * Copyright Nick Thompson, 2019 + * (C) Copyright Matt Borland 2026. + * 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) + * + * Module build check for boost::math::statistics::anderson_darling_normality_statistic. + * It exercises the exported normality-statistic entry point when the test is built + * against the boost.math module. The double expected value and the scale/shift + * invariance checks mirror the assertions in test_anderson_darling.cpp. + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif +#include "math_unit_test.hpp" + +using boost::math::statistics::anderson_darling_normality_statistic; + +// The Anderson-Darling normality statistic agrees with Mathematica's +// AndersonDarlingTest and is invariant under affine rescaling of the data. +void test_ad_normal_agreement_w_mathematica() +{ + // To reproduce: + // data = RandomVariate[NormalDistribution[0.0, 1], 32]; + // AndersonDarlingTest[data, NormalDistribution[0.0, 1.0], "TestStatistic"] + std::vector v = {0.6018671202167422, 0.34935310534248165, -0.2975464874480147, 0.19075371678288966, 0.7871329594028097, 1.153968559452821, + -0.22255484635945819, 0.08509539017654276, -1.3495873906132927, 0.5579622886226612, -0.8781637835839865, 1.144016010880056, + 0.3117638373078617, 1.2774825413798292, 0.24847416220730323, -0.5002468827503855, -0.23124277830160153, 0.1880980838556693, + -1.2249409521605903, 2.583585311795, -1.4237305768919715, -0.7613985266437971, -1.089096700141564, -1.2595396780059587, + -0.735507006841229, -0.6957024998691735, 0.24671590370045435, 0.24620128485023313, -2.4445908627621833, 0.1882647961008893, + 1.8527432579288248, -0.1908629038857823, -1.6542624501251562, 1.414542907065601, 0.8188282235404601, -0.5040501225935047, + -1.634617885381599, -0.43608956281596023, -1.7347258501594351, 0.8387606547880405, 0.3554282034994122, -0.27872688042721255, + -1.6445047421517192, 1.0262620986278987, -0.14517030192098415, -0.15386932114942647, -0.13364750619758223, 0.27194802295714676, + -0.6396907621289796, 0.3390884293844603, -0.08298748318375798, -0.7165572035514544, -0.2580817977433051, -1.9250094572058072, + -0.07995578394716944, -1.146629910012214, -2.0053073148074665, -1.6745995591714353, 0.2973860474005926, -0.4981763213542575, + 0.22190763958244972, 0.699111028057888, -1.1872952966557475, 0.6151420566782272}; + + double expected = 1.542329830419774; + std::sort(v.begin(), v.end()); + double ADtest = anderson_darling_normality_statistic(v, 0.0, 1.0); + + CHECK_ULP_CLOSE(expected, ADtest, 250); + + // Scaling the data and the supplied standard deviation leaves the statistic unchanged. + double sigma = 2; + for (auto & x : v) + { + x *= sigma; + } + ADtest = anderson_darling_normality_statistic(v, 0.0, sigma); + CHECK_ULP_CLOSE(expected, ADtest, 250); + + // Shifting the data and the supplied mean leaves the statistic unchanged. + double mu = 10; + for (auto & x : v) + { + x += mu; + } + ADtest = anderson_darling_normality_statistic(v, mu, sigma); + CHECK_ULP_CLOSE(expected, ADtest, 250); +} + +int main() +{ + test_ad_normal_agreement_w_mathematica(); + return boost::math::test::report_errors(); +} diff --git a/test/test_archive.cpp b/test/test_archive.cpp deleted file mode 100644 index b73773be36..0000000000 --- a/test/test_archive.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (c) 2006 Johan Rade -// Copyright (c) 2011 Paul A. Bristow - filename changes for boost-trunk. - -// 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) - -//#ifdef _MSC_VER -//# pragma warning(disable : 4511 4512 4702) -//#endif - -#define BOOST_TEST_MAIN - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "almost_equal.ipp" - -namespace { - -// The anonymous namespace resolves ambiguities on platforms -// with fpclassify etc functions at global scope. - -using namespace boost::archive; - -using namespace boost::math; -using boost::math::signbit; -using boost::math::changesign; -using (boost::math::isnan)(; - -//------------------------------------------------------------------------------ - -void archive_basic_test(); -void archive_put_trap_test(); -void archive_get_trap_test(); - -BOOST_AUTO_TEST_CASE(archive_test) -{ - archive_basic_test(); - archive_put_trap_test(); - archive_get_trap_test(); -} - -//------------------------------------------------------------------------------ - -template -void archive_basic_test_impl(); - -void archive_basic_test() -{ - archive_basic_test_impl(); - archive_basic_test_impl(); - archive_basic_test_impl< - char, text_oarchive, text_iarchive, long double>(); - archive_basic_test_impl< - wchar_t, text_woarchive, text_wiarchive, float>(); - archive_basic_test_impl< - wchar_t, text_woarchive, text_wiarchive, double>(); - archive_basic_test_impl< - wchar_t, text_woarchive, text_wiarchive, long double>(); -} - -template -void archive_basic_test_impl() -{ - if((std::numeric_limits::has_infinity == 0) || (std::numeric_limits::infinity() == 0)) - return; - std::locale default_locale(std::locale::classic(), - new boost::archive::codecvt_null); - std::locale tmp_locale(default_locale, new nonfinite_num_put); - std::locale my_locale(tmp_locale, new nonfinite_num_get); - - std::basic_stringstream ss; - ss.imbue(my_locale); - - ValType a1 = static_cast(0); - ValType a2 = static_cast(2307.35); - ValType a3 = std::numeric_limits::infinity(); - BOOST_CHECK((boost::math::isinf)(a3)); - ValType a4 = std::numeric_limits::quiet_NaN(); - BOOST_CHECK(((boost::math::isnan)()(a4)); - ValType a5 = std::numeric_limits::signaling_NaN(); - BOOST_CHECK(((boost::math::isnan)()(a5)); - ValType a6 = (changesign)(static_cast(0)); - ValType a7 = static_cast(-57.13); - ValType a8 = -std::numeric_limits::infinity(); - BOOST_CHECK((boost::math::isinf)(a8)); - ValType a9 = -std::numeric_limits::quiet_NaN(); - BOOST_CHECK(((boost::math::isnan)()(a9)); - ValType a10 = -std::numeric_limits::signaling_NaN(); - BOOST_CHECK(((boost::math::isnan)()(a10)); - - { - OArchiveType oa(ss, no_codecvt); - oa & a1 & a2 & a3 & a4 & a5 & a6 & a7 & a8 & a9 & a10; - } - - ValType b1, b2, b3, b4, b5, b6, b7, b8, b9, b10; - - { - IArchiveType ia(ss, no_codecvt); - ia & b1 & b2 & b3 & b4 & b5 & b6 & b7 & b8 & b9 & b10; - } - - BOOST_CHECK(a1 == b1); - BOOST_CHECK(almost_equal(a2, b2)); - BOOST_CHECK(a3 == b3); - BOOST_CHECK((isnan)(b4)); - BOOST_CHECK(!(signbit)(b4)); - BOOST_CHECK((isnan)(b5)); - BOOST_CHECK(!(signbit)(b5)); - BOOST_CHECK(a6 == b6); - BOOST_CHECK(almost_equal(a7, b7)); - BOOST_CHECK(a8 == b8); - BOOST_CHECK((isnan)(b9)); - BOOST_CHECK((signbit)(b9)); - BOOST_CHECK((isnan)(b10)); - BOOST_CHECK((signbit)(b10)); -} - -//------------------------------------------------------------------------------ - -template -void archive_put_trap_test_impl(); - -void archive_put_trap_test() -{ - archive_put_trap_test_impl(); - archive_put_trap_test_impl(); - archive_put_trap_test_impl< - char, text_oarchive, text_iarchive, long double>(); - archive_put_trap_test_impl< - wchar_t, text_woarchive, text_wiarchive, float>(); - archive_put_trap_test_impl< - wchar_t, text_woarchive, text_wiarchive, double>(); - archive_put_trap_test_impl< - wchar_t, text_woarchive, text_wiarchive, long double>(); -} - -template -void archive_put_trap_test_impl() -{ - if((std::numeric_limits::has_infinity == 0) || (std::numeric_limits::infinity() == 0)) - return; - - std::locale default_locale(std::locale::classic(), - new boost::archive::codecvt_null); - std::locale new_locale(default_locale, - new nonfinite_num_put(trap_infinity)); - - std::basic_stringstream ss; - ss.exceptions(std::ios_base::failbit | std::ios_base::badbit); - ss.imbue(new_locale); - - ValType a = std::numeric_limits::infinity(); - - OArchiveType oa(ss, no_codecvt); - - try { - oa & a; - } - catch(std::exception&) { - ss.clear(); - return; - } - - BOOST_CHECK(false); -} - -//------------------------------------------------------------------------------ - -template -void archive_get_trap_test_impl(); - -void archive_get_trap_test() -{ - archive_get_trap_test_impl(); - archive_get_trap_test_impl(); - archive_get_trap_test_impl< - char, text_oarchive, text_iarchive, long double>(); - archive_get_trap_test_impl< - wchar_t, text_woarchive, text_wiarchive, float>(); - archive_get_trap_test_impl< - wchar_t, text_woarchive, text_wiarchive, double>(); - archive_get_trap_test_impl< - wchar_t, text_woarchive, text_wiarchive, long double>(); -} - -template -void archive_get_trap_test_impl() -{ - if((std::numeric_limits::has_infinity == 0) || (std::numeric_limits::infinity() == 0)) - return; - - std::locale default_locale(std::locale::classic(), - new boost::archive::codecvt_null); - std::locale tmp_locale(default_locale, new nonfinite_num_put); - std::locale my_locale(tmp_locale, - new nonfinite_num_get(trap_nan)); - - std::basic_stringstream ss; - ss.exceptions(std::ios_base::failbit); - ss.imbue(my_locale); - - ValType a = -std::numeric_limits::quiet_NaN(); - - { - OArchiveType oa(ss, no_codecvt); - oa & a; - } - - ValType b; - { - IArchiveType ia(ss, no_codecvt); - try { - ia & b; - } - catch(std::exception&) { - return; - } - } - - BOOST_CHECK(false); -} - -//------------------------------------------------------------------------------ - -} // anonymous namespace diff --git a/test/test_arcsine.cpp b/test/test_arcsine.cpp index dc2fba919e..5a4b1f11d2 100644 --- a/test/test_arcsine.cpp +++ b/test/test_arcsine.cpp @@ -297,6 +297,10 @@ void test_spots(RealType) BOOST_CHECK_EQUAL(mean(arcsine_01), 0.5); // 1 / (1 + 1) = 1/2 exactly. BOOST_CHECK_EQUAL(median(arcsine_01), 0.5); // 1 / (1 + 1) = 1/2 exactly. BOOST_CHECK_EQUAL(variance(arcsine_01), 0.125); // 1/8 = 0.125 + // entropy = log(pi (x_max - x_min) / 4), as for beta(1/2, 1/2) scaled to [x_min, x_max]: + BOOST_CHECK_CLOSE_FRACTION(entropy(arcsine_01), static_cast(-0.24156447527049044469103689156329442450L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(entropy(arcsine_distribution(-1, 1)), static_cast(0.45158270528945486472619522989488214357L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(entropy(arcsine_distribution(2, 1002)), static_cast(6.6661908037116466073629374724897981983L), tolerance); BOOST_CHECK_CLOSE_FRACTION(standard_deviation(arcsine_01), one_div_root_two() / 2, tolerance); // 1/ sqrt(s) = 0.35355339059327379 BOOST_CHECK_EQUAL(skewness(arcsine_01), 0); // BOOST_CHECK_EQUAL(kurtosis_excess(arcsine_01), -1.5); // -3/2 diff --git a/test/asinh_test.hpp b/test/test_asinh.hpp similarity index 100% rename from test/asinh_test.hpp rename to test/test_asinh.hpp diff --git a/test/atanh_test.hpp b/test/test_atanh.hpp similarity index 100% rename from test/atanh_test.hpp rename to test/test_atanh.hpp diff --git a/test/test_autodiff.hpp b/test/test_autodiff.hpp index 3a53827262..a37d20cb9c 100644 --- a/test/test_autodiff.hpp +++ b/test/test_autodiff.hpp @@ -6,25 +6,18 @@ #ifndef BOOST_MATH_TEST_AUTODIFF_HPP #define BOOST_MATH_TEST_AUTODIFF_HPP -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MODULE test_autodiff -#endif - -#ifndef BOOST_ALLOW_DEPRECATED_HEADERS -#define BOOST_ALLOW_DEPRECATED_HEADERS // artifact of sp_typeinfo.hpp inclusion from unit_test.hpp -#endif - #include #include #include #include +#include #include #include #include #include #include -#include +#include "math_unit_test.hpp" #include #include @@ -134,7 +127,7 @@ struct RandomSample { template RandomSample(U start, V finish) - : rng_(std::random_device{}()), + : rng_(42), dist_(static_cast(start), get_endpoint_t{}(finish)) {} @@ -172,7 +165,7 @@ auto isNearZero(const T& t) noexcept -> typename std::enable_if::epsilon())); + return fpclassify(fabs(t)) == FP_ZERO || fpclassify(fabs(t)) == FP_SUBNORMAL || fabs(t) <= sqrt(std::numeric_limits::epsilon()); } template diff --git a/test/test_autodiff_1.cpp b/test/test_autodiff_1.cpp index 144f610516..918e760620 100644 --- a/test/test_autodiff_1.cpp +++ b/test/test_autodiff_1.cpp @@ -4,21 +4,23 @@ // https://www.boost.org/LICENSE_1_0.txt) #include "test_autodiff.hpp" +#include +#include -BOOST_AUTO_TEST_SUITE(test_autodiff_1) -BOOST_AUTO_TEST_CASE_TEMPLATE(constructors, T, all_float_types) { +template +void constructors() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; // Verify value-initialized instance has all 0 entries. const autodiff_fvar empty1 = autodiff_fvar(); for (auto i : boost::irange(m + 1)) { - BOOST_CHECK_EQUAL(empty1.derivative(i), 0); + CHECK_EQUAL(empty1.derivative(i), static_cast(0)); } const auto empty2 = autodiff_fvar(); for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { - BOOST_CHECK_EQUAL(empty2.derivative(i, j), 0); + CHECK_EQUAL(empty2.derivative(i, j), static_cast(0)); } } // Single variable @@ -26,21 +28,21 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(constructors, T, all_float_types) { const auto x = make_fvar(cx); for (auto i : boost::irange(m + 1)) { if (i == 0u) { - BOOST_CHECK_EQUAL(x.derivative(i), cx); + CHECK_EQUAL(x.derivative(i), cx); } else if (i == 1) { - BOOST_CHECK_EQUAL(x.derivative(i), 1); + CHECK_EQUAL(x.derivative(i), static_cast(1)); } else { - BOOST_CHECK_EQUAL(x.derivative(i), 0); + CHECK_EQUAL(x.derivative(i), static_cast(0)); } } const autodiff_fvar xn = x; for (auto i : boost::irange(n + 1)) { if (i == 0) { - BOOST_CHECK_EQUAL(xn.derivative(i), cx); + CHECK_EQUAL(xn.derivative(i), cx); } else if (i == 1) { - BOOST_CHECK_EQUAL(xn.derivative(i), 1); + CHECK_EQUAL(xn.derivative(i), static_cast(1)); } else { - BOOST_CHECK_EQUAL(xn.derivative(i), 0); + CHECK_EQUAL(xn.derivative(i), static_cast(0)); } } // Second independent variable @@ -49,27 +51,34 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(constructors, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(y.derivative(i, j), cy); + CHECK_EQUAL(y.derivative(i, j), cy); } else if (i == 0 && j == 1) { - BOOST_CHECK_EQUAL(y.derivative(i, j), static_cast(1.0)); + CHECK_EQUAL(y.derivative(i, j), static_cast(1.0)); } else { - BOOST_CHECK_EQUAL(y.derivative(i, j), static_cast(0.0)); + CHECK_EQUAL(y.derivative(i, j), static_cast(0.0)); } } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(implicit_constructors, T, all_float_types) { +template +void implicit_constructors() { constexpr std::size_t m = 3; const autodiff_fvar x = 3; const autodiff_fvar one = uncast_return(x); const autodiff_fvar two_and_a_half = 2.5; - BOOST_CHECK_EQUAL(static_cast(x), static_cast(3.0)); - BOOST_CHECK_EQUAL(static_cast(one), static_cast(1.0)); - BOOST_CHECK_EQUAL(static_cast(two_and_a_half), static_cast(2.5)); + CHECK_EQUAL(static_cast(x), static_cast(3.0)); + CHECK_EQUAL(static_cast(one), static_cast(1.0)); + CHECK_EQUAL(static_cast(two_and_a_half), static_cast(2.5)); + // Only types that T can be constructed from convert implicitly (#424: Eigen expressions must not). + CHECK_TRUE((std::is_convertible>::value)); + CHECK_TRUE((std::is_convertible, m>>::value)); + CHECK_TRUE((!std::is_convertible, autodiff_fvar>::value)); + CHECK_TRUE((!std::is_constructible, std::vector>::value)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(assignment, T, all_float_types) { +template +void assignment() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 10; @@ -83,11 +92,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(empty.derivative(i, j), cx); + CHECK_EQUAL(empty.derivative(i, j), cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(empty.derivative(i, j), 1.0); + CHECK_EQUAL(empty.derivative(i, j), static_cast(1.0)); } else { - BOOST_CHECK_EQUAL(empty.derivative(i, j), 0.0); + CHECK_EQUAL(empty.derivative(i, j), static_cast(0.0)); } } } @@ -96,11 +105,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(empty.derivative(i, j), cy); + CHECK_EQUAL(empty.derivative(i, j), cy); } else if (i == 0 && j == 1) { - BOOST_CHECK_EQUAL(empty.derivative(i, j), 1.0); + CHECK_EQUAL(empty.derivative(i, j), static_cast(1.0)); } else { - BOOST_CHECK_EQUAL(empty.derivative(i, j), 0.0); + CHECK_EQUAL(empty.derivative(i, j), static_cast(0.0)); } } } @@ -108,28 +117,30 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(empty.derivative(i, j), cx); + CHECK_EQUAL(empty.derivative(i, j), cx); } else { - BOOST_CHECK_EQUAL(empty.derivative(i, j), 0.0); + CHECK_EQUAL(empty.derivative(i, j), static_cast(0.0)); } } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ostream, T, all_float_types) { +template +void ostream() { constexpr std::size_t m = 3; const T cx = 10; const auto x = make_fvar(cx); std::ostringstream ss; ss << "x = " << x; - BOOST_CHECK_EQUAL(ss.str(), "x = depth(1)(10,1,0,0)"); + CHECK_EQUAL(ss.str(), std::string("x = depth(1)(10,1,0,0)")); ss.str(std::string()); const auto scalar = make_fvar(cx); ss << "scalar = " << scalar; - BOOST_CHECK_EQUAL(ss.str(), "scalar = depth(1)(10)"); + CHECK_EQUAL(ss.str(), std::string("scalar = depth(1)(10)")); } -BOOST_AUTO_TEST_CASE_TEMPLATE(addition_assignment, T, all_float_types) { +template +void addition_assignment() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 10; @@ -140,11 +151,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(addition_assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(sum.derivative(i, j), cx); + CHECK_EQUAL(sum.derivative(i, j), cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(sum.derivative(i, j), T(1)); + CHECK_EQUAL(sum.derivative(i, j), T(1)); } else { - BOOST_CHECK_EQUAL(sum.derivative(i, j), T(0)); + CHECK_EQUAL(sum.derivative(i, j), T(0)); } } } @@ -155,15 +166,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(addition_assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(sum.derivative(i, j), cy); + CHECK_EQUAL(sum.derivative(i, j), cy); } else { - BOOST_CHECK_EQUAL(sum.derivative(i, j), T(0)); + CHECK_EQUAL(sum.derivative(i, j), T(0)); } } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(subtraction_assignment, T, all_float_types) { +template +void subtraction_assignment() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 10; @@ -174,11 +186,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(subtraction_assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(sum.derivative(i, j), -cx); + CHECK_EQUAL(sum.derivative(i, j), -cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(sum.derivative(i, j), T(-1)); + CHECK_EQUAL(sum.derivative(i, j), T(-1)); } else { - BOOST_CHECK_EQUAL(sum.derivative(i, j), T(0)); + CHECK_EQUAL(sum.derivative(i, j), T(0)); } } } @@ -189,15 +201,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(subtraction_assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(sum.derivative(i, j), -cy); + CHECK_EQUAL(sum.derivative(i, j), -cy); } else { - BOOST_CHECK_EQUAL(sum.derivative(i, j), T(0)); + CHECK_EQUAL(sum.derivative(i, j), T(0)); } } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_assignment, T, all_float_types) { +template +void multiplication_assignment() { // Try explicit bracing based on feedback. Doesn't add very much except 26 // extra lines. constexpr std::size_t m = 3; @@ -210,11 +223,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(product.derivative(i, j), cx); + CHECK_EQUAL(product.derivative(i, j), cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(product.derivative(i, j), T(1)); + CHECK_EQUAL(product.derivative(i, j), T(1)); } else { - BOOST_CHECK_EQUAL(product.derivative(i, j), T(0)); + CHECK_EQUAL(product.derivative(i, j), T(0)); } } } @@ -225,9 +238,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(product.derivative(i, j), cy); + CHECK_EQUAL(product.derivative(i, j), cy); } else { - BOOST_CHECK_EQUAL(product.derivative(i, j), T(0)); + CHECK_EQUAL(product.derivative(i, j), T(0)); } } } @@ -237,18 +250,19 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_assignment, T, all_float_types) { // std::cout << "x = " << x << std::endl; for (auto i : boost::irange(m + 1)) { if (i == 0) { - BOOST_CHECK(boost::math::isnan(static_cast(x))); // Correct + CHECK_TRUE(boost::math::isnan(static_cast(x))); // Correct // BOOST_CHECK_EQUAL(x.derivative(i) == 0.0); // Wrong. See // multiply_assign_by_root_type(). } else if (i == 1) { - BOOST_CHECK(boost::math::isinf(x.derivative(i))); + CHECK_TRUE(boost::math::isinf(x.derivative(i))); } else { - BOOST_CHECK_EQUAL(x.derivative(i), 0.0); + CHECK_EQUAL(x.derivative(i), static_cast(0.0)); } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(division_assignment, T, all_float_types) { +template +void division_assignment() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 16; @@ -256,13 +270,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(division_assignment, T, all_float_types) { // Single variable const auto x = make_fvar(cx); quotient /= x; - BOOST_CHECK_EQUAL(quotient.derivative(0, 0), 1 / cx); - BOOST_CHECK_EQUAL(quotient.derivative(1, 0), -1 / pow(cx, 2)); - BOOST_CHECK_EQUAL(quotient.derivative(2, 0), 2 / pow(cx, 3)); - BOOST_CHECK_EQUAL(quotient.derivative(3, 0), -6 / pow(cx, 4)); + CHECK_EQUAL(quotient.derivative(0, 0), 1 / cx); + CHECK_EQUAL(quotient.derivative(1, 0), static_cast(-1 / pow(cx, 2))); + CHECK_EQUAL(quotient.derivative(2, 0), static_cast(2 / pow(cx, 3))); + CHECK_EQUAL(quotient.derivative(3, 0), static_cast(-6 / pow(cx, 4))); for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(std::size_t(1), n + 1)) { - BOOST_CHECK_EQUAL(quotient.derivative(i, j), T(0)); + CHECK_EQUAL(quotient.derivative(i, j), T(0)); } } // Arithmetic constant @@ -272,15 +286,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(division_assignment, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(quotient.derivative(i, j), 1 / cy); + CHECK_EQUAL(quotient.derivative(i, j), 1 / cy); } else { - BOOST_CHECK_EQUAL(quotient.derivative(i, j), T(0)); + CHECK_EQUAL(quotient.derivative(i, j), T(0)); } } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(unary_signs, T, all_float_types) { +template +void unary_signs() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 16; @@ -291,11 +306,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(unary_signs, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), -cx); + CHECK_EQUAL(lhs.derivative(i, j), -cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), T(-1)); + CHECK_EQUAL(lhs.derivative(i, j), T(-1)); } else { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), T(0)); + CHECK_EQUAL(lhs.derivative(i, j), T(0)); } } } @@ -303,48 +318,52 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(unary_signs, T, all_float_types) { for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(n + 1)) { if (i == 0 && j == 0) { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), cx); + CHECK_EQUAL(lhs.derivative(i, j), cx); } else if (i == 1 && j == 0) { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), T(1)); + CHECK_EQUAL(lhs.derivative(i, j), T(1)); } else { - BOOST_CHECK_EQUAL(lhs.derivative(i, j), T(0)); + CHECK_EQUAL(lhs.derivative(i, j), T(0)); } } } } // TODO 3 tests for 3 operator+() definitions. -BOOST_AUTO_TEST_CASE_TEMPLATE(cast_double, T, all_float_types) { +template +void cast_double() { const T ca(13); const T i(12); constexpr std::size_t m = 3; const auto x = make_fvar(ca); - BOOST_CHECK_LT(i, x); - BOOST_CHECK_EQUAL(i * x, i * ca); + CHECK_TRUE((i) < (x)); + CHECK_TRUE((i * x) == (i * ca)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(int_double_casting, T, all_float_types) { +template +void int_double_casting() { const T ca = 3; const auto x0 = make_fvar(ca); - BOOST_CHECK_EQUAL(static_cast(x0), ca); + CHECK_EQUAL(static_cast(x0), ca); const auto x1 = make_fvar(ca); - BOOST_CHECK_EQUAL(static_cast(x1), ca); + CHECK_EQUAL(static_cast(x1), ca); const auto x2 = make_fvar(ca); - BOOST_CHECK_EQUAL(static_cast(x2), ca); + CHECK_EQUAL(static_cast(x2), ca); } -BOOST_AUTO_TEST_CASE_TEMPLATE(scalar_addition, T, all_float_types) { +template +void scalar_addition() { const T ca = 3; const T cb = 4; const auto sum0 = autodiff_fvar(ca) + autodiff_fvar(cb); - BOOST_CHECK_EQUAL(ca + cb, static_cast(sum0)); + CHECK_EQUAL(ca + cb, static_cast(sum0)); const auto sum1 = autodiff_fvar(ca) + cb; - BOOST_CHECK_EQUAL(ca + cb, static_cast(sum1)); + CHECK_EQUAL(ca + cb, static_cast(sum1)); const auto sum2 = ca + autodiff_fvar(cb); - BOOST_CHECK_EQUAL(ca + cb, static_cast(sum2)); + CHECK_EQUAL(ca + cb, static_cast(sum2)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(power8, T, all_float_types) { +template +void power8() { constexpr std::size_t n = 8u; const T ca = 3; auto x = make_fvar(ca); @@ -354,45 +373,45 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(power8, T, all_float_types) { x *= x; const T power_factorial = boost::math::factorial(n); for (auto i : boost::irange(n + 1)) { - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( static_cast(x.derivative(i)), static_cast(power_factorial / boost::math::factorial(static_cast(n - i)) * - pow(ca, n - i)), - std::numeric_limits::epsilon()); + pow(ca, n - i)), (std::numeric_limits::epsilon()) / 100); } x = make_fvar(ca); // Test operator*() x = x * x * x * x * x * x * x * x; for (auto i : boost::irange(n + 1)) { - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( static_cast(x.derivative(i)), static_cast(power_factorial / boost::math::factorial(static_cast(n - i)) * - pow(ca, n - i)), - std::numeric_limits::epsilon()); + pow(ca, n - i)), (std::numeric_limits::epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(dim1_multiplication, T, all_float_types) { +template +void dim1_multiplication() { constexpr std::size_t m = 2; constexpr std::size_t n = 3; const T cy = 4; auto y0 = make_fvar(cy); auto y = make_fvar(cy); y *= y0; - BOOST_CHECK_EQUAL(y.derivative(0), cy * cy); - BOOST_CHECK_EQUAL(y.derivative(1), 2 * cy); - BOOST_CHECK_EQUAL(y.derivative(2), T(2)); - BOOST_CHECK_EQUAL(y.derivative(3), T(0)); + CHECK_EQUAL(y.derivative(0), cy * cy); + CHECK_EQUAL(y.derivative(1), 2 * cy); + CHECK_EQUAL(y.derivative(2), T(2)); + CHECK_EQUAL(y.derivative(3), T(0)); y = y * cy; - BOOST_CHECK_EQUAL(y.derivative(0), cy * cy * cy); - BOOST_CHECK_EQUAL(y.derivative(1), 2 * cy * cy); - BOOST_CHECK_EQUAL(y.derivative(2), 2.0 * cy); - BOOST_CHECK_EQUAL(y.derivative(3), 0.0); + CHECK_EQUAL(y.derivative(0), cy * cy * cy); + CHECK_EQUAL(y.derivative(1), 2 * cy * cy); + CHECK_EQUAL(y.derivative(2), static_cast(2.0 * cy)); + CHECK_EQUAL(y.derivative(3), static_cast(0.0)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(dim1and2_multiplication, T, all_float_types) { +template +void dim1and2_multiplication() { constexpr std::size_t m = 2; constexpr std::size_t n = 3; const T cx = 3; @@ -400,52 +419,53 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(dim1and2_multiplication, T, all_float_types) { auto x = make_fvar(cx); auto y = make_fvar(cy); y *= x; - BOOST_CHECK_EQUAL(y.derivative(0, 0), cx * cy); - BOOST_CHECK_EQUAL(y.derivative(0, 1), cx); - BOOST_CHECK_EQUAL(y.derivative(1, 0), cy); - BOOST_CHECK_EQUAL(y.derivative(1, 1), T(1)); + CHECK_EQUAL(y.derivative(0, 0), cx * cy); + CHECK_EQUAL(y.derivative(0, 1), cx); + CHECK_EQUAL(y.derivative(1, 0), cy); + CHECK_EQUAL(y.derivative(1, 1), T(1)); for (auto i : boost::irange(std::size_t(1), m)) { for (auto j : boost::irange(std::size_t(1), n)) { if (i == 1 && j == 1) { - BOOST_CHECK_EQUAL(y.derivative(i, j), T(1)); + CHECK_EQUAL(y.derivative(i, j), T(1)); } else { - BOOST_CHECK_EQUAL(y.derivative(i, j), T(0)); + CHECK_EQUAL(y.derivative(i, j), T(0)); } } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(dim2_addition, T, all_float_types) { +template +void dim2_addition() { constexpr std::size_t m = 2; constexpr std::size_t n = 3; const T cx = 3; const auto x = make_fvar(cx); - BOOST_CHECK_EQUAL(x.derivative(0), cx); - BOOST_CHECK_EQUAL(x.derivative(1), T(1)); - BOOST_CHECK_EQUAL(x.derivative(2), 0.0); + CHECK_EQUAL(x.derivative(0), cx); + CHECK_EQUAL(x.derivative(1), T(1)); + CHECK_EQUAL(x.derivative(2), static_cast(0.0)); const T cy = 4; const auto y = make_fvar(cy); - BOOST_CHECK_EQUAL(static_cast(y.derivative(0)), cy); - BOOST_CHECK_EQUAL(static_cast(y.derivative(1)), - 0.0); // partial of y w.r.t. x. - - BOOST_CHECK_EQUAL(y.derivative(0, 0), cy); - BOOST_CHECK_EQUAL(y.derivative(0, 1), T(1)); - BOOST_CHECK_EQUAL(y.derivative(1, 0), 0.0); - BOOST_CHECK_EQUAL(y.derivative(1, 1), 0.0); + CHECK_EQUAL(static_cast(y.derivative(0)), cy); + CHECK_EQUAL(static_cast(y.derivative(1)), static_cast(0.0)); // partial of y w.r.t. x. + + CHECK_EQUAL(y.derivative(0, 0), cy); + CHECK_EQUAL(y.derivative(0, 1), T(1)); + CHECK_EQUAL(y.derivative(1, 0), static_cast(0.0)); + CHECK_EQUAL(y.derivative(1, 1), static_cast(0.0)); const auto z = x + y; - BOOST_CHECK_EQUAL(z.derivative(0, 0), cx + cy); - BOOST_CHECK_EQUAL(z.derivative(0, 1), T(1)); - BOOST_CHECK_EQUAL(z.derivative(1, 0), T(1)); - BOOST_CHECK_EQUAL(z.derivative(1, 1), 0.0); + CHECK_EQUAL(z.derivative(0, 0), cx + cy); + CHECK_EQUAL(z.derivative(0, 1), T(1)); + CHECK_EQUAL(z.derivative(1, 0), T(1)); + CHECK_EQUAL(z.derivative(1, 1), static_cast(0.0)); // The following 4 are unnecessarily more expensive than the previous 4. - BOOST_CHECK_EQUAL(z.derivative(0).derivative(0), cx + cy); - BOOST_CHECK_EQUAL(z.derivative(0).derivative(1), T(1)); - BOOST_CHECK_EQUAL(z.derivative(1).derivative(0), T(1)); - BOOST_CHECK_EQUAL(z.derivative(1).derivative(1), 0.0); + CHECK_EQUAL(z.derivative(0).derivative(0), cx + cy); + CHECK_EQUAL(z.derivative(0).derivative(1), T(1)); + CHECK_EQUAL(z.derivative(1).derivative(0), T(1)); + CHECK_EQUAL(z.derivative(1).derivative(1), static_cast(0.0)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(dim2_multiplication, T, all_float_types) { +template +void dim2_multiplication() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 6; @@ -453,30 +473,30 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(dim2_multiplication, T, all_float_types) { const T cy = 5; const auto y = make_fvar(cy); const auto z = x * x * y * y * y; - BOOST_CHECK_EQUAL(z.derivative(0, 0), cx * cx * cy * cy * cy); // x^2 * y^3 - BOOST_CHECK_EQUAL(z.derivative(0, 1), cx * cx * 3 * cy * cy); // x^2 * 3y^2 - BOOST_CHECK_EQUAL(z.derivative(0, 2), cx * cx * 6 * cy); // x^2 * 6y - BOOST_CHECK_EQUAL(z.derivative(0, 3), cx * cx * 6); // x^2 * 6 - BOOST_CHECK_EQUAL(z.derivative(0, 4), T(0)); // x^2 * 0 - BOOST_CHECK_EQUAL(z.derivative(1, 0), 2 * cx * cy * cy * cy); // 2x * y^3 - BOOST_CHECK_EQUAL(z.derivative(1, 1), 2 * cx * 3 * cy * cy); // 2x * 3y^2 - BOOST_CHECK_EQUAL(z.derivative(1, 2), 2 * cx * 6 * cy); // 2x * 6y - BOOST_CHECK_EQUAL(z.derivative(1, 3), 2 * cx * 6); // 2x * 6 - BOOST_CHECK_EQUAL(z.derivative(1, 4), T(0)); // 2x * 0 - BOOST_CHECK_EQUAL(z.derivative(2, 0), 2 * cy * cy * cy); // 2 * y^3 - BOOST_CHECK_EQUAL(z.derivative(2, 1), 2 * 3 * cy * cy); // 2 * 3y^2 - BOOST_CHECK_EQUAL(z.derivative(2, 2), 2 * 6 * cy); // 2 * 6y - BOOST_CHECK_EQUAL(z.derivative(2, 3), 2 * 6); // 2 * 6 - BOOST_CHECK_EQUAL(z.derivative(2, 4), T(0)); // 2 * 0 - BOOST_CHECK_EQUAL(z.derivative(3, 0), T(0)); // 0 * y^3 - BOOST_CHECK_EQUAL(z.derivative(3, 1), T(0)); // 0 * 3y^2 - BOOST_CHECK_EQUAL(z.derivative(3, 2), T(0)); // 0 * 6y - BOOST_CHECK_EQUAL(z.derivative(3, 3), T(0)); // 0 * 6 - BOOST_CHECK_EQUAL(z.derivative(3, 4), T(0)); // 0 * 0 + CHECK_EQUAL(z.derivative(0, 0), cx * cx * cy * cy * cy); // x^2 * y^3 + CHECK_EQUAL(z.derivative(0, 1), cx * cx * 3 * cy * cy); // x^2 * 3y^2 + CHECK_EQUAL(z.derivative(0, 2), cx * cx * 6 * cy); // x^2 * 6y + CHECK_EQUAL(z.derivative(0, 3), cx * cx * 6); // x^2 * 6 + CHECK_EQUAL(z.derivative(0, 4), T(0)); // x^2 * 0 + CHECK_EQUAL(z.derivative(1, 0), 2 * cx * cy * cy * cy); // 2x * y^3 + CHECK_EQUAL(z.derivative(1, 1), 2 * cx * 3 * cy * cy); // 2x * 3y^2 + CHECK_EQUAL(z.derivative(1, 2), 2 * cx * 6 * cy); // 2x * 6y + CHECK_EQUAL(z.derivative(1, 3), 2 * cx * 6); // 2x * 6 + CHECK_EQUAL(z.derivative(1, 4), T(0)); // 2x * 0 + CHECK_EQUAL(z.derivative(2, 0), 2 * cy * cy * cy); // 2 * y^3 + CHECK_EQUAL(z.derivative(2, 1), 2 * 3 * cy * cy); // 2 * 3y^2 + CHECK_EQUAL(z.derivative(2, 2), 2 * 6 * cy); // 2 * 6y + CHECK_EQUAL(z.derivative(2, 3), static_cast(2 * 6)); // 2 * 6 + CHECK_EQUAL(z.derivative(2, 4), T(0)); // 2 * 0 + CHECK_EQUAL(z.derivative(3, 0), T(0)); // 0 * y^3 + CHECK_EQUAL(z.derivative(3, 1), T(0)); // 0 * 3y^2 + CHECK_EQUAL(z.derivative(3, 2), T(0)); // 0 * 6y + CHECK_EQUAL(z.derivative(3, 3), T(0)); // 0 * 6 + CHECK_EQUAL(z.derivative(3, 4), T(0)); // 0 * 0 } -BOOST_AUTO_TEST_CASE_TEMPLATE(dim2_multiplication_and_subtraction, T, - all_float_types) { +template +void dim2_multiplication_and_subtraction() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 6; @@ -484,39 +504,41 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(dim2_multiplication_and_subtraction, T, const T cy = 5; const auto y = make_fvar(cy); const auto z = x * x - y * y; - BOOST_CHECK_EQUAL(z.derivative(0, 0), cx * cx - cy * cy); - BOOST_CHECK_EQUAL(z.derivative(0, 1), -2 * cy); - BOOST_CHECK_EQUAL(z.derivative(0, 2), T(-2)); - BOOST_CHECK_EQUAL(z.derivative(0, 3), T(0)); - BOOST_CHECK_EQUAL(z.derivative(0, 4), T(0)); - BOOST_CHECK_EQUAL(z.derivative(1, 0), 2 * cx); - BOOST_CHECK_EQUAL(z.derivative(2, 0), T(2)); + CHECK_EQUAL(z.derivative(0, 0), cx * cx - cy * cy); + CHECK_EQUAL(z.derivative(0, 1), -2 * cy); + CHECK_EQUAL(z.derivative(0, 2), T(-2)); + CHECK_EQUAL(z.derivative(0, 3), T(0)); + CHECK_EQUAL(z.derivative(0, 4), T(0)); + CHECK_EQUAL(z.derivative(1, 0), 2 * cx); + CHECK_EQUAL(z.derivative(2, 0), T(2)); for (auto i : boost::irange(std::size_t(1), m + 1)) { for (auto j : boost::irange(std::size_t(1), n + 1)) { - BOOST_CHECK_EQUAL(z.derivative(i, j), T(0)); + CHECK_EQUAL(z.derivative(i, j), T(0)); } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(inverse, T, all_float_types) { +template +void inverse() { constexpr std::size_t m = 3; const T cx = 4; const auto x = make_fvar(cx); const auto xinv = x.inverse(); - BOOST_CHECK_EQUAL(xinv.derivative(0), 1 / cx); - BOOST_CHECK_EQUAL(xinv.derivative(1), -1 / pow(cx, 2)); - BOOST_CHECK_EQUAL(xinv.derivative(2), 2 / pow(cx, 3)); - BOOST_CHECK_EQUAL(xinv.derivative(3), -6 / pow(cx, 4)); + CHECK_EQUAL(xinv.derivative(0), 1 / cx); + CHECK_EQUAL(xinv.derivative(1), static_cast(-1 / pow(cx, 2))); + CHECK_EQUAL(xinv.derivative(2), static_cast(2 / pow(cx, 3))); + CHECK_EQUAL(xinv.derivative(3), static_cast(-6 / pow(cx, 4))); const auto zero = make_fvar(0); const auto inf = zero.inverse(); for (auto i : boost::irange(m + 1)) { - BOOST_CHECK_EQUAL(inf.derivative(i), + CHECK_EQUAL(inf.derivative(i), (i % 2 == 1 ? -1 : 1) * std::numeric_limits::infinity()); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(division, T, all_float_types) { +template +void division() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 16; @@ -524,125 +546,130 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(division, T, all_float_types) { const T cy = 4; auto y = make_fvar(cy); auto z = x * x / (y * y); - BOOST_CHECK_EQUAL(z.derivative(0, 0), cx * cx / (cy * cy)); // x^2 * y^-2 - BOOST_CHECK_EQUAL(z.derivative(0, 1), cx * cx * (-2) * pow(cy, -3)); - BOOST_CHECK_EQUAL(z.derivative(0, 2), cx * cx * (6) * pow(cy, -4)); - BOOST_CHECK_EQUAL(z.derivative(0, 3), cx * cx * (-24) * pow(cy, -5)); - BOOST_CHECK_EQUAL(z.derivative(0, 4), cx * cx * (120) * pow(cy, -6)); - BOOST_CHECK_EQUAL(z.derivative(1, 0), 2 * cx / (cy * cy)); - BOOST_CHECK_EQUAL(z.derivative(1, 1), 2 * cx * (-2) * pow(cy, -3)); - BOOST_CHECK_EQUAL(z.derivative(1, 2), 2 * cx * (6) * pow(cy, -4)); - BOOST_CHECK_EQUAL(z.derivative(1, 3), 2 * cx * (-24) * pow(cy, -5)); - BOOST_CHECK_EQUAL(z.derivative(1, 4), 2 * cx * (120) * pow(cy, -6)); - BOOST_CHECK_EQUAL(z.derivative(2, 0), 2 / (cy * cy)); - BOOST_CHECK_EQUAL(z.derivative(2, 1), 2 * (-2) * pow(cy, -3)); - BOOST_CHECK_EQUAL(z.derivative(2, 2), 2 * (6) * pow(cy, -4)); - BOOST_CHECK_EQUAL(z.derivative(2, 3), 2 * (-24) * pow(cy, -5)); - BOOST_CHECK_EQUAL(z.derivative(2, 4), 2 * (120) * pow(cy, -6)); + CHECK_EQUAL(z.derivative(0, 0), cx * cx / (cy * cy)); // x^2 * y^-2 + CHECK_EQUAL(z.derivative(0, 1), static_cast(cx * cx * (-2) * pow(cy, -3))); + CHECK_EQUAL(z.derivative(0, 2), static_cast(cx * cx * (6) * pow(cy, -4))); + CHECK_EQUAL(z.derivative(0, 3), static_cast(cx * cx * (-24) * pow(cy, -5))); + CHECK_EQUAL(z.derivative(0, 4), static_cast(cx * cx * (120) * pow(cy, -6))); + CHECK_EQUAL(z.derivative(1, 0), 2 * cx / (cy * cy)); + CHECK_EQUAL(z.derivative(1, 1), static_cast(2 * cx * (-2) * pow(cy, -3))); + CHECK_EQUAL(z.derivative(1, 2), static_cast(2 * cx * (6) * pow(cy, -4))); + CHECK_EQUAL(z.derivative(1, 3), static_cast(2 * cx * (-24) * pow(cy, -5))); + CHECK_EQUAL(z.derivative(1, 4), static_cast(2 * cx * (120) * pow(cy, -6))); + CHECK_EQUAL(z.derivative(2, 0), 2 / (cy * cy)); + CHECK_EQUAL(z.derivative(2, 1), static_cast(2 * (-2) * pow(cy, -3))); + CHECK_EQUAL(z.derivative(2, 2), static_cast(2 * (6) * pow(cy, -4))); + CHECK_EQUAL(z.derivative(2, 3), static_cast(2 * (-24) * pow(cy, -5))); + CHECK_EQUAL(z.derivative(2, 4), static_cast(2 * (120) * pow(cy, -6))); for (auto j : boost::irange(n + 1)) { - BOOST_CHECK_EQUAL(z.derivative(3, j), 0.0); + CHECK_EQUAL(z.derivative(3, j), static_cast(0.0)); } auto x1 = make_fvar(cx); auto z1 = x1 / cy; - BOOST_CHECK_EQUAL(z1.derivative(0), cx / cy); - BOOST_CHECK_EQUAL(z1.derivative(1), 1 / cy); - BOOST_CHECK_EQUAL(z1.derivative(2), 0.0); - BOOST_CHECK_EQUAL(z1.derivative(3), 0.0); + CHECK_EQUAL(z1.derivative(0), cx / cy); + CHECK_EQUAL(z1.derivative(1), 1 / cy); + CHECK_EQUAL(z1.derivative(2), static_cast(0.0)); + CHECK_EQUAL(z1.derivative(3), static_cast(0.0)); auto y2 = make_fvar(cy); auto z2 = cx / y2; - BOOST_CHECK_EQUAL(z2.derivative(0, 0), cx / cy); - BOOST_CHECK_EQUAL(z2.derivative(0, 1), -cx / pow(cy, 2)); - BOOST_CHECK_EQUAL(z2.derivative(0, 2), 2 * cx / pow(cy, 3)); - BOOST_CHECK_EQUAL(z2.derivative(0, 3), -6 * cx / pow(cy, 4)); - BOOST_CHECK_EQUAL(z2.derivative(0, 4), 24 * cx / pow(cy, 5)); + CHECK_EQUAL(z2.derivative(0, 0), cx / cy); + CHECK_EQUAL(z2.derivative(0, 1), static_cast(-cx / pow(cy, 2))); + CHECK_EQUAL(z2.derivative(0, 2), static_cast(2 * cx / pow(cy, 3))); + CHECK_EQUAL(z2.derivative(0, 3), static_cast(-6 * cx / pow(cy, 4))); + CHECK_EQUAL(z2.derivative(0, 4), static_cast(24 * cx / pow(cy, 5))); for (auto i : boost::irange(std::size_t(1), m + 1)) { for (auto j : boost::irange(n + 1)) { - BOOST_CHECK_EQUAL(z2.derivative(i, j), 0.0); + CHECK_EQUAL(z2.derivative(i, j), static_cast(0.0)); } } const auto z3 = y / x; - BOOST_CHECK_EQUAL(z3.derivative(0, 0), cy / cx); - BOOST_CHECK_EQUAL(z3.derivative(0, 1), 1 / cx); - BOOST_CHECK_EQUAL(z3.derivative(1, 0), -cy / pow(cx, 2)); - BOOST_CHECK_EQUAL(z3.derivative(1, 1), -1 / pow(cx, 2)); - BOOST_CHECK_EQUAL(z3.derivative(2, 0), 2 * cy / pow(cx, 3)); - BOOST_CHECK_EQUAL(z3.derivative(2, 1), 2 / pow(cx, 3)); - BOOST_CHECK_EQUAL(z3.derivative(3, 0), -6 * cy / pow(cx, 4)); - BOOST_CHECK_EQUAL(z3.derivative(3, 1), -6 / pow(cx, 4)); + CHECK_EQUAL(z3.derivative(0, 0), cy / cx); + CHECK_EQUAL(z3.derivative(0, 1), 1 / cx); + CHECK_EQUAL(z3.derivative(1, 0), static_cast(-cy / pow(cx, 2))); + CHECK_EQUAL(z3.derivative(1, 1), static_cast(-1 / pow(cx, 2))); + CHECK_EQUAL(z3.derivative(2, 0), static_cast(2 * cy / pow(cx, 3))); + CHECK_EQUAL(z3.derivative(2, 1), static_cast(2 / pow(cx, 3))); + CHECK_EQUAL(z3.derivative(3, 0), static_cast(-6 * cy / pow(cx, 4))); + CHECK_EQUAL(z3.derivative(3, 1), static_cast(-6 / pow(cx, 4))); for (auto i : boost::irange(m + 1)) { for (auto j : boost::irange(std::size_t(2), n + 1)) { - BOOST_CHECK_EQUAL(z3.derivative(i, j), 0.0); + CHECK_EQUAL(z3.derivative(i, j), static_cast(0.0)); } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(equality, T, all_float_types) { +template +void equality() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 10; const T cy = 10; const auto x = make_fvar(cx); const auto y = make_fvar(cy); - BOOST_CHECK_EQUAL(x, y); - BOOST_CHECK_EQUAL(x, cy); - BOOST_CHECK_EQUAL(cx, y); - BOOST_CHECK_EQUAL(cy, x); - BOOST_CHECK_EQUAL(y, cx); + CHECK_TRUE((x) == (y)); + CHECK_TRUE((x) == (cy)); + CHECK_TRUE((cx) == (y)); + CHECK_TRUE((cy) == (x)); + CHECK_TRUE((y) == (cx)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(inequality, T, all_float_types) { +template +void inequality() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 10; const T cy = 11; const auto x = make_fvar(cx); const auto y = make_fvar(cy); - BOOST_CHECK_NE(x, y); - BOOST_CHECK_NE(x, cy); - BOOST_CHECK_NE(cx, y); - BOOST_CHECK_NE(cy, x); - BOOST_CHECK_NE(y, cx); + CHECK_TRUE((x) != (y)); + CHECK_TRUE((x) != (cy)); + CHECK_TRUE((cx) != (y)); + CHECK_TRUE((cy) != (x)); + CHECK_TRUE((y) != (cx)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(less_than_or_equal_to, T, all_float_types) { +template +void less_than_or_equal_to() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 10; const T cy = 11; const auto x = make_fvar(cx); const auto y = make_fvar(cy); - BOOST_CHECK_LE(x, y); - BOOST_CHECK_LE(x, y - 1); - BOOST_CHECK_LT(x, y); - BOOST_CHECK_LE(x, cy); - BOOST_CHECK_LE(x, cy - 1); - BOOST_CHECK_LT(x, cy); - BOOST_CHECK_LE(cx, y); - BOOST_CHECK_LE(cx, y - 1); - BOOST_CHECK_LT(cx, y); + CHECK_TRUE((x) <= (y)); + CHECK_TRUE((x) <= (y - 1)); + CHECK_TRUE((x) < (y)); + CHECK_TRUE((x) <= (cy)); + CHECK_TRUE((x) <= (cy - 1)); + CHECK_TRUE((x) < (cy)); + CHECK_TRUE((cx) <= (y)); + CHECK_TRUE((cx) <= (y - 1)); + CHECK_TRUE((cx) < (y)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(greater_than_or_equal_to, T, all_float_types) { +template +void greater_than_or_equal_to() { constexpr std::size_t m = 3; constexpr std::size_t n = 4; const T cx = 11; const T cy = 10; const auto x = make_fvar(cx); const auto y = make_fvar(cy); - BOOST_CHECK_GE(x, y); - BOOST_CHECK_GE(x, y + 1); - BOOST_CHECK_GT(x, y); - BOOST_CHECK_GE(x, cy); - BOOST_CHECK_GE(x, cy + 1); - BOOST_CHECK_GT(x, cy); - BOOST_CHECK_GE(cx, y); - BOOST_CHECK_GE(cx, y + 1); - BOOST_CHECK_GT(cx, y); + CHECK_TRUE((x) >= (y)); + CHECK_TRUE((x) >= (y + 1)); + CHECK_TRUE((x) > (y)); + CHECK_TRUE((x) >= (cy)); + CHECK_TRUE((x) >= (cy + 1)); + CHECK_TRUE((x) > (cy)); + CHECK_TRUE((cx) >= (y)); + CHECK_TRUE((cx) >= (y + 1)); + CHECK_TRUE((cx) > (y)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(fabs_test, T, all_float_types) { +template +void fabs_test() { using bmp::fabs; using detail::fabs; using std::fabs; @@ -650,29 +677,30 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fabs_test, T, all_float_types) { const T cx = 11; const auto x = make_fvar(cx); auto a = fabs(x); - BOOST_CHECK_EQUAL(a.derivative(0), fabs(cx)); - BOOST_CHECK_EQUAL(a.derivative(1), T(1)); - BOOST_CHECK_EQUAL(a.derivative(2), T(0)); - BOOST_CHECK_EQUAL(a.derivative(3), T(0)); + CHECK_EQUAL(a.derivative(0), fabs(cx)); + CHECK_EQUAL(a.derivative(1), T(1)); + CHECK_EQUAL(a.derivative(2), T(0)); + CHECK_EQUAL(a.derivative(3), T(0)); a = fabs(-x); - BOOST_CHECK_EQUAL(a.derivative(0), fabs(cx)); - BOOST_CHECK_EQUAL(a.derivative(1), T(1)); // fabs(-x) = fabs(x) - BOOST_CHECK_EQUAL(a.derivative(2), T(0)); - BOOST_CHECK_EQUAL(a.derivative(3), T(0)); + CHECK_EQUAL(a.derivative(0), fabs(cx)); + CHECK_EQUAL(a.derivative(1), T(1)); // fabs(-x) = fabs(x) + CHECK_EQUAL(a.derivative(2), T(0)); + CHECK_EQUAL(a.derivative(3), T(0)); const auto xneg = make_fvar(-cx); a = fabs(xneg); - BOOST_CHECK_EQUAL(a.derivative(0), fabs(cx)); - BOOST_CHECK_EQUAL(a.derivative(1), -T(1)); - BOOST_CHECK_EQUAL(a.derivative(2), T(0)); - BOOST_CHECK_EQUAL(a.derivative(3), T(0)); + CHECK_EQUAL(a.derivative(0), fabs(cx)); + CHECK_EQUAL(a.derivative(1), -T(1)); + CHECK_EQUAL(a.derivative(2), T(0)); + CHECK_EQUAL(a.derivative(3), T(0)); const auto zero = make_fvar(0); a = fabs(zero); for (auto i : boost::irange(m + 1)) { - BOOST_CHECK_EQUAL(a.derivative(i), T(0)); + CHECK_EQUAL(a.derivative(i), T(0)); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ceil_and_floor, T, all_float_types) { +template +void ceil_and_floor() { using bmp::ceil; using bmp::floor; using std::ceil; @@ -683,13 +711,42 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ceil_and_floor, T, all_float_types) { const auto x = make_fvar(test); auto c = ceil(x); auto f = floor(x); - BOOST_CHECK_EQUAL(c.derivative(0), ceil(test)); - BOOST_CHECK_EQUAL(f.derivative(0), floor(test)); + CHECK_EQUAL(c.derivative(0), ceil(test)); + CHECK_EQUAL(f.derivative(0), floor(test)); for (auto i : boost::irange(std::size_t(1), m + 1)) { - BOOST_CHECK_EQUAL(c.derivative(i), T(0)); - BOOST_CHECK_EQUAL(f.derivative(i), T(0)); + CHECK_EQUAL(c.derivative(i), T(0)); + CHECK_EQUAL(f.derivative(i), T(0)); } } } -BOOST_AUTO_TEST_SUITE_END() +int main() +{ + boost::mp11::mp_for_each>([](auto t) { constructors(); }); + boost::mp11::mp_for_each>([](auto t) { implicit_constructors(); }); + boost::mp11::mp_for_each>([](auto t) { assignment(); }); + boost::mp11::mp_for_each>([](auto t) { ostream(); }); + boost::mp11::mp_for_each>([](auto t) { addition_assignment(); }); + boost::mp11::mp_for_each>([](auto t) { subtraction_assignment(); }); + boost::mp11::mp_for_each>([](auto t) { multiplication_assignment(); }); + boost::mp11::mp_for_each>([](auto t) { division_assignment(); }); + boost::mp11::mp_for_each>([](auto t) { unary_signs(); }); + boost::mp11::mp_for_each>([](auto t) { cast_double(); }); + boost::mp11::mp_for_each>([](auto t) { int_double_casting(); }); + boost::mp11::mp_for_each>([](auto t) { scalar_addition(); }); + boost::mp11::mp_for_each>([](auto t) { power8(); }); + boost::mp11::mp_for_each>([](auto t) { dim1_multiplication(); }); + boost::mp11::mp_for_each>([](auto t) { dim1and2_multiplication(); }); + boost::mp11::mp_for_each>([](auto t) { dim2_addition(); }); + boost::mp11::mp_for_each>([](auto t) { dim2_multiplication(); }); + boost::mp11::mp_for_each>([](auto t) { dim2_multiplication_and_subtraction(); }); + boost::mp11::mp_for_each>([](auto t) { inverse(); }); + boost::mp11::mp_for_each>([](auto t) { division(); }); + boost::mp11::mp_for_each>([](auto t) { equality(); }); + boost::mp11::mp_for_each>([](auto t) { inequality(); }); + boost::mp11::mp_for_each>([](auto t) { less_than_or_equal_to(); }); + boost::mp11::mp_for_each>([](auto t) { greater_than_or_equal_to(); }); + boost::mp11::mp_for_each>([](auto t) { fabs_test(); }); + boost::mp11::mp_for_each>([](auto t) { ceil_and_floor(); }); + return boost::math::test::report_errors(); +} diff --git a/test/test_autodiff_2.cpp b/test/test_autodiff_2.cpp index 7315e7dc1b..0c4de2d26a 100644 --- a/test/test_autodiff_2.cpp +++ b/test/test_autodiff_2.cpp @@ -5,9 +5,9 @@ #include "test_autodiff.hpp" -BOOST_AUTO_TEST_SUITE(test_autodiff_2) -BOOST_AUTO_TEST_CASE_TEMPLATE(one_over_one_plus_x_squared, T, all_float_types) { +template +void one_over_one_plus_x_squared() { constexpr std::size_t m = 4; const T cx(1); auto f = make_fvar(cx); @@ -15,14 +15,15 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(one_over_one_plus_x_squared, T, all_float_types) { f *= f; f += T(1); f = f.inverse(); - BOOST_CHECK_EQUAL(f.derivative(0u), T(0.5)); - BOOST_CHECK_EQUAL(f.derivative(1u), T(-0.5)); - BOOST_CHECK_EQUAL(f.derivative(2u), T(0.5)); - BOOST_CHECK_EQUAL(f.derivative(3u), 0); - BOOST_CHECK_EQUAL(f.derivative(4u), -3); + CHECK_EQUAL(f.derivative(0u), T(0.5)); + CHECK_EQUAL(f.derivative(1u), T(-0.5)); + CHECK_EQUAL(f.derivative(2u), T(0.5)); + CHECK_EQUAL(f.derivative(3u), static_cast(0)); + CHECK_EQUAL(f.derivative(4u), static_cast(-3)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(exp_test, T, all_float_types) { +template +void exp_test() { using std::exp; constexpr std::size_t m = 4; const T cx = 2; @@ -32,12 +33,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(exp_test, T, all_float_types) { // std::cout.precision(100); // std::cout << "y.derivative("< +void tan_test() { BOOST_MATH_STD_USING const T eps = 800 * boost::math::tools::epsilon(); // percent const T cx = boost::math::constants::third_pi(); @@ -147,57 +156,77 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(tan_test, T, bin_float_types) { constexpr unsigned m = 5; const auto x = make_fvar(cx); auto y = tan(x); - BOOST_CHECK_CLOSE(y.derivative(0u), root_three, eps); - BOOST_CHECK_CLOSE(y.derivative(1u), T(4), eps); - BOOST_CHECK_CLOSE(y.derivative(2u), T(8) * root_three, eps); - BOOST_CHECK_CLOSE(y.derivative(3u), T(80), eps); - BOOST_CHECK_CLOSE(y.derivative(4u), T(352) * root_three, eps); - BOOST_CHECK_CLOSE(y.derivative(5u), T(5824), eps); + CHECK_RELATIVE_ERROR(y.derivative(0u), root_three, (eps) / 100); + CHECK_RELATIVE_ERROR(y.derivative(1u), T(4), (eps) / 100); + CHECK_RELATIVE_ERROR(y.derivative(2u), T(8) * root_three, (eps) / 100); + CHECK_RELATIVE_ERROR(y.derivative(3u), T(80), (eps) / 100); + CHECK_RELATIVE_ERROR(y.derivative(4u), T(352) * root_three, (eps) / 100); + CHECK_RELATIVE_ERROR(y.derivative(5u), T(5824), (eps) / 100); } -BOOST_AUTO_TEST_CASE_TEMPLATE(fmod_test, T, bin_float_types) { +template +void fmod_test() { BOOST_MATH_STD_USING constexpr unsigned m = 3; const T cx = T(3.25); const T cy = T(0.5); auto x = make_fvar(cx); auto y = fmod(x, autodiff_fvar(cy)); - BOOST_CHECK_EQUAL(y.derivative(0u), T(0.25)); - BOOST_CHECK_EQUAL(y.derivative(1u), T(1)); - BOOST_CHECK_EQUAL(y.derivative(2u), T(0)); - BOOST_CHECK_EQUAL(y.derivative(3u), T(0)); + CHECK_EQUAL(y.derivative(0u), T(0.25)); + CHECK_EQUAL(y.derivative(1u), T(1)); + CHECK_EQUAL(y.derivative(2u), T(0)); + CHECK_EQUAL(y.derivative(3u), T(0)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(round_and_trunc, T, all_float_types) { +template +void fma_test() { + BOOST_MATH_STD_USING + constexpr unsigned m = 3; + const T cx = T(3.25); + auto x = make_fvar(cx); + auto y = fma(x, x, autodiff_fvar(T(0.5))); + CHECK_EQUAL(y.derivative(0u), T(11.0625)); + CHECK_EQUAL(y.derivative(1u), T(6.5)); + CHECK_EQUAL(y.derivative(2u), T(2)); + CHECK_EQUAL(y.derivative(3u), T(0)); + // The value is rounded once: (1 + 2^-12)^2 - (1 + 2^-11) is exactly 2^-24. + auto z = make_fvar(1 + ldexp(T(1), -12)); + CHECK_EQUAL(fma(z, z, autodiff_fvar(-(1 + ldexp(T(1), -11)))).derivative(0u), ldexp(T(1), -24)); +} + +template +void round_and_trunc() { BOOST_MATH_STD_USING constexpr unsigned m = 3; const T cx = T(3.25); auto x = make_fvar(cx); auto y = round(x); - BOOST_CHECK_EQUAL(y.derivative(0u), round(cx)); - BOOST_CHECK_EQUAL(y.derivative(1u), T(0)); - BOOST_CHECK_EQUAL(y.derivative(2u), T(0)); - BOOST_CHECK_EQUAL(y.derivative(3u), T(0)); + CHECK_EQUAL(y.derivative(0u), round(cx)); + CHECK_EQUAL(y.derivative(1u), T(0)); + CHECK_EQUAL(y.derivative(2u), T(0)); + CHECK_EQUAL(y.derivative(3u), T(0)); y = trunc(x); - BOOST_CHECK_EQUAL(y.derivative(0u), trunc(cx)); - BOOST_CHECK_EQUAL(y.derivative(1u), T(0)); - BOOST_CHECK_EQUAL(y.derivative(2u), T(0)); - BOOST_CHECK_EQUAL(y.derivative(3u), T(0)); + CHECK_EQUAL(y.derivative(0u), trunc(cx)); + CHECK_EQUAL(y.derivative(1u), T(0)); + CHECK_EQUAL(y.derivative(2u), T(0)); + CHECK_EQUAL(y.derivative(3u), T(0)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(iround_and_itrunc, T, all_float_types) { +template +void iround_and_itrunc() { BOOST_MATH_STD_USING using namespace boost::math; constexpr unsigned m = 3; const T cx = T(3.25); auto x = make_fvar(cx); int y = iround(x); - BOOST_CHECK_EQUAL(y, iround(cx)); + CHECK_EQUAL(y, iround(cx)); y = itrunc(x); - BOOST_CHECK_EQUAL(y, itrunc(cx)); + CHECK_EQUAL(y, itrunc(cx)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w0_test, T, all_float_types) { +template +void lambert_w0_test() { const T eps = 1000 * boost::math::tools::epsilon(); // percent constexpr unsigned m = 10; const T cx = 3; @@ -218,7 +247,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w0_test, T, all_float_types) { auto y = lambert_w0(x); for (auto i : boost::irange(m + 1)) { const T answer = answers[i]; - BOOST_CHECK_CLOSE(y.derivative(i), answer, eps); + CHECK_RELATIVE_ERROR(y.derivative(i), answer, (eps) / 100); } // const T cx0 = -1 / boost::math::constants::e(); // auto edge = lambert_w0(make_fvar(cx0)); @@ -229,7 +258,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w0_test, T, all_float_types) { // depth(1)(-1,3.68935e+19,-9.23687e+57,4.62519e+96,-2.89497e+135,2.02945e+174,-1.52431e+213,1.19943e+252,-9.75959e+290,8.14489e+329,-6.93329e+368) } -BOOST_AUTO_TEST_CASE_TEMPLATE(digamma_test, T, all_float_types) { +template +void digamma_test() { const T eps = 1000 * boost::math::tools::epsilon(); // percent constexpr unsigned m = 10; const T cx = 3; @@ -250,11 +280,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(digamma_test, T, all_float_types) { auto y = digamma(x); for (auto i : boost::irange(m + 1)) { const T answer = answers[i]; - BOOST_CHECK_CLOSE(y.derivative(i), answer, eps); + CHECK_RELATIVE_ERROR(y.derivative(i), answer, (eps) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(lgamma_test, T, all_float_types) { +template +void lgamma_test() { const T eps = 1000 * boost::math::tools::epsilon(); // percent constexpr unsigned m = 10; const T cx = 3; @@ -275,11 +306,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lgamma_test, T, all_float_types) { auto y = lgamma(x); for (auto i : boost::irange(m + 1)) { const T answer = answers[i]; - BOOST_CHECK_CLOSE(y.derivative(i), answer, eps); + CHECK_RELATIVE_ERROR(y.derivative(i), answer, (eps) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(tgamma_test, T, all_float_types) { +template +void tgamma_test() { const T eps = 1000 * boost::math::tools::epsilon(); // percent constexpr unsigned m = 10; const T cx = 3; @@ -300,11 +332,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(tgamma_test, T, all_float_types) { auto y = tgamma(x); for (auto i : boost::irange(m + 1)) { const T answer = answers[i]; - BOOST_CHECK_CLOSE(y.derivative(i), answer, eps); + CHECK_RELATIVE_ERROR(y.derivative(i), answer, (eps) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(tgamma2_test, T, all_float_types) { +template +void tgamma2_test() { //const T eps = 5000 * boost::math::tools::epsilon(); // ok for non-multiprecision const T eps = 500000 * boost::math::tools::epsilon(); // percent constexpr unsigned m = 10; @@ -326,8 +359,29 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(tgamma2_test, T, all_float_types) { auto y = tgamma(x); for (auto i : boost::irange(m + 1)) { const T answer = answers[i]; - BOOST_CHECK_CLOSE(y.derivative(i), answer, eps); + CHECK_RELATIVE_ERROR(y.derivative(i), answer, (eps) / 100); } } -BOOST_AUTO_TEST_SUITE_END() +int main() +{ + boost::mp11::mp_for_each>([](auto t) { atanh_test(); }); + boost::mp11::mp_for_each>([](auto t) { atan_test(); }); + boost::mp11::mp_for_each>([](auto t) { erf_test(); }); + boost::mp11::mp_for_each>([](auto t) { sinc_test(); }); + boost::mp11::mp_for_each>([](auto t) { sinh_and_cosh(); }); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + boost::mp11::mp_for_each>([](auto t) { tanh_test(); }); +#endif + boost::mp11::mp_for_each>([](auto t) { tan_test(); }); + boost::mp11::mp_for_each>([](auto t) { fmod_test(); }); + boost::mp11::mp_for_each>([](auto t) { fma_test(); }); + boost::mp11::mp_for_each>([](auto t) { round_and_trunc(); }); + boost::mp11::mp_for_each>([](auto t) { iround_and_itrunc(); }); + boost::mp11::mp_for_each>([](auto t) { lambert_w0_test(); }); + boost::mp11::mp_for_each>([](auto t) { digamma_test(); }); + boost::mp11::mp_for_each>([](auto t) { lgamma_test(); }); + boost::mp11::mp_for_each>([](auto t) { tgamma_test(); }); + boost::mp11::mp_for_each>([](auto t) { tgamma2_test(); }); + return boost::math::test::report_errors(); +} diff --git a/test/test_autodiff_4.cpp b/test/test_autodiff_4.cpp index a752be7dc4..2018d7cb0d 100644 --- a/test/test_autodiff_4.cpp +++ b/test/test_autodiff_4.cpp @@ -6,10 +6,9 @@ #include "test_autodiff.hpp" #include -BOOST_AUTO_TEST_SUITE(test_autodiff_4) -BOOST_AUTO_TEST_CASE_TEMPLATE(lround_llround_lltrunc_truncl, T, - all_float_types) { +template +void lround_llround_lltrunc_truncl() { using boost::math::llround; using boost::math::lltrunc; using boost::math::lround; @@ -26,20 +25,21 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lround_llround_lltrunc_truncl, T, const auto &cx = static_cast(3.25); auto x = make_fvar(cx); auto yl = lround(x); - BOOST_CHECK_EQUAL(yl, lround(cx)); + CHECK_EQUAL(yl, lround(cx)); auto yll = llround(x); - BOOST_CHECK_EQUAL(yll, llround(cx)); - BOOST_CHECK_EQUAL(lltrunc(cx), lltrunc(x)); + CHECK_EQUAL(yll, llround(cx)); + CHECK_EQUAL(lltrunc(cx), lltrunc(x)); #ifndef BOOST_NO_CXX17_IF_CONSTEXPR if constexpr (!bmp::is_number::value && !bmp::is_number_expression::value) { - BOOST_CHECK_EQUAL(truncl(x), truncl(cx)); + CHECK_EQUAL(truncl(x), truncl(cx)); } #endif } -BOOST_AUTO_TEST_CASE_TEMPLATE(equality, T, all_float_types) { +template +void equality() { BOOST_MATH_STD_USING using boost::math::epsilon_difference; using boost::math::fpclassify; @@ -51,12 +51,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(equality, T, all_float_types) { { auto x = make_fvar(T(0)); auto y = T(-0.0); - BOOST_CHECK_EQUAL(x.derivative(0u), y); + CHECK_EQUAL(x.derivative(0u), y); } } #if defined(BOOST_AUTODIFF_TESTING_INCLUDE_MULTIPRECISION) -BOOST_AUTO_TEST_CASE_TEMPLATE(multiprecision, T, multiprecision_float_types) { +template +void multiprecision() { using boost::multiprecision::fabs; using detail::fabs; using std::fabs; @@ -78,11 +79,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(multiprecision, T, multiprecision_float_types) { // for cpp_dec_float const T relative_error = static_cast(fabs(v.derivative(Nw, Nx, Ny, Nz) / answer - 1)); - BOOST_CHECK_LT(relative_error, eps); + CHECK_TRUE((relative_error) < (eps)); } #endif -BOOST_AUTO_TEST_CASE_TEMPLATE(acosh_hpp, T, all_float_types) { +template +void acosh_hpp() { using boost::math::acosh; using test_constants = test_constants_t; static constexpr auto m = test_constants::order; @@ -93,12 +95,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(acosh_hpp, T, all_float_types) { auto x = x_sampler.next(); auto autodiff_v = acosh(make_fvar(x)); auto anchor_v = acosh(x); - BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v, - 1e3 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (1e3 * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(asinh_hpp, T, all_float_types) { +template +void asinh_hpp() { using boost::math::asinh; using test_constants = test_constants_t; static constexpr auto m = test_constants::order; @@ -110,12 +112,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(asinh_hpp, T, all_float_types) { auto autodiff_v = asinh(make_fvar(x)); auto anchor_v = asinh(x); - BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v, - 1e3 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (1e3 * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(atanh_hpp, T, all_float_types) { +template +void atanh_hpp() { using boost::math::nextafter; using std::nextafter; @@ -130,12 +132,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(atanh_hpp, T, all_float_types) { auto autodiff_v = atanh(make_fvar(x)); auto anchor_v = atanh(x); - BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v, - 1e3 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (1e3 * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(atan_hpp, T, all_float_types) { +template +void atan_hpp() { using boost::math::float_prior; using boost::math::fpclassify; using boost::math::signbit; @@ -161,12 +163,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(atan_hpp, T, all_float_types) { auto autodiff_v = atan(make_fvar(x)); auto anchor_v = atan(x); - BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v, - T(1e3) * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (T(1e3) * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(bernoulli_hpp, T, all_float_types) { +template +void bernoulli_hpp() { using boost::multiprecision::min; using std::min; @@ -177,17 +179,28 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(bernoulli_hpp, T, all_float_types) { { auto autodiff_v = boost::math::bernoulli_b2n>(i); auto anchor_v = boost::math::bernoulli_b2n(i); - BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v, - 50 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (50 * test_constants::pct_epsilon()) / 100); } { auto i_ = (min)(19, i); auto autodiff_v = boost::math::tangent_t2n>(i_); auto anchor_v = boost::math::tangent_t2n(i_); - BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v, - 50 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (50 * test_constants::pct_epsilon()) / 100); } } } -BOOST_AUTO_TEST_SUITE_END() +int main() +{ + boost::mp11::mp_for_each>([](auto t) { lround_llround_lltrunc_truncl(); }); + boost::mp11::mp_for_each>([](auto t) { equality(); }); +#if defined(BOOST_AUTODIFF_TESTING_INCLUDE_MULTIPRECISION) + boost::mp11::mp_for_each>([](auto t) { multiprecision(); }); +#endif + boost::mp11::mp_for_each>([](auto t) { acosh_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { asinh_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { atanh_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { atan_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { bernoulli_hpp(); }); + return boost::math::test::report_errors(); +} diff --git a/test/test_autodiff_5.cpp b/test/test_autodiff_5.cpp index 966568cc5a..4f6e43f528 100644 --- a/test/test_autodiff_5.cpp +++ b/test/test_autodiff_5.cpp @@ -6,9 +6,9 @@ #include "test_autodiff.hpp" #include -BOOST_AUTO_TEST_SUITE(test_autodiff_5) -BOOST_AUTO_TEST_CASE_TEMPLATE(binomial_hpp, T, all_float_types) { +template +void binomial_hpp() { using boost::multiprecision::min; using std::fabs; using std::min; @@ -30,24 +30,26 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(binomial_hpp, T, all_float_types) { ? make_fvar(boost::math::binomial_coefficient(n, r)) : boost::math::binomial_coefficient(n, r); auto anchor_v = boost::math::binomial_coefficient(n, r); - BOOST_CHECK_EQUAL(autodiff_v.derivative(0u), anchor_v); + CHECK_EQUAL(autodiff_v.derivative(0u), anchor_v); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(cbrt_hpp, T, all_float_types) { +template +void cbrt_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{-2000, 2000}; for (auto i : boost::irange(test_constants::n_samples)) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK_CLOSE(boost::math::cbrt(make_fvar(x)).derivative(0u), - boost::math::cbrt(x), 50 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(boost::math::cbrt(make_fvar(x)).derivative(0u), + boost::math::cbrt(x), (50 * test_constants::pct_epsilon()) / 100); } } #if !defined(__APPLE__) -BOOST_AUTO_TEST_CASE_TEMPLATE(chebyshev_hpp, T, all_float_types) { +template +void chebyshev_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; { @@ -57,32 +59,31 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(chebyshev_hpp, T, all_float_types) { std::ignore = i; auto n = n_sampler.next(); auto x = x_sampler.next(); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::chebyshev_t(n, make_fvar(x)).derivative(0u), - boost::math::chebyshev_t(n, x), 40 * test_constants::pct_epsilon()); + boost::math::chebyshev_t(n, x), (40 * test_constants::pct_epsilon()) / 100); // Lower accuracy with clang/apple: - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::chebyshev_u(n, make_fvar(x)).derivative(0u), - boost::math::chebyshev_u(n, x), 80 * test_constants::pct_epsilon()); + boost::math::chebyshev_u(n, x), (80 * test_constants::pct_epsilon()) / 100); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::chebyshev_t_prime(n, make_fvar(x)).derivative(0u), - boost::math::chebyshev_t_prime(n, x), - 40 * test_constants::pct_epsilon()); + boost::math::chebyshev_t_prime(n, x), (40 * test_constants::pct_epsilon()) / 100); /*/usr/include/boost/math/special_functions/chebyshev.hpp:164:40: error: cannot convert boost::math::differentiation::autodiff_v1::detail::fvar to double in return - BOOST_CHECK_EQUAL(boost::math::chebyshev_clenshaw_recurrence(c.data(),c.size(),make_fvar(0.20)) + CHECK_EQUAL(boost::math::chebyshev_clenshaw_recurrence(c.data(),c.size(),make_fvar(0.20)) , boost::math::chebyshev_clenshaw_recurrence(c.data(),c.size(),static_cast(0.20)));*/ /*try { std::array c0{{14.2, -13.7, 82.3, 96}}; - BOOST_CHECK_CLOSE(boost::math::chebyshev_clenshaw_recurrence(c0.data(), + CHECK_RELATIVE_ERROR(boost::math::chebyshev_clenshaw_recurrence(c0.data(), c0.size(), make_fvar(x)), boost::math::chebyshev_clenshaw_recurrence(c0.data(), - c0.size(), x), 10*test_constants::pct_epsilon()); } catch (...) { + c0.size(), x), (10*test_constants::pct_epsilon()) / 100); } catch (...) { std::rethrow_exception(std::exception_ptr(std::current_exception())); }*/ } @@ -90,19 +91,21 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(chebyshev_hpp, T, all_float_types) { } #endif -BOOST_AUTO_TEST_CASE_TEMPLATE(cospi_hpp, T, all_float_types) { +template +void cospi_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{-2000, 2000}; for (auto i : boost::irange(test_constants::n_samples)) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK_CLOSE(boost::math::cos_pi(make_fvar(x)).derivative(0u), - boost::math::cos_pi(x), test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(boost::math::cos_pi(make_fvar(x)).derivative(0u), + boost::math::cos_pi(x), (test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(digamma_hpp, T, all_float_types) { +template +void digamma_hpp() { using boost::math::nextafter; using std::nextafter; @@ -115,9 +118,18 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(digamma_hpp, T, all_float_types) { auto x = nextafter(x_sampler.next(), ((std::numeric_limits::max))()); auto autodiff_v = boost::math::digamma(make_fvar(x)); auto anchor_v = boost::math::digamma(x); - BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v, - 1e4 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (1e4 * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_SUITE_END() +int main() +{ + boost::mp11::mp_for_each>([](auto t) { binomial_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { cbrt_hpp(); }); +#if !defined(__APPLE__) + boost::mp11::mp_for_each>([](auto t) { chebyshev_hpp(); }); +#endif + boost::mp11::mp_for_each>([](auto t) { cospi_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { digamma_hpp(); }); + return boost::math::test::report_errors(); +} diff --git a/test/test_autodiff_6.cpp b/test/test_autodiff_6.cpp index 7cbc11d0f3..45b31ab784 100644 --- a/test/test_autodiff_6.cpp +++ b/test/test_autodiff_6.cpp @@ -6,13 +6,13 @@ #include "test_autodiff.hpp" #include -BOOST_AUTO_TEST_SUITE(test_autodiff_6) /********************************************************************************************************************* * special functions tests *********************************************************************************************************************/ -BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_1_hpp, T, all_float_types) { +template +void ellint_1_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample k_sampler{T{-1}, T{1}}; @@ -22,17 +22,17 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_1_hpp, T, all_float_types) { std::ignore = i; auto k = k_sampler.next(); auto phi = phi_sampler.next(); - BOOST_CHECK_CLOSE(boost::math::ellint_1(make_fvar(k)).derivative(0u), - boost::math::ellint_1(k), - T(2.5e3) * test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR(boost::math::ellint_1(make_fvar(k)).derivative(0u), + boost::math::ellint_1(k), (T(2.5e3) * test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::ellint_1(make_fvar(k), make_fvar(phi)) .derivative(0u), - boost::math::ellint_1(k, phi), T(1e4) * test_constants::pct_epsilon()); + boost::math::ellint_1(k, phi), (T(1e4) * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_2_hpp, T, all_float_types) { +template +void ellint_2_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample k_sampler{-1, 1}; @@ -42,17 +42,17 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_2_hpp, T, all_float_types) { std::ignore = i; auto k = k_sampler.next(); auto phi = phi_sampler.next(); - BOOST_CHECK_CLOSE(boost::math::ellint_2(make_fvar(k)).derivative(0u), - boost::math::ellint_2(k), - 2.5e3 * test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR(boost::math::ellint_2(make_fvar(k)).derivative(0u), + boost::math::ellint_2(k), (2.5e3 * test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::ellint_2(make_fvar(k), make_fvar(phi)) .derivative(0u), - boost::math::ellint_2(k, phi), T(2.5e3) * test_constants::pct_epsilon()); + boost::math::ellint_2(k, phi), (T(2.5e3) * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_3_hpp, T, all_float_types) { +template +void ellint_3_hpp() { using boost::math::nextafter; using boost::multiprecision::nextafter; @@ -73,16 +73,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_3_hpp, T, all_float_types) { auto phi = phi_sampler.next(); auto n = (min)((min)(n_sampler.next(), T(1) / (sin(phi) * sin(phi))), nextafter(T(1), T(0))); - BOOST_CHECK_CLOSE(boost::math::ellint_3(make_fvar(k), + CHECK_RELATIVE_ERROR(boost::math::ellint_3(make_fvar(k), make_fvar(n), make_fvar(phi)) .derivative(0u), - boost::math::ellint_3(k, n, phi), - T(2.5e3) * test_constants::pct_epsilon()); + boost::math::ellint_3(k, n, phi), (T(2.5e3) * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_d_hpp, T, all_float_types) { +template +void ellint_d_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample k_sampler{-1, 1}; @@ -92,17 +92,17 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_d_hpp, T, all_float_types) { std::ignore = i; auto k = k_sampler.next(); auto phi = phi_sampler.next(); - BOOST_CHECK_CLOSE(boost::math::ellint_d(make_fvar(k)).derivative(0u), - boost::math::ellint_d(k), - T(2.5e3) * test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR(boost::math::ellint_d(make_fvar(k)).derivative(0u), + boost::math::ellint_d(k), (T(2.5e3) * test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::ellint_d(make_fvar(k), make_fvar(phi)) .derivative(0u), - boost::math::ellint_d(k, phi), 2.5e3 * test_constants::pct_epsilon()); + boost::math::ellint_d(k, phi), (2.5e3 * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rf_hpp, T, all_float_types) { +template +void ellint_rf_hpp() { using boost::math::tools::max; using std::max; @@ -122,15 +122,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rf_hpp, T, all_float_types) { auto y = nextafter(y_sampler.next(), ((std::numeric_limits::max))()); auto z = nextafter(z_sampler.next(), ((std::numeric_limits::max))()); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::ellint_rf(make_fvar(x), make_fvar(y), make_fvar(z)) .derivative(0u), - boost::math::ellint_rf(x, y, z), T(2.5e3) * test_constants::pct_epsilon()); + boost::math::ellint_rf(x, y, z), (T(2.5e3) * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rc_hpp, T, all_float_types) { +template +void ellint_rc_hpp() { using boost::math::fpclassify; using boost::math::nextafter; using boost::math::signbit; @@ -154,14 +155,15 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rc_hpp, T, all_float_types) { ((std::numeric_limits::max))())); } - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::ellint_rc(make_fvar(x), make_fvar(y)) .derivative(0u), - boost::math::ellint_rc(x, y), T(2.5e3) * test_constants::pct_epsilon()); + boost::math::ellint_rc(x, y), (T(2.5e3) * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rj_hpp, T, all_float_types) { +template +void ellint_rj_hpp() { using boost::math::fpclassify; using boost::math::nextafter; using boost::math::signbit; @@ -192,16 +194,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rj_hpp, T, all_float_types) { nextafter(T(0), T(signbit(p) ? -1 : 1) * ((std::numeric_limits::max))())); } - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::ellint_rj(make_fvar(x), make_fvar(y), make_fvar(z), make_fvar(p)) .derivative(0u), - boost::math::ellint_rj(x, y, z, p), - 2.5e3 * test_constants::pct_epsilon()); + boost::math::ellint_rj(x, y, z, p), (2.5e3 * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rd_hpp, T, all_float_types) { +template +void ellint_rd_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{0, 2000}; @@ -212,15 +214,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rd_hpp, T, all_float_types) { auto x = x_sampler.next(); auto y = (x == 0 ? 1 : 0) + y_sampler.next(); auto z = z_sampler.next(); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::ellint_rd(make_fvar(x), make_fvar(y), make_fvar(z)) .derivative(0u), - boost::math::ellint_rd(x, y, z), T(2.5e3) * test_constants::pct_epsilon()); + boost::math::ellint_rd(x, y, z), (T(2.5e3) * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rg_hpp, T, all_float_types) { +template +void ellint_rg_hpp() { using boost::math::nextafter; using std::nextafter; @@ -236,15 +239,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ellint_rg_hpp, T, all_float_types) { auto x = nextafter(x_sampler.next(), ((std::numeric_limits::max))()); auto y = nextafter(y_sampler.next(), ((std::numeric_limits::max))()); auto z = z_sampler.next(); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::ellint_rg(make_fvar(x), make_fvar(y), make_fvar(z)) .derivative(0u), - boost::math::ellint_rg(x, y, z), 50 * test_constants::pct_epsilon()); + boost::math::ellint_rg(x, y, z), (50 * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(erf_hpp, T, all_float_types) { +template +void erf_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{-2000, 2000}; @@ -252,30 +256,44 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(erf_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK(isNearZero(erf(make_fvar(x)).derivative(0u) - + CHECK_TRUE(isNearZero(erf(make_fvar(x)).derivative(0u) - boost::math::erf(x))); - BOOST_CHECK(isNearZero(erfc(make_fvar(x)).derivative(0u) - + CHECK_TRUE(isNearZero(erfc(make_fvar(x)).derivative(0u) - boost::math::erfc(x))); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(expint_hpp, T, all_float_types) { +template +void expint_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{1, 83}; for (auto n : boost::irange(1u, static_cast(test_constants::n_samples))) { auto x = x_sampler.next(); - BOOST_CHECK_CLOSE(boost::math::expint(n, make_fvar(x)).derivative(0u), - boost::math::expint(n, x), - 200 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(boost::math::expint(n, make_fvar(x)).derivative(0u), + boost::math::expint(n, x), (200 * test_constants::pct_epsilon()) / 100); for (auto y : {-1, 1}) { - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::expint(make_fvar(x * y)).derivative(0u), - boost::math::expint(x * y), 200 * test_constants::pct_epsilon()); + boost::math::expint(x * y), (200 * test_constants::pct_epsilon()) / 100); } } } -BOOST_AUTO_TEST_SUITE_END() +int main() +{ + boost::mp11::mp_for_each>([](auto t) { ellint_1_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { ellint_2_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { ellint_3_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { ellint_d_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { ellint_rf_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { ellint_rc_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { ellint_rj_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { ellint_rd_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { ellint_rg_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { erf_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { expint_hpp(); }); + return boost::math::test::report_errors(); +} diff --git a/test/test_autodiff_7.cpp b/test/test_autodiff_7.cpp index cbf81c6566..678a7818ce 100644 --- a/test/test_autodiff_7.cpp +++ b/test/test_autodiff_7.cpp @@ -5,9 +5,9 @@ #include "test_autodiff.hpp" -BOOST_AUTO_TEST_SUITE(test_autodiff_7) -BOOST_AUTO_TEST_CASE_TEMPLATE(expm1_hpp, T, all_float_types) { +template +void expm1_hpp() { using boost::math::differentiation::detail::log; using boost::multiprecision::log; using std::log; @@ -17,10 +17,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(expm1_hpp, T, all_float_types) { for (auto i : boost::irange(test_constants::n_samples)) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK_CLOSE(boost::math::expm1(make_fvar(x)).derivative(0u), - boost::math::expm1(x), - 50 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(boost::math::expm1(make_fvar(x)).derivative(0u), + boost::math::expm1(x), (50 * test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_SUITE_END() +int main() +{ + boost::mp11::mp_for_each>([](auto t) { expm1_hpp(); }); + return boost::math::test::report_errors(); +} diff --git a/test/test_autodiff_8.cpp b/test/test_autodiff_8.cpp index b15f5c3d74..130423a9d0 100644 --- a/test/test_autodiff_8.cpp +++ b/test/test_autodiff_8.cpp @@ -6,23 +6,22 @@ #include "test_autodiff.hpp" #include -BOOST_AUTO_TEST_SUITE(test_autodiff_8) -// This workaround is a temporary fix for Clang on Apple: -#if !defined(__clang__) || !defined(__APPLE__) || !defined(__MACH__) -BOOST_AUTO_TEST_CASE_TEMPLATE(hermite_hpp, T, all_float_types) { +template +void hermite_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; - test_detail::RandomSample x_sampler{-200, 200}; - for (auto i : boost::irange(14u)) { + test_detail::RandomSample x_sampler{-1, 1}; + for (auto i : boost::irange(3u)) { auto x = x_sampler.next(); auto autodiff_v = boost::math::hermite(i, make_fvar(x)); auto anchor_v = boost::math::hermite(i, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (100 * test_constants::pct_epsilon()) / 100); } } -#endif -BOOST_AUTO_TEST_CASE_TEMPLATE(heuman_lambda_hpp, T, all_float_types) { + +template +void heuman_lambda_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{-1, 1}; @@ -35,11 +34,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(heuman_lambda_hpp, T, all_float_types) { auto autodiff_v = boost::math::heuman_lambda(make_fvar(x), make_fvar(phi)); auto anchor_v = boost::math::heuman_lambda(x, phi); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_TRUE(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(hypot_hpp, T, all_float_types) { +template +void hypot_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{-2000, 2000}; @@ -51,11 +51,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(hypot_hpp, T, all_float_types) { auto autodiff_v = boost::math::hypot(make_fvar(x), make_fvar(y)); auto anchor_v = boost::math::hypot(x, y); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_TRUE(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi_elliptic_hpp, T, all_float_types) { +template +void jacobi_elliptic_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample k_sampler{0, 1}; @@ -64,58 +65,59 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi_elliptic_hpp, T, all_float_types) { std::ignore = i; auto k = k_sampler.next(); auto theta = theta_sampler.next(); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_cd(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_cd(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_cn(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_cn(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_cs(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_cs(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_dc(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_dc(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_dn(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_dn(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_ds(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_ds(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_nc(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_nc(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_nd(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_nd(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_ns(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_ns(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_sc(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_sc(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_sd(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_sd(k, theta))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_sn(make_fvar(k), make_fvar(theta)) .derivative(0u) - boost::math::jacobi_sn(k, theta))); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi_zeta_hpp, T, all_float_types) { +template +void jacobi_zeta_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{-1, 1}; @@ -125,44 +127,38 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(jacobi_zeta_hpp, T, all_float_types) { std::ignore = i; auto x = x_sampler.next(); auto phi = phi_sampler.next(); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::jacobi_zeta(make_fvar(x), make_fvar(phi)) .derivative(0u) - boost::math::jacobi_zeta(x, phi))); } } -#if !defined(__clang__) || !defined(__APPLE__) || !defined(__MACH__) -BOOST_AUTO_TEST_CASE_TEMPLATE(laguerre_hpp, T, all_float_types) { - using boost::multiprecision::min; - using std::min; - +template +void laguerre_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; - test_detail::RandomSample n_sampler{1, 50}; - test_detail::RandomSample r_sampler{0, 50}; - test_detail::RandomSample x_sampler{0, 50}; - - for (auto i : boost::irange(test_constants::n_samples)) { - std::ignore = i; - auto n = n_sampler.next(); - auto r = (min)(n - 1, r_sampler.next()); - auto x = x_sampler.next(); - + int n = 3; + int r = 2; + for (T x : {T(0), T(0.25), T(0.5), T(0.75), T(1)}) { { auto autodiff_v = boost::math::laguerre(n, make_fvar(x)); auto anchor_v = boost::math::laguerre(n, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (1000 * test_constants::pct_epsilon()) / 100); } + { auto autodiff_v = boost::math::laguerre(n, r, make_fvar(x)); auto anchor_v = boost::math::laguerre(n, r, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (500 * test_constants::pct_epsilon()) / 100); } } } -#endif -BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w_hpp, T, all_float_types) { + +template +void lambert_w_hpp() { using boost::math::nextafter; using boost::math::tools::max; using boost::multiprecision::fabs; @@ -188,12 +184,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w_hpp, T, all_float_types) { { auto autodiff_v = boost::math::lambert_w0(make_fvar(x_)); auto anchor_v = boost::math::lambert_w0(x_); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_TRUE(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } { auto autodiff_v = boost::math::lambert_w0_prime(make_fvar(x_)); auto anchor_v = boost::math::lambert_w0_prime(x_); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_TRUE(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } @@ -204,17 +200,18 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w_hpp, T, all_float_types) { ((std::numeric_limits::max))())), ((std::numeric_limits::max))()); x_ = (max)(static_cast(-0.36), x_); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::lambert_wm1(make_fvar(x_)).derivative(0u) - boost::math::lambert_wm1(x_))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( boost::math::lambert_wm1_prime(make_fvar(x_)).derivative(0u) - boost::math::lambert_wm1_prime(x_))); } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(log1p_hpp, T, all_float_types) { +template +void log1p_hpp() { using boost::math::log1p; using boost::multiprecision::log1p; @@ -224,12 +221,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(log1p_hpp, T, all_float_types) { for (auto i : boost::irange(test_constants::n_samples)) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK( + CHECK_TRUE( isNearZero(log1p(make_fvar(x)).derivative(0u) - log1p(x))); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(next_hpp, T, all_float_types) { +template +void next_hpp() { using boost::math::float_advance; using boost::math::float_distance; using boost::math::float_next; @@ -242,64 +240,65 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(next_hpp, T, all_float_types) { for (auto i : boost::irange(test_constants::n_samples)) { const auto j = static_cast(i); auto fvar_j = make_fvar(j); - BOOST_CHECK(isNearZero(float_next(fvar_j).derivative(0u) - float_next(j))); - BOOST_CHECK( + CHECK_TRUE(isNearZero(float_next(fvar_j).derivative(0u) - float_next(j))); + CHECK_TRUE( isNearZero(float_prior(fvar_j).derivative(0u) - float_prior(j))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( nextafter(fvar_j, make_fvar(static_cast(1))).derivative(0u) - nextafter(j, static_cast(1)))); - BOOST_CHECK( + CHECK_TRUE( isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 2))) - nextafter(j, static_cast(i + 2)))); - BOOST_CHECK( + CHECK_TRUE( isNearZero(nextafter(fvar_j, make_fvar(static_cast(i + 1))) .derivative(0u) - nextafter(j, static_cast(i + 2)))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( nextafter(fvar_j, make_fvar(static_cast(-1))).derivative(0u) - nextafter(j, static_cast(-1)))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( nextafter(fvar_j, make_fvar(static_cast(-1 * (i + 2)))) .derivative(0u) - nextafter(j, -1 * static_cast(i + 2)))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( nextafter(fvar_j, make_fvar(static_cast(-1 * (i + 1)))) .derivative(0u) - nextafter(j, -1 * static_cast(i + 2)))); - BOOST_CHECK(isNearZero(nextafter(fvar_j, fvar_j) - fvar_j)); + CHECK_TRUE(isNearZero(nextafter(fvar_j, fvar_j) - fvar_j)); - BOOST_CHECK(isNearZero(float_advance(fvar_j, 1).derivative(0u) - + CHECK_TRUE(isNearZero(float_advance(fvar_j, 1).derivative(0u) - float_advance(j, 1))); - BOOST_CHECK(isNearZero(float_advance(fvar_j, i + 2).derivative(0u) - + CHECK_TRUE(isNearZero(float_advance(fvar_j, i + 2).derivative(0u) - float_advance(j, i + 2))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( float_advance(fvar_j, i + 1).derivative(0u) - float_advance(float_advance(fvar_j, i + 2), -1).derivative(0u))); - BOOST_CHECK(isNearZero(float_advance(fvar_j, -1).derivative(0u) - + CHECK_TRUE(isNearZero(float_advance(fvar_j, -1).derivative(0u) - float_advance(j, -1))); - BOOST_CHECK(isNearZero( + CHECK_TRUE(isNearZero( float_advance(fvar_j, -i - 1).derivative(0u) - float_advance(float_advance(fvar_j, -i - 2), 1).derivative(0u))); - BOOST_CHECK(isNearZero(float_advance(fvar_j, 0) - fvar_j)); + CHECK_TRUE(isNearZero(float_advance(fvar_j, 0) - fvar_j)); - BOOST_CHECK(isNearZero(float_distance(fvar_j, j).derivative(0u) - + CHECK_TRUE(isNearZero(float_distance(fvar_j, j).derivative(0u) - static_cast(0))); - BOOST_CHECK( + CHECK_TRUE( isNearZero(float_distance(float_next(fvar_j), fvar_j).derivative(0u) - ((make_fvar(-1))).derivative(0u))); - BOOST_CHECK( + CHECK_TRUE( isNearZero(float_distance(float_prior(fvar_j), fvar_j).derivative(0u) - (make_fvar(1)).derivative(0u))); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(owens_t_hpp, T, bin_float_types) { +template +void owens_t_hpp() { BOOST_MATH_STD_USING; using test_constants = test_constants_t; static constexpr auto m = test_constants::order; @@ -312,49 +311,51 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(owens_t_hpp, T, bin_float_types) { auto autodiff_v = boost::math::owens_t(make_fvar(h), make_fvar(a)); auto anchor_v = boost::math::owens_t(h, a); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_TRUE(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(pow_hpp, T, all_float_types) { +template +void pow_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; for (auto i : boost::irange(10)) { - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR( boost::math::pow<0>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<0>(static_cast(i)), test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + boost::math::pow<0>(static_cast(i)), (test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::pow<1>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<1>(static_cast(i)), test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + boost::math::pow<1>(static_cast(i)), (test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::pow<2>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<2>(static_cast(i)), test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + boost::math::pow<2>(static_cast(i)), (test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::pow<3>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<3>(static_cast(i)), test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + boost::math::pow<3>(static_cast(i)), (test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::pow<4>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<4>(static_cast(i)), test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + boost::math::pow<4>(static_cast(i)), (test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::pow<5>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<5>(static_cast(i)), test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + boost::math::pow<5>(static_cast(i)), (test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::pow<6>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<6>(static_cast(i)), test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + boost::math::pow<6>(static_cast(i)), (test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::pow<7>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<7>(static_cast(i)), test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + boost::math::pow<7>(static_cast(i)), (test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::pow<8>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<8>(static_cast(i)), test_constants::pct_epsilon()); - BOOST_CHECK_CLOSE( + boost::math::pow<8>(static_cast(i)), (test_constants::pct_epsilon()) / 100); + CHECK_RELATIVE_ERROR( boost::math::pow<9>(make_fvar(static_cast(i))).derivative(0u), - boost::math::pow<9>(static_cast(i)), test_constants::pct_epsilon()); + boost::math::pow<9>(static_cast(i)), (test_constants::pct_epsilon()) / 100); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(polygamma_hpp, T, all_float_types) { +template +void polygamma_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{0, 2000}; @@ -363,19 +364,20 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(polygamma_hpp, T, all_float_types) { try { auto autodiff_v = boost::math::polygamma(i, make_fvar(x)); auto anchor_v = boost::math::polygamma(i, x); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_TRUE(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } catch (const std::overflow_error &) { std::cout << "Overflow Error thrown with inputs i: " << i << " x: " << x << std::endl; - BOOST_CHECK_THROW(boost::math::polygamma(i, make_fvar(x)), + CHECK_THROW(boost::math::polygamma(i, make_fvar(x)), boost::wrapexcept); - BOOST_CHECK_THROW(boost::math::polygamma(i, x), + CHECK_THROW(boost::math::polygamma(i, x), boost::wrapexcept); } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(powm1_hpp, T, all_float_types) { +template +void powm1_hpp() { using boost::math::tools::max; using boost::multiprecision::max; using std::max; @@ -409,26 +411,28 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(powm1_hpp, T, all_float_types) { auto autodiff_v = boost::math::powm1(make_fvar(x), make_fvar(y)); auto anchor_v = boost::math::powm1(x, y); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_TRUE(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } #if __clang_major__ > 5 || __GNUC__ > 5 || defined(_MSC_VER) -BOOST_AUTO_TEST_CASE_TEMPLATE(sin_pi_hpp, T, all_float_types) { +template +void sin_pi_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{-2000, 2000}; for (auto i : boost::irange(test_constants::n_samples)) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK( + CHECK_TRUE( isNearZero(boost::math::sin_pi(make_fvar(x)).derivative(0u) - boost::math::sin_pi(x))); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(sinhc_hpp, T, all_float_types) { +template +void sinhc_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{ -80, 80 }; @@ -438,13 +442,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(sinhc_hpp, T, all_float_types) { if (x != 0) { auto autodiff_v = boost::math::sinhc_pi(make_fvar(x)); auto anchor_v = boost::math::sinhc_pi(x); - BOOST_CHECK_CLOSE(autodiff_v.derivative(0u), anchor_v, - 50 * test_constants::pct_epsilon()); + CHECK_RELATIVE_ERROR(autodiff_v.derivative(0u), anchor_v, (50 * test_constants::pct_epsilon()) / 100); } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(spherical_harmonic_hpp, T, all_float_types) { +template +void spherical_harmonic_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample theta_sampler{0, @@ -461,9 +465,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(spherical_harmonic_hpp, T, all_float_types) { auto autodiff_v = boost::math::spherical_harmonic( n, r, make_fvar(theta), make_fvar(phi)); auto anchor_v = boost::math::spherical_harmonic(n, r, theta, phi); - BOOST_CHECK( + CHECK_TRUE( isNearZero(autodiff_v.real().derivative(0u) - anchor_v.real())); - BOOST_CHECK( + CHECK_TRUE( isNearZero(autodiff_v.imag().derivative(0u) - anchor_v.imag())); } @@ -471,39 +475,41 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(spherical_harmonic_hpp, T, all_float_types) { auto autodiff_v = boost::math::spherical_harmonic_r( n, r, make_fvar(theta), make_fvar(phi)); auto anchor_v = boost::math::spherical_harmonic_r(n, r, theta, phi); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_TRUE(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } { auto autodiff_v = boost::math::spherical_harmonic_i( n, r, make_fvar(theta), make_fvar(phi)); auto anchor_v = boost::math::spherical_harmonic_i(n, r, theta, phi); - BOOST_CHECK(isNearZero(autodiff_v.derivative(0u) - anchor_v)); + CHECK_TRUE(isNearZero(autodiff_v.derivative(0u) - anchor_v)); } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(sqrt1pm1_hpp, T, all_float_types) { +template +void sqrt1pm1_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{-1, 2000}; for (auto i : boost::irange(test_constants::n_samples)) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK( + CHECK_TRUE( isNearZero(boost::math::sqrt1pm1(make_fvar(x)).derivative(0u) - boost::math::sqrt1pm1(x))); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(trigamma_hpp, T, all_float_types) { +template +void trigamma_hpp() { using test_constants = test_constants_t; static constexpr auto m = test_constants::order; test_detail::RandomSample x_sampler{0, 2000}; for (auto i : boost::irange(test_constants::n_samples)) { std::ignore = i; auto x = x_sampler.next(); - BOOST_CHECK( + CHECK_TRUE( isNearZero(boost::math::trigamma(make_fvar(x)).derivative(0u) - boost::math::trigamma(x))); } @@ -511,4 +517,35 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(trigamma_hpp, T, all_float_types) { #endif // Compiler guard -BOOST_AUTO_TEST_SUITE_END() +int main() +{ + boost::mp11::mp_for_each>([](auto t) { hermite_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { heuman_lambda_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { hypot_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { jacobi_elliptic_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { jacobi_zeta_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { laguerre_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { lambert_w_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { log1p_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { next_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { owens_t_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { pow_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { polygamma_hpp(); }); + boost::mp11::mp_for_each>([](auto t) { powm1_hpp(); }); +#if __clang_major__ > 5 || __GNUC__ > 5 || defined(_MSC_VER) + boost::mp11::mp_for_each>([](auto t) { sin_pi_hpp(); }); +#endif +#if __clang_major__ > 5 || __GNUC__ > 5 || defined(_MSC_VER) + boost::mp11::mp_for_each>([](auto t) { sinhc_hpp(); }); +#endif +#if __clang_major__ > 5 || __GNUC__ > 5 || defined(_MSC_VER) + boost::mp11::mp_for_each>([](auto t) { spherical_harmonic_hpp(); }); +#endif +#if __clang_major__ > 5 || __GNUC__ > 5 || defined(_MSC_VER) + boost::mp11::mp_for_each>([](auto t) { sqrt1pm1_hpp(); }); +#endif +#if __clang_major__ > 5 || __GNUC__ > 5 || defined(_MSC_VER) + boost::mp11::mp_for_each>([](auto t) { trigamma_hpp(); }); +#endif + return boost::math::test::report_errors(); +} diff --git a/test/test_autodiff_module.cpp b/test/test_autodiff_module.cpp new file mode 100644 index 0000000000..d7f58e746c --- /dev/null +++ b/test/test_autodiff_module.cpp @@ -0,0 +1,79 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Module build check for forward-mode automatic differentiation. The fvar class +// template, the make_fvar factory, its arithmetic operators and the +// std::numeric_limits specialization all reach a consumer through the +// boost.math module. Exercising make_fvar/derivative and that specialization +// confirms the differentiation component resolves when built against the module. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif +#include "math_unit_test.hpp" + +template +void test_spots(T, const char* type_name) +{ + std::cout << "Testing autodiff for type " << type_name << std::endl; + + using boost::math::differentiation::make_fvar; + + // f(x) = x * x at x = 3. value 9, f'(x) = 2x = 6, f''(x) = 2. + { + const auto x {make_fvar(static_cast(3))}; + const auto y {x * x}; + CHECK_EQUAL(y.derivative(0), static_cast(9)); + CHECK_EQUAL(y.derivative(1), static_cast(6)); + CHECK_EQUAL(y.derivative(2), static_cast(2)); + + // The std::numeric_limits specialization must cross the module boundary. + static_assert(std::numeric_limits::is_specialized, "autodiff numeric_limits"); + } + + // Single independent variable f(x) = x at x = 10. value 10, f'(x) = 1, rest 0. + { + const auto x {make_fvar(static_cast(10))}; + CHECK_EQUAL(x.derivative(0), static_cast(10)); + CHECK_EQUAL(x.derivative(1), static_cast(1)); + CHECK_EQUAL(x.derivative(2), static_cast(0)); + CHECK_EQUAL(x.derivative(3), static_cast(0)); + } + + // f(x) = 1 / x at x = 16 (a power of two, so every derivative is exact). + // f'(x) = -1 / x^2, f''(x) = 2 / x^3, f'''(x) = -6 / x^4. + { + const T cx {16}; + const auto x {make_fvar(cx)}; + const auto quotient {static_cast(1) / x}; + CHECK_ULP_CLOSE(static_cast(1) / cx, quotient.derivative(0), 2); + CHECK_ULP_CLOSE(static_cast(-1) / (cx * cx), quotient.derivative(1), 2); + CHECK_ULP_CLOSE(static_cast(2) / (cx * cx * cx), quotient.derivative(2), 2); + CHECK_ULP_CLOSE(static_cast(-6) / (cx * cx * cx * cx), quotient.derivative(3), 2); + } + + // Second independent variable f(x, y) = y at y = 100. df/dy = 1, others 0. + { + const auto y {make_fvar(static_cast(100))}; + CHECK_EQUAL(y.derivative(0, 0), static_cast(100)); + CHECK_EQUAL(y.derivative(0, 1), static_cast(1)); + CHECK_EQUAL(y.derivative(1, 0), static_cast(0)); + CHECK_EQUAL(y.derivative(0, 2), static_cast(0)); + } +} + +int main() +{ + test_spots(0.0F, "float"); + test_spots(0.0, "double"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_autodiff_reverse.hpp b/test/test_autodiff_reverse.hpp index d539fa243b..05e800ceb2 100644 --- a/test/test_autodiff_reverse.hpp +++ b/test/test_autodiff_reverse.hpp @@ -4,12 +4,9 @@ // https://www.boost.org/LICENSE_1_0.txt) #ifndef TEST_AUTODIFF_REVERSE_HPP #define TEST_AUTODIFF_REVERSE_HPP -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MODULE test_autodiff -#endif #define BOOST_MP_NO_QUAD #define BOOST_MATH_DISABLE_FLOAT128 -#include +#include "math_unit_test.hpp" #include // always safe #if __has_include() @@ -19,13 +16,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -134,7 +131,7 @@ struct RandomSample template RandomSample(U start, V finish) - : rng_(std::random_device{}()) + : rng_(42) // fixed, as in test_autodiff.hpp, so that a failure reproduces , dist_(static_cast(start), get_endpoint_t{}(finish)) {} @@ -156,7 +153,7 @@ static_assert(std::is_same::dist_t, ""); template -constexpr T boost_close_tol(T scale_factor = 1e5) +constexpr T boost_close_tol(T /*scale_factor*/ = T(1e5)) { - return 0.01; + return T(0.01); } diff --git a/test/test_barycentric_rational.cpp b/test/test_barycentric_rational.cpp index f131f6995b..2f14f707d3 100644 --- a/test/test_barycentric_rational.cpp +++ b/test/test_barycentric_rational.cpp @@ -4,16 +4,13 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_TEST_MODULE barycentric_rational - #include #include #include #include -#include -#include #include #include +#include "math_unit_test.hpp" #ifdef BOOST_HAS_FLOAT128 #include @@ -49,7 +46,7 @@ void test_interpolation_condition() for (size_t i = 0; i < x.size(); ++i) { Real z = interpolator(x[i]); - BOOST_CHECK_CLOSE(z, y[i], 100*numeric_limits::epsilon()); + CHECK_ULP_CLOSE(y[i], z, 2); } // Make sure that the move constructor does the same thing: @@ -60,7 +57,7 @@ void test_interpolation_condition() for (size_t i = 0; i < x_copy.size(); ++i) { Real z = move_interpolator(x_copy[i]); - BOOST_CHECK_CLOSE(z, y_copy[i], 100*numeric_limits::epsilon()); + CHECK_ULP_CLOSE(y_copy[i], z, 2); } } @@ -86,7 +83,7 @@ void test_interpolation_condition_high_order() for (size_t i = 0; i < x.size(); ++i) { Real z = interpolator(x[i]); - BOOST_CHECK_CLOSE(z, y[i], 100*numeric_limits::epsilon()); + CHECK_ULP_CLOSE(y[i], z, 2); } } @@ -116,8 +113,8 @@ void test_constant() // Don't evaluate the constant at x[i]; that's already tested in the interpolation condition test. Real t = x[i] + dis(gen); Real z = interpolator(t); - BOOST_CHECK_CLOSE(z, constant, 100*sqrt(numeric_limits::epsilon())); - BOOST_CHECK_SMALL(interpolator.prime(t), sqrt(numeric_limits::epsilon())); + CHECK_ABSOLUTE_ERROR(constant, z, Real((sqrt(numeric_limits::epsilon()))*abs(constant))); + CHECK_ABSOLUTE_ERROR(0, interpolator.prime(t), sqrt(numeric_limits::epsilon())); } } @@ -146,8 +143,8 @@ void test_constant_high_order() { Real t = x[i] + dis(gen); Real z = interpolator(t); - BOOST_CHECK_CLOSE(z, constant, 1000*sqrt(numeric_limits::epsilon())); - BOOST_CHECK_SMALL(interpolator.prime(t), 100*sqrt(numeric_limits::epsilon())); + CHECK_ABSOLUTE_ERROR(constant, z, Real(10*(sqrt(numeric_limits::epsilon()))*abs(constant))); + CHECK_ABSOLUTE_ERROR(0, interpolator.prime(t), 100*sqrt(numeric_limits::epsilon())); } } @@ -175,13 +172,13 @@ void test_runge() { Real t = x[i]; Real z = interpolator(t); - BOOST_CHECK_CLOSE(z, y[i], 0.03); + CHECK_ABSOLUTE_ERROR(y[i], z, Real(0.0003*abs(y[i]))); Real z_prime = interpolator.prime(t); Real num = -50*t; Real denom = (1+25*t*t)*(1+25*t*t); if (abs(num/denom) > 0.00001) { - BOOST_CHECK_CLOSE_FRACTION(z_prime, num/denom, 0.03); + CHECK_ABSOLUTE_ERROR(num/denom, z_prime, Real(0.03*abs(num/denom))); } } @@ -191,7 +188,7 @@ void test_runge() { Real t = x[i] + dis(gen); Real z = interpolator(t); - BOOST_CHECK_CLOSE(z, 1/(1+25*t*t), tol); + CHECK_ABSOLUTE_ERROR(1/(1+25*t*t), z, Real(tol/100*abs(1/(1+25*t*t)))); Real z_prime = interpolator.prime(t); Real num = -50*t; Real denom = (1+25*t*t)*(1+25*t*t); @@ -200,7 +197,7 @@ void test_runge() if (abs(runge_prime) > 0 && abs(z_prime - runge_prime)/abs(runge_prime) > tol) { std::cout << "Error too high for t = " << t << " which is a distance " << t - x[i] << " from node " << i << "/" << x.size() << " associated with data (" << x[i] << ", " << y[i] << ")\n"; - BOOST_CHECK_CLOSE_FRACTION(z_prime, runge_prime, tol); + CHECK_ABSOLUTE_ERROR(runge_prime, z_prime, Real(tol*abs(runge_prime))); } } } @@ -229,11 +226,11 @@ void test_weights() Real w = interpolator.weight(i); if (i % 2 == 0) { - BOOST_CHECK_CLOSE(w, 1, 0.00001); + CHECK_ABSOLUTE_ERROR(1, w, Real(1e-07)); } else { - BOOST_CHECK_CLOSE(w, -1, 0.00001); + CHECK_ABSOLUTE_ERROR(-1, w, Real(1e-07)); } } @@ -246,18 +243,18 @@ void test_weights() Real w_expect = 1/(x[i] - x[i - 1]) + 1/(x[i+1] - x[i]); if (i % 2 == 0) { - BOOST_CHECK_CLOSE(w, -w_expect, 0.00001); + CHECK_ABSOLUTE_ERROR(-w_expect, w, Real(1e-07*abs(-w_expect))); } else { - BOOST_CHECK_CLOSE(w, w_expect, 0.00001); + CHECK_ABSOLUTE_ERROR(w_expect, w, Real(1e-07*abs(w_expect))); } } } -BOOST_AUTO_TEST_CASE(barycentric_rational) +void barycentric_rational() { // The tests took too long at the higher precisions. // They still pass, but the CI system is starting to time out, @@ -320,3 +317,9 @@ BOOST_AUTO_TEST_CASE(barycentric_rational) #endif } + +int main() +{ + barycentric_rational(); + return boost::math::test::report_errors(); +} diff --git a/test/test_barycentric_rational_module.cpp b/test/test_barycentric_rational_module.cpp new file mode 100644 index 0000000000..62ab7a77d7 --- /dev/null +++ b/test/test_barycentric_rational_module.cpp @@ -0,0 +1,95 @@ +// Copyright Nick Thompson, 2017 +// 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) +// +// Module build check for barycentric_rational. Exercises the exported +// interpolator through `import boost.math;` so that its templates (and the +// std::shared_ptr / std::vector members they rely on) resolve when the test is +// compiled against the boost.math named module. The assertions use only +// mathematically certain properties: an interpolant reproduces its node values +// exactly, and a constant sample set is interpolated by that constant with a +// zero derivative. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#endif +#include "math_unit_test.hpp" + +template +void test_barycentric(const char* type_name) +{ + std::cout << "Testing barycentric_rational on type " << type_name << std::endl; + + using std::sqrt; + + // Interpolation condition: the interpolant reproduces its node values. + // operator()(x_i) returns the stored y_i exactly, so this is bit-exact. + std::vector x { static_cast(0), static_cast(1), static_cast(2), + static_cast(3), static_cast(4), static_cast(5), + static_cast(6) }; + std::vector y { static_cast(2.5), static_cast(-1.0), static_cast(3.25), + static_cast(0.5), static_cast(-4.0), static_cast(6.75), + static_cast(1.0) }; + + boost::math::interpolators::barycentric_rational interp(x.data(), y.data(), y.size()); + for (std::size_t i = 0; i < x.size(); ++i) + { + CHECK_ULP_CLOSE(y[i], interp(x[i]), 0); + } + + // Same condition with an explicit approximation order of 5 (needs order < node count). + std::vector xh { static_cast(0), static_cast(1), static_cast(2), + static_cast(3), static_cast(4), static_cast(5), + static_cast(6), static_cast(7) }; + std::vector yh { static_cast(1), static_cast(2), static_cast(4), + static_cast(8), static_cast(16), static_cast(32), + static_cast(64), static_cast(128) }; + boost::math::interpolators::barycentric_rational interp5(xh.data(), yh.data(), yh.size(), 5); + for (std::size_t i = 0; i < xh.size(); ++i) + { + CHECK_ULP_CLOSE(yh[i], interp5(xh[i]), 0); + } + + // The move constructor produces an equivalent interpolant. + std::vector xm = x; + std::vector ym = y; + boost::math::interpolators::barycentric_rational minterp(std::move(xm), std::move(ym)); + for (std::size_t i = 0; i < x.size(); ++i) + { + CHECK_ULP_CLOSE(y[i], minterp(x[i]), 0); + } + + // A constant sample set is interpolated by that constant, with zero derivative. + const Real c = static_cast(-8); + std::vector xc { static_cast(0), static_cast(1), static_cast(2), + static_cast(3), static_cast(4), static_cast(5) }; + std::vector yc(xc.size(), c); + boost::math::interpolators::barycentric_rational interpc(xc.data(), yc.data(), yc.size()); + + const Real prime_tol = sqrt(std::numeric_limits::epsilon()); + for (const Real t : { static_cast(0.5), static_cast(2.5), static_cast(4.5) }) + { + CHECK_ULP_CLOSE(c, interpc(t), 4); + CHECK_ABSOLUTE_ERROR(static_cast(0), interpc.prime(t), prime_tol); + } +} + +int main() +{ + test_barycentric("float"); + test_barycentric("double"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_bernoulli.cpp b/test/test_bernoulli.cpp index 256a897783..ad5dfb2064 100644 --- a/test/test_bernoulli.cpp +++ b/test/test_bernoulli.cpp @@ -146,6 +146,16 @@ void test_spots(RealType) static_cast(5.11111111111111111111111111111111111111111111L), tolerance); + // entropy = -p log(p) - (1 - p) log(1 - p): + BOOST_CHECK_CLOSE_FRACTION(entropy(bernoulli_distribution(static_cast(0.1L))), + static_cast(0.3250829733914482395065500282238179392356L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(entropy(bernoulli_distribution(static_cast(0.5L))), + static_cast(0.6931471805599453094172321214581765680755L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(entropy(bernoulli_distribution(static_cast(1e-10L))), + static_cast(2.402585092989045684017824788017689207601e-9L), tolerance); + BOOST_CHECK_EQUAL(entropy(bernoulli_distribution(0)), 0); + BOOST_CHECK_EQUAL(entropy(bernoulli_distribution(1)), 0); + #ifndef BOOST_MATH_NO_EXCEPTIONS BOOST_MATH_CHECK_THROW( quantile( diff --git a/test/test_bessel_airy_zeros.cpp b/test/test_bessel_airy_zeros.cpp index 2e5fbe937f..dd04026b6d 100644 --- a/test/test_bessel_airy_zeros.cpp +++ b/test/test_bessel_airy_zeros.cpp @@ -140,7 +140,23 @@ void test_bessel_zeros(RealType) // class boost::exception_detail::clone_impl >: // Error in function boost::math::bessel_jy(double,double): Order of Bessel function is too large to evaluate: got 3.4028234663852886e+038 - BOOST_MATH_CHECK_THROW(cyl_bessel_j_zero(boost::math::tools::max_value(), 1), boost::math::evaluation_error); + // Whether this overflows internally depends on how double is evaluated: with double promoted + // to long double, or on arm64 where an intermediate overflows, it throws, but with unpromoted SSE2 double + // on x86 the correctly rounded answer (which is max_value itself) is returned. + BOOST_IF_CONSTEXPR (std::is_same::value && !BOOST_MATH_PROMOTE_DOUBLE_POLICY) + { + try + { + BOOST_CHECK(cyl_bessel_j_zero(boost::math::tools::max_value(), 1) > boost::math::tools::max_value() / 2); + } + catch (const boost::math::evaluation_error&) + { + } + } + else + { + BOOST_MATH_CHECK_THROW(cyl_bessel_j_zero(boost::math::tools::max_value(), 1), boost::math::evaluation_error); + } BOOST_CHECK_CLOSE_FRACTION(cyl_bessel_j_zero(boost::math::tools::min_value(), 1), static_cast(2.4048255576957727686216318793264546431242449091460L), tolerance); diff --git a/test/test_bessel_i.cpp b/test/test_bessel_i.cpp index 10641848dc..ccfe31704f 100644 --- a/test/test_bessel_i.cpp +++ b/test/test_bessel_i.cpp @@ -52,7 +52,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_bessel_i_prime.cpp b/test/test_bessel_i_prime.cpp index e4db73a410..3254425d69 100644 --- a/test/test_bessel_i_prime.cpp +++ b/test/test_bessel_i_prime.cpp @@ -37,7 +37,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } @@ -58,12 +58,9 @@ void expected_results() "Mac OS", // platform largest_type, // test type(s) ".*", // test data group -#ifdef __aarch64__ - // Error rates for M1 macs are higher than x86_64 macs + // Unpromoted double has the same error rates on M1 and x86_64 macs + // (3763 for the negative order Mathworld data on x86_64): ".*", 4000, 1500); // test function -#else - ".*", 3500, 1500); // test function -#endif // // Cygwin: // @@ -102,7 +99,8 @@ void expected_results() "Win32.*", // platform largest_type, // test type(s) ".*", // test data group - ".*", 3500, 1000); // test function + // Unpromoted double: I'(-4.999, 2.125) = 1.1e-4 is off by 3763 eps, but its cond in v is 1.5e6: + ".*", 4000, 1500); // test function add_expected_result( ".*", // compiler ".*", // stdlib diff --git a/test/test_bessel_iterator.cpp b/test/test_bessel_iterator.cpp new file mode 100644 index 0000000000..95ce490c64 --- /dev/null +++ b/test/test_bessel_iterator.cpp @@ -0,0 +1,172 @@ +// (C) Copyright John Maddock, 2024 +// 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) + +#define BOOST_TEST_MAIN +#include +#include +#include + + +BOOST_AUTO_TEST_CASE(test_main) +{ + using boost::math::bessel_j_backwards_iterator; + using boost::math::bessel_i_backwards_iterator; + using boost::math::bessel_i_forwards_iterator; + + BOOST_CHECK_THROW(bessel_j_backwards_iterator(-2.3, 5.0), std::domain_error); + BOOST_CHECK_THROW(bessel_j_backwards_iterator(-2.3, 5.0, 2.0), std::domain_error); + BOOST_CHECK_THROW(bessel_j_backwards_iterator(-2.3, 5.0, 2.0, 2.0), std::domain_error); + + double tolerance = std::numeric_limits::epsilon() * 5; + + { + bessel_j_backwards_iterator i(12, 2.0); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_j(8, 2.0), tolerance); + double v = *i++; + BOOST_CHECK_CLOSE_FRACTION(v, boost::math::cyl_bessel_j(8, 2.0), tolerance); + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_j(7, 2.0), tolerance); + } + { + bessel_j_backwards_iterator i(12, 2.0, boost::math::cyl_bessel_j(12, 2.0)); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_j(8, 2.0), tolerance); + } + { + bessel_j_backwards_iterator i(12, 2.0, boost::math::cyl_bessel_j(13, 2.0), boost::math::cyl_bessel_j(12, 2.0)); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_j(8, 2.0), tolerance); + } + + { + bessel_i_backwards_iterator i(12, 2.0); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(8, 2.0), tolerance); + double v = *i++; + BOOST_CHECK_CLOSE_FRACTION(v, boost::math::cyl_bessel_i(8, 2.0), tolerance); + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(7, 2.0), tolerance); + + BOOST_CHECK_THROW(bessel_i_backwards_iterator(-1.1, 2.0), std::domain_error); + BOOST_CHECK_THROW(bessel_i_backwards_iterator(-1.1, 2.0, 1.0), std::domain_error); + BOOST_CHECK_THROW(bessel_i_backwards_iterator(-1.1, 2.0, 1.0, 1.0), std::domain_error); + } + { + bessel_i_backwards_iterator i(12, 2.0, boost::math::cyl_bessel_i(12, 2.0)); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(8, 2.0), tolerance); + } + { + bessel_i_backwards_iterator i(12, 2.0, boost::math::cyl_bessel_i(13, 2.0), boost::math::cyl_bessel_i(12, 2.0)); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(8, 2.0), tolerance); + } + + { + bessel_i_forwards_iterator i(-12, 2.0); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(-8, 2.0), tolerance); + double v = *i++; + BOOST_CHECK_CLOSE_FRACTION(v, boost::math::cyl_bessel_i(-8, 2.0), tolerance); + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(-7, 2.0), tolerance); + + BOOST_CHECK_THROW(bessel_i_forwards_iterator(1.1, 2.0), std::domain_error); + BOOST_CHECK_THROW(bessel_i_forwards_iterator(1.1, 2.0, 1.0), std::domain_error); + BOOST_CHECK_THROW(bessel_i_forwards_iterator(1.1, 2.0, 1.0, 1.0), std::domain_error); + } + { + bessel_i_forwards_iterator i(-12, 2.0, boost::math::cyl_bessel_i(-12, 2.0)); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(-8, 2.0), tolerance); + } + { + bessel_i_forwards_iterator i(-12, 2.0, boost::math::cyl_bessel_i(-13, 2.0), boost::math::cyl_bessel_i(-12, 2.0)); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(-8, 2.0), tolerance); + } +} + +BOOST_AUTO_TEST_CASE(test_order_offset) +{ + using boost::math::bessel_j_backwards_iterator; + using boost::math::bessel_i_backwards_iterator; + using boost::math::bessel_i_forwards_iterator; + using boost::math::tools::recurrence_offset; + using mp_t = boost::multiprecision::cpp_bin_float_50; + // I_{v+j}(x) and J_{v+j}(x) to double precision, with v + j exact: + auto I = [](double v, int j, double x) { return static_cast(boost::math::cyl_bessel_i(mp_t(v) + j, mp_t(x))); }; + auto J = [](double v, int j, double x) { return static_cast(boost::math::cyl_bessel_j(mp_t(v) + j, mp_t(x))); }; + + // + // Starting from order v + k with k an integer, each order v + j is rounded only once. Starting from the rounded + // order v + k instead puts every order out by ~eps * k; for I near v = -1 and small x that costs over 5000 eps: + // + double tolerance = std::numeric_limits::epsilon() * 20; + { + double v = -0.999, x = 0.01; + bessel_i_backwards_iterator i(v, x, I(v, 21, x), I(v, 20, x), recurrence_offset(20)); + for (int j = 20; j >= 0; --j, ++i) + BOOST_CHECK_CLOSE_FRACTION(*i, I(v, j, x), tolerance); + bessel_i_backwards_iterator i1(v, x, I(v, 20, x), recurrence_offset(20)); + for (int j = 20; j >= 0; --j, ++i1) + BOOST_CHECK_CLOSE_FRACTION(*i1, I(v, j, x), tolerance); + } + { + double v = 0.1, x = 2; + bessel_i_backwards_iterator i(v, x, I(v, 101, x), I(v, 100, x), recurrence_offset(100)); + for (int j = 100; j >= 0; --j, ++i) + BOOST_CHECK_CLOSE_FRACTION(*i, I(v, j, x), tolerance); + } + { + double v = 0.1, x = 2; + bessel_j_backwards_iterator i(v, x, J(v, 41, x), J(v, 40, x), recurrence_offset(40)); + for (int j = 40; j >= 0; --j, ++i) + BOOST_CHECK_CLOSE_FRACTION(*i, J(v, j, x), tolerance); + bessel_j_backwards_iterator i1(v, x, J(v, 40, x), recurrence_offset(40)); + for (int j = 40; j >= 0; --j, ++i1) + BOOST_CHECK_CLOSE_FRACTION(*i1, J(v, j, x), tolerance); + } + // + // The constructors that compute the starting value, and the forwards iterator (only stable for integer orders): + // + tolerance = std::numeric_limits::epsilon() * 5; + { + bessel_i_backwards_iterator i(2.0, 2.0, recurrence_offset(10)); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(8, 2.0), tolerance); + bessel_j_backwards_iterator k(2.0, 2.0, recurrence_offset(10)); + for (unsigned j = 0; j < 4; ++j) + ++k; + BOOST_CHECK_CLOSE_FRACTION(*k, boost::math::cyl_bessel_j(8, 2.0), tolerance); + } + { + bessel_i_forwards_iterator i(0.0, 2.0, recurrence_offset(-12)); + for (unsigned j = 0; j < 4; ++j) + ++i; + BOOST_CHECK_CLOSE_FRACTION(*i, boost::math::cyl_bessel_i(-8, 2.0), tolerance); + bessel_i_forwards_iterator i1(0.0, 2.0, boost::math::cyl_bessel_i(-12, 2.0), recurrence_offset(-12)); + for (unsigned j = 0; j < 4; ++j) + ++i1; + BOOST_CHECK_CLOSE_FRACTION(*i1, boost::math::cyl_bessel_i(-8, 2.0), tolerance); + bessel_i_forwards_iterator i2(0.0, 2.0, boost::math::cyl_bessel_i(-13, 2.0), boost::math::cyl_bessel_i(-12, 2.0), recurrence_offset(-12)); + for (unsigned j = 0; j < 4; ++j) + ++i2; + BOOST_CHECK_CLOSE_FRACTION(*i2, boost::math::cyl_bessel_i(-8, 2.0), tolerance); + } + // The domain checks apply to the starting order v + k: + BOOST_CHECK_THROW(bessel_i_backwards_iterator(0.5, 2.0, 1.0, recurrence_offset(-2)), std::domain_error); + BOOST_CHECK_THROW(bessel_i_backwards_iterator(0.5, 2.0, 1.0, 1.0, recurrence_offset(-2)), std::domain_error); + BOOST_CHECK_THROW(bessel_j_backwards_iterator(0.5, 2.0, 1.0, recurrence_offset(-1)), std::domain_error); + BOOST_CHECK_THROW(bessel_i_forwards_iterator(-0.5, 2.0, 1.0, recurrence_offset(2)), std::domain_error); +} diff --git a/test/test_bessel_j.cpp b/test/test_bessel_j.cpp index 2570c3e092..4a3a996763 100644 --- a/test/test_bessel_j.cpp +++ b/test/test_bessel_j.cpp @@ -52,7 +52,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } @@ -198,6 +198,8 @@ void expected_results() BOOST_IF_CONSTEXPR ((std::numeric_limits::digits != std::numeric_limits::digits) && (std::numeric_limits::digits < 90)) { + if (boost::math::policies::promote_double<>()) + { // some errors spill over into type double as well: add_expected_result( ".*", // compiler @@ -227,6 +229,7 @@ void expected_results() "double", // test type(s) ".*", // test data group ".*", 30, 30); // test function + } // // and we have a few cases with higher limits as well: // @@ -252,7 +255,7 @@ void expected_results() ".*(JN|j).*|.*Tricky.*", // test data group ".*", 33000, 20000); // test function } - else BOOST_IF_CONSTEXPR (std::numeric_limits::digits >= 90) + else BOOST_IF_CONSTEXPR (boost::math::policies::promote_double<>() && std::numeric_limits::digits >= 90) { add_expected_result( ".*", // compiler diff --git a/test/test_bessel_j.hpp b/test/test_bessel_j.hpp index 33c150df48..3234769d02 100644 --- a/test/test_bessel_j.hpp +++ b/test/test_bessel_j.hpp @@ -288,6 +288,18 @@ void test_bessel(T, const char* name) BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j(364, T(38.5)), SC_(1.793940496519190500748409872348034004417458734118663909894e-309), tolerance); #endif // + // Integer order close to a zero of J0, where J0 can't be used to normalize the backward recurrence. + // The abscissas are doubles, so only test types that can represent them: + // + if (boost::math::tools::digits() >= 53) + { + T zero_tolerance = boost::math::tools::epsilon() * 20; + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j(10, T(8.6537237301984558)), SC_(0.0996158647456921646927721919213908589596019870131360940723049378983), zero_tolerance); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j(7, T(5.5200781102863106)), SC_(0.0881464684159767016952121525637257877790920066703460259556066159961), zero_tolerance); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j(12, T(11.791534439014281)), SC_(0.1795280373512378986489789702185521318452327344959779893506059462388), zero_tolerance); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j(9, T(8.6537279129110122)), SC_(0.1833532562916418433167901418287371987480602621047903858777232081307), zero_tolerance); + } + // // Special cases at infinity: // BOOST_IF_CONSTEXPR (std::numeric_limits::has_infinity) diff --git a/test/test_bessel_j_prime.cpp b/test/test_bessel_j_prime.cpp index d4641bbd48..8d79a41e30 100644 --- a/test/test_bessel_j_prime.cpp +++ b/test/test_bessel_j_prime.cpp @@ -38,7 +38,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } @@ -180,6 +180,8 @@ void expected_results() if((std::numeric_limits::digits != std::numeric_limits::digits) && (std::numeric_limits::digits < 90)) { + if (boost::math::policies::promote_double<>()) + { // some errors spill over into type double as well: add_expected_result( ".*", // compiler @@ -209,6 +211,7 @@ void expected_results() "double", // test type(s) ".*", // test data group ".*", 30, 30); // test function + } // // and we have a few cases with higher limits as well: // diff --git a/test/test_bessel_j_prime.hpp b/test/test_bessel_j_prime.hpp index ed9d53d69b..418a4cd54b 100644 --- a/test/test_bessel_j_prime.hpp +++ b/test/test_bessel_j_prime.hpp @@ -265,6 +265,20 @@ void test_bessel_prime(T, const char* name) BOOST_CHECK_EQUAL(boost::math::cyl_bessel_j_prime(T(-1), T(0)), T(-0.5)); BOOST_CHECK_EQUAL(boost::math::cyl_bessel_j_prime(T(2), T(0)), T(0)); + // + // The three term asymptotic expansion was used for x > 95 and v < 1, where it is only good to 1e4 eps, + // values from Arb as (J(v-1, x) - J(v+1, x)) / 2, the abscissas are doubles so we only test double: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + T large_x_tol = boost::math::tools::epsilon() * 20; + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j_prime(T(1.0007482056796131), T(113.87316017807642)), static_cast(0.0747696314057408945840436353080930202707L), large_x_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j_prime(T(0.3), T(150.5)), static_cast(0.0650254984322614707173842423734883453958L), large_x_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j_prime(T(0), T(120.75)), static_cast(-0.040227984996192229945874445912887161952L), large_x_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j_prime(T(2), T(250.25)), static_cast(-0.048437217713892677788514150828785684487L), large_x_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_j_prime(T(3.7), T(330.5)), static_cast(0.0146548919503718203861877942627449196684L), large_x_tol); + } + // // Special cases that are errors: // diff --git a/test/test_bessel_k.cpp b/test/test_bessel_k.cpp index 6053114585..4cbff48759 100644 --- a/test/test_bessel_k.cpp +++ b/test/test_bessel_k.cpp @@ -59,7 +59,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } @@ -134,6 +134,30 @@ BOOST_AUTO_TEST_CASE( test_main ) test_bessel(0.1F, "float"); #endif test_bessel(0.1, "double"); + + { + // https://github.com/boostorg/math/issues/1229 + // Force evaluation at double precision so extended long double + // evaluation does not mask underflow in the starting K values. + typedef boost::math::policies::policy< + boost::math::policies::promote_double > no_promote_policy; + const no_promote_policy pol; + const double tol = 256 * std::numeric_limits::epsilon(); + + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_k(1000, 747.0, pol), + 9.4914699277133192873957343540027064981e-66, tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_k(1000.25, 747.0, pol), + 1.2500811621640357229654772264173947351e-65, tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_k(-1000, 746.0, pol), + 5.0516775170486159420895532449059993901e-65, tol); + +#if !defined(BOOST_MATH_ENABLE_SYCL) + if (std::numeric_limits::has_denorm == std::denorm_present) + BOOST_CHECK_EQUAL(boost::math::cyl_bessel_k(100, 746.0, pol), + 8 * std::numeric_limits::denorm_min()); +#endif + } + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_bessel(0.1L, "long double"); #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS diff --git a/test/test_bessel_k_prime.cpp b/test/test_bessel_k_prime.cpp index 6d69268f85..a9e03d0387 100644 --- a/test/test_bessel_k_prime.cpp +++ b/test/test_bessel_k_prime.cpp @@ -43,7 +43,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } diff --git a/test/test_bessel_y.cpp b/test/test_bessel_y.cpp index 05d85b83bc..5600ba4b91 100644 --- a/test/test_bessel_y.cpp +++ b/test/test_bessel_y.cpp @@ -52,7 +52,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } @@ -202,7 +202,7 @@ void expected_results() ".*", 2000, 2000); // test function #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - BOOST_IF_CONSTEXPR((std::numeric_limits::digits != std::numeric_limits::digits) + BOOST_IF_CONSTEXPR(boost::math::policies::promote_double<>() && (std::numeric_limits::digits != std::numeric_limits::digits) && (std::numeric_limits::digits < 90)) { // some errors spill over into type double as well: @@ -221,7 +221,7 @@ void expected_results() ".*Yv.*", // test data group ".*", 80, 70); // test function } - else BOOST_IF_CONSTEXPR(std::numeric_limits::digits >= 90) + else BOOST_IF_CONSTEXPR(boost::math::policies::promote_double<>() && std::numeric_limits::digits >= 90) { add_expected_result( ".*", // compiler diff --git a/test/test_bessel_y_prime.cpp b/test/test_bessel_y_prime.cpp index 9848b63356..ccc1ea0a50 100644 --- a/test/test_bessel_y_prime.cpp +++ b/test/test_bessel_y_prime.cpp @@ -38,7 +38,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } @@ -112,13 +112,17 @@ void expected_results() // of the function means that 0.5ulp error in the input has a // non-zero output error. // Typical case is cyl_neumann_prime(8.5, boost::math::constants::pi() * 4); - add_expected_result( - ".*", // compiler - ".*", // stdlib - "linux", // platform - "double", // test type(s) - ".*", // test data group - ".*", 30, 20); // test function + // + // Unpromoted double gets the largest type rows below: the worst cases are ill-conditioned, + // e.g. Y'(-18, 31.618) at 620 eps has cond 2e4, Y'(-503.01, 8071.5) at 3e4 eps has cond 3e7. + if(boost::math::policies::promote_double<>()) + add_expected_result( + ".*", // compiler + ".*", // stdlib + "linux", // platform + "double", // test type(s) + ".*", // test data group + ".*", 30, 20); // test function add_expected_result( ".*", // compiler ".*", // stdlib @@ -220,7 +224,7 @@ void expected_results() ".*", 2000, 2000); // test function #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if((std::numeric_limits::digits != std::numeric_limits::digits) + if(boost::math::policies::promote_double<>() && (std::numeric_limits::digits != std::numeric_limits::digits) && (std::numeric_limits::digits < 90)) { // some errors spill over into type double as well: diff --git a/test/test_bessel_y_prime.hpp b/test/test_bessel_y_prime.hpp index aabb458b0b..46ae82219b 100644 --- a/test/test_bessel_y_prime.hpp +++ b/test/test_bessel_y_prime.hpp @@ -242,6 +242,19 @@ void test_bessel_prime(T, const char* name) } }; do_test_cyl_neumann_y_prime(yv_prime_coverage_data, name, "y': Extra coverage data"); } + // + // The three term asymptotic expansion was used for x > 95 and v < 1, where it is only good to 1e4 eps, + // values from Arb as (Y(v-1, x) - Y(v+1, x)) / 2, the abscissas are doubles so we only test double: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + T large_x_tol = boost::math::tools::epsilon() * 20; + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_neumann_prime(T(0.83333333333333337), T(109.0014391556391)), static_cast(0.0760449235630686830463871181005626524645L), large_x_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_neumann_prime(T(0.3), T(150.5)), static_cast(0.0013333757161545900983834743661673159689L), large_x_tol * 10); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_neumann_prime(T(0), T(120.75)), static_cast(0.0604488068298503912759500045186664470565L), large_x_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_neumann_prime(T(2), T(250.25)), static_cast(0.0140607640770331360026206679138142471927L), large_x_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_neumann_prime(T(3.7), T(330.5)), static_cast(-0.041368494497016115551472552645071817405L), large_x_tol); + } static const std::array, 1> sph_prime_coverage_data = { { // (SphericalBesselY[-1, 5/2] - (SphericalBesselY(0, 5/2)+5/2 * SphericalBesselY[1, 5/2])/(5/2))/2 {{ SC_(0.0), SC_(2.5), SC_(0.1112058791540732032473814343996886423728680128280382077091151343) }}, diff --git a/test/test_beta.cpp b/test/test_beta.cpp index ce56360a13..df1f6773fc 100644 --- a/test/test_beta.cpp +++ b/test/test_beta.cpp @@ -82,6 +82,23 @@ void expected_results() "(long\\s+)?double", // test type(s) "Beta Function: Divergent.*", // test data group "beta", 30, 6); // test function + // + // MinGW, where real_concept's 80-bit long double libm is less accurate (measured 368 and 55): + // + add_expected_result( + "GNU.*", // compiler + ".*", // stdlib + "Win32.*", // platform + "real_concept", // test type(s) + "Beta Function: Medium.*", // test data group + "beta", 400, 40); // test function + add_expected_result( + "GNU.*", // compiler + ".*", // stdlib + "Win32.*", // platform + "real_concept", // test type(s) + "Beta Function: Divergent.*", // test data group + "beta", 60, 15); // test function add_expected_result( ".*", // compiler ".*", // stdlib diff --git a/test/test_beta_dist.cpp b/test/test_beta_dist.cpp index 3983f526ff..801db52f58 100644 --- a/test/test_beta_dist.cpp +++ b/test/test_beta_dist.cpp @@ -624,6 +624,29 @@ void test_spots(RealType) } // template void test_spots(RealType) +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 45 digits: log(beta(a, b)) - (a-1) digamma(a) - (b-1) digamma(b) + (a+b-2) digamma(a+b). + // The large-parameter cases cancel catastrophically in that form. + RealType tol = 50 * boost::math::tools::epsilon(); + auto check = [&](long double a, long double b, long double h) + { + beta_distribution dist(static_cast(a), static_cast(b)); + BOOST_CHECK_CLOSE_FRACTION(entropy(dist), static_cast(h), tol); + }; + check(2.0L, 3.0L, -0.2349066497880003102297094798388788407985L); + check(0.5L, 0.5L, -0.2415644752704904446910368915632944245037L); + check(0.125L, 8.0L, -7.236093290136823717228800592217375034163L); + check(9.5L, 2.0L, -0.922951609703585681996556781537869432303L); + check(30.0L, 70.0L, -1.671603471334352932984107068683246070161L); + check(10.0L, 1000000.0L, -11.27947087941654488172437002583796804517L); + check(10000.0L, 10000.0L, -4.225977424873357422152240946297157538477L); + check(1000000.0L, 0.001L, -1006.482327533958828091847078424074949448L); + check(1e10L, 1e10L, -11.13370770263047364243672571920348908759L); + BOOST_CHECK_EQUAL(entropy(beta_distribution(1, 1)), RealType(0)); // Uniform. +} + BOOST_AUTO_TEST_CASE( test_main ) { BOOST_MATH_CONTROL_FP; @@ -718,10 +741,14 @@ BOOST_AUTO_TEST_CASE( test_main ) // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. test_spots(0.0); // Test double. + test_entropy(0.0F); + test_entropy(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. + test_entropy(0.0L); #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x582)) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #endif diff --git a/test/test_bezier_polynomial.cpp b/test/test_bezier_polynomial.cpp new file mode 100644 index 0000000000..6944a18e16 --- /dev/null +++ b/test/test_bezier_polynomial.cpp @@ -0,0 +1,274 @@ +/* + * Copyright Nick Thompson, 2021 + * 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) + */ + +#include +#ifndef BOOST_MATH_NO_THREAD_LOCAL_WITH_NON_TRIVIAL_TYPES +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#ifdef BOOST_HAS_FLOAT128 +#include +using boost::multiprecision::float128; +#endif + +#if __has_include() +# include +#endif + +using boost::math::interpolators::bezier_polynomial; + +template +void test_linear() +{ + std::vector> control_points(2); + control_points[0] = {Real(0), Real(0)}; + control_points[1] = {Real(1), Real(1)}; + auto control_points_copy = control_points; + auto bp = bezier_polynomial(std::move(control_points_copy)); + + // P(0) = P_0: + CHECK_ULP_CLOSE(control_points[0][0], bp(0)[0], 3); + CHECK_ULP_CLOSE(control_points[0][1], bp(0)[1], 3); + + // P(1) = P_n: + CHECK_ULP_CLOSE(control_points[1][0], bp(1)[0], 3); + CHECK_ULP_CLOSE(control_points[1][1], bp(1)[1], 3); + + for (Real t = Real(1)/32; t < 1; t += Real(1)/32) { + Real expected0 = (1-t)*control_points[0][0] + t*control_points[1][0]; + CHECK_ULP_CLOSE(expected0, bp(t)[0], 3); + } + + // P(1) = P_n: + std::array endpoint{1,2}; + bp.edit_control_point(endpoint, 1); + CHECK_ULP_CLOSE(endpoint[0], bp(1)[0], 3); + CHECK_ULP_CLOSE(endpoint[1], bp(1)[1], 3); + +} + +template +void test_quadratic() +{ + std::vector> control_points(3); + control_points[0] = {Real(0), Real(0)}; + control_points[1] = {Real(1), Real(1)}; + control_points[2] = {Real(2), Real(2)}; + auto control_points_copy = control_points; + auto bp = bezier_polynomial(std::move(control_points_copy)); + + // P(0) = P_0: + auto computed_point = bp(0); + CHECK_ULP_CLOSE(control_points[0][0], computed_point[0], 3); + CHECK_ULP_CLOSE(control_points[0][1], computed_point[1], 3); + auto computed_dp = bp.prime(0); + CHECK_ULP_CLOSE(2*(control_points[1][0] - control_points[0][0]), computed_dp[0], 3); + CHECK_ULP_CLOSE(2*(control_points[1][1] - control_points[0][1]), computed_dp[1], 3); + + // P(1) = P_n: + computed_point = bp(1); + CHECK_ULP_CLOSE(control_points[2][0], computed_point[0], 3); + CHECK_ULP_CLOSE(control_points[2][1], computed_point[1], 3); +} + +// All points on a Bezier polynomial fall into the convex hull of the control polygon. +template +void test_convex_hull() +{ + std::vector> control_points(4); + control_points[0] = {Real(0), Real(0)}; + control_points[1] = {Real(0), Real(1)}; + control_points[2] = {Real(1), Real(1)}; + control_points[3] = {Real(1), Real(0)}; + auto bp = bezier_polynomial(std::move(control_points)); + + for (Real t = 0; t <= 1; t += Real(1)/32) { + auto p = bp(t); + CHECK_LE(p[0], Real(1)); + CHECK_LE(Real(0), p[0]); + CHECK_LE(p[1], Real(1)); + CHECK_LE(Real(0), p[1]); + } +} + +// Reversal Symmetry: If q(t) is the Bezier polynomial which consumes the control points in reversed order from p(t), +// then p(t) = q(1-t). +template +void test_reversal_symmetry() +{ + std::vector> control_points(10); + std::uniform_real_distribution dis(-1,1); + std::mt19937_64 gen; + for (size_t i = 0; i < control_points.size(); ++i) { + for (size_t j = 0; j < 3; ++j) { + control_points[i][j] = dis(gen); + } + } + + auto control_points_copy = control_points; + auto bp0 = bezier_polynomial(std::move(control_points_copy)); + + control_points_copy = control_points; + std::reverse(control_points_copy.begin(), control_points_copy.end()); + auto bp1 = bezier_polynomial(std::move(control_points_copy)); + auto P0 = bp0(Real(0)); + CHECK_ULP_CLOSE(control_points[0][0], P0[0], 3); + CHECK_ULP_CLOSE(control_points[0][1], P0[1], 3); + CHECK_ULP_CLOSE(control_points[0][2], P0[2], 3); + auto P1 = bp0(Real(1)); + CHECK_ULP_CLOSE(control_points.back()[0], P1[0], 3); + CHECK_ULP_CLOSE(control_points.back()[1], P1[1], 3); + CHECK_ULP_CLOSE(control_points.back()[2], P1[2], 3); + + P0 = bp1(Real(1)); + CHECK_ULP_CLOSE(control_points[0][0], P0[0], 3); + CHECK_ULP_CLOSE(control_points[0][1], P0[1], 3); + CHECK_ULP_CLOSE(control_points[0][2], P0[2], 3); + + P1 = bp1(Real(0)); + CHECK_ULP_CLOSE(control_points.back()[0], P1[0], 3); + CHECK_ULP_CLOSE(control_points.back()[1], P1[1], 3); + CHECK_ULP_CLOSE(control_points.back()[2], P1[2], 3); + + for (Real t = 0; t <= 1; t += Real(1.0)) { + auto P0 = bp0(t); + auto P1 = bp1(Real(1.0)-t); + if (!CHECK_ULP_CLOSE(P0[0], P1[0], 3)) { + std::cerr << " Error at t = " << t << "\n"; + } + CHECK_ULP_CLOSE(P0[1], P1[1], 3); + CHECK_ULP_CLOSE(P0[2], P1[2], 3); + } +} + +// Linear precision: If all control points lie *equidistantly* on a line, then the Bezier curve falls on a line. +// See Bezier and B-spline techniques, Section 2.8, Remark 8. +template +void test_linear_precision() +{ + std::vector> control_points(10); + std::array P0 = {1,1,1}; + std::array Pf = {2,2,2}; + control_points[0] = P0; + control_points[9] = Pf; + for (size_t i = 1; i < 9; ++i) { + Real t = Real(i)/(control_points.size()-1); + control_points[i][0] = (1-t)*P0[0] + t*Pf[0]; + control_points[i][1] = (1-t)*P0[1] + t*Pf[1]; + control_points[i][2] = (1-t)*P0[2] + t*Pf[2]; + } + + auto bp = bezier_polynomial(std::move(control_points)); + for (Real t = 0; t < 1; t += Real(1)/32) { + std::array P; + P[0] = (1-t)*P0[0] + t*Pf[0]; + P[1] = (1-t)*P0[1] + t*Pf[1]; + P[2] = (1-t)*P0[2] + t*Pf[2]; + + auto computed = bp(t); + CHECK_ULP_CLOSE(P[0], computed[0], 4); + CHECK_ULP_CLOSE(P[1], computed[1], 4); + CHECK_ULP_CLOSE(P[2], computed[2], 4); + + std::array dP; + dP[0] = Pf[0] - P0[0]; + dP[1] = Pf[1] - P0[1]; + dP[2] = Pf[2] - P0[2]; + auto dpComputed = bp.prime(t); + CHECK_ULP_CLOSE(dP[0], dpComputed[0], 5); + } +} + +// The scratch space is thread_local, so a curve built on one thread must also be usable on others. +template +void test_other_threads() +{ + std::vector> control_points(7); + for (size_t i = 0; i < control_points.size(); ++i) { + control_points[i] = {Real(i), Real(i*i), Real(1)/Real(i + 1)}; + } + auto bp = bezier_polynomial(std::move(control_points)); + std::vector ts{Real(0), Real(0.125), Real(0.5), Real(0.75), Real(1)}; + std::vector> expected_p, expected_dp; + for (Real t : ts) { + expected_p.push_back(bp(t)); + expected_dp.push_back(bp.prime(t)); + } + // Evaluate on other threads, then check on this one: the checks themselves are not thread-safe. + std::vector>> computed_p(4), computed_dp(4); + std::vector threads; + for (size_t k = 0; k < computed_p.size(); ++k) { + threads.emplace_back([&, k]() { + for (Real t : ts) { + computed_p[k].push_back(bp(t)); + computed_dp[k].push_back(bp.prime(t)); + } + }); + } + for (auto& thread : threads) { + thread.join(); + } + for (size_t k = 0; k < computed_p.size(); ++k) { + for (size_t i = 0; i < ts.size(); ++i) { + for (size_t j = 0; j < 3; ++j) { + CHECK_EQUAL(expected_p[i][j], computed_p[k][i][j]); + CHECK_EQUAL(expected_dp[i][j], computed_dp[k][i][j]); + } + } + } +} + +int main() +{ + #ifdef __STDCPP_FLOAT32_T__ + test_linear(); + test_quadratic(); + test_convex_hull(); + test_linear_precision(); + test_reversal_symmetry(); + #else + test_linear(); + test_quadratic(); + test_convex_hull(); + test_linear_precision(); + test_reversal_symmetry(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_convex_hull(); + test_linear_precision(); + test_reversal_symmetry(); + #else + test_linear(); + test_quadratic(); + test_convex_hull(); + test_linear_precision(); + test_reversal_symmetry(); + #endif + test_other_threads(); + + #ifdef BOOST_HAS_FLOAT128 + test_linear(); + test_quadratic(); + test_convex_hull(); + #endif + + return boost::math::test::report_errors(); +} + +#else +int main() { + return 0; +} +#endif diff --git a/test/test_bezier_polynomial_module.cpp b/test/test_bezier_polynomial_module.cpp new file mode 100644 index 0000000000..eea9bbadd4 --- /dev/null +++ b/test/test_bezier_polynomial_module.cpp @@ -0,0 +1,142 @@ +// Copyright Nick Thompson, 2021 +// 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) +// +// Module build check for bezier_polynomial. Consuming the interpolator through +// `import boost.math;` confirms the exported class template and its +// operator()/prime/edit_control_point members resolve from a module consumer +// (along with the std::shared_ptr / std::array members they rely on). The +// assertions exercise only mathematically-certain Bezier properties: endpoint +// interpolation, the exact straight line produced by collinear equidistant +// control points, the degree-n endpoint derivative n*(P_1 - P_0), and the +// convex-hull bound. Expected values are taken from test_bezier_polynomial.cpp. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +using boost::math::interpolators::bezier_polynomial; + +// A Bezier polynomial with two control points is the straight segment +// P(t) = (1-t) P_0 + t P_1, and editing a control point moves the endpoint. +template +void test_linear(const char* type_name) +{ + std::cout << "Testing bezier_polynomial linear segment on type " << type_name << std::endl; + + std::vector> control_points(2); + control_points[0] = {Real(0), Real(0)}; + control_points[1] = {Real(1), Real(1)}; + auto control_points_copy = control_points; + auto bp = bezier_polynomial(std::move(control_points_copy)); + + // P(0) == P_0. + CHECK_ULP_CLOSE(control_points[0][0], bp(0)[0], 3); + CHECK_ULP_CLOSE(control_points[0][1], bp(0)[1], 3); + + // P(1) == P_1. + CHECK_ULP_CLOSE(control_points[1][0], bp(1)[0], 3); + CHECK_ULP_CLOSE(control_points[1][1], bp(1)[1], 3); + + // Interior points fall on the line P(t) = (t, t). 1/32 is dyadic, so the + // sampled t values are exact. + for (Real t = Real(1)/32; t < 1; t += Real(1)/32) + { + Real expected0 = (1 - t) * control_points[0][0] + t * control_points[1][0]; + CHECK_ULP_CLOSE(expected0, bp(t)[0], 3); + } + + // Editing the endpoint control point moves P(1) to the new point. + std::array endpoint {Real(1), Real(2)}; + bp.edit_control_point(endpoint, 1); + CHECK_ULP_CLOSE(endpoint[0], bp(1)[0], 3); + CHECK_ULP_CLOSE(endpoint[1], bp(1)[1], 3); +} + +// Three collinear, equidistant control points produce the straight segment +// from P_0 to P_2, so P(0) == P_0, P(1) == P_2, and P'(0) == 2 (P_1 - P_0). +template +void test_quadratic(const char* type_name) +{ + std::cout << "Testing bezier_polynomial quadratic on type " << type_name << std::endl; + + std::vector> control_points(3); + control_points[0] = {Real(0), Real(0)}; + control_points[1] = {Real(1), Real(1)}; + control_points[2] = {Real(2), Real(2)}; + auto control_points_copy = control_points; + auto bp = bezier_polynomial(std::move(control_points_copy)); + + // P(0) == P_0. + auto computed_point = bp(0); + CHECK_ULP_CLOSE(control_points[0][0], computed_point[0], 3); + CHECK_ULP_CLOSE(control_points[0][1], computed_point[1], 3); + + // P'(0) == n (P_1 - P_0) with degree n == 2. + auto computed_dp = bp.prime(0); + CHECK_ULP_CLOSE(2 * (control_points[1][0] - control_points[0][0]), computed_dp[0], 3); + CHECK_ULP_CLOSE(2 * (control_points[1][1] - control_points[0][1]), computed_dp[1], 3); + + // P(1) == P_2. + computed_point = bp(1); + CHECK_ULP_CLOSE(control_points[2][0], computed_point[0], 3); + CHECK_ULP_CLOSE(control_points[2][1], computed_point[1], 3); +} + +// Every point of a Bezier polynomial lies in the convex hull of its control +// polygon; here that hull is the unit square, and the endpoints are exact. +template +void test_convex_hull(const char* type_name) +{ + std::cout << "Testing bezier_polynomial convex hull on type " << type_name << std::endl; + + std::vector> control_points(4); + control_points[0] = {Real(0), Real(0)}; + control_points[1] = {Real(0), Real(1)}; + control_points[2] = {Real(1), Real(1)}; + control_points[3] = {Real(1), Real(0)}; + auto bp = bezier_polynomial(std::move(control_points)); + + // Endpoint interpolation: P(0) == (0,0), P(1) == (1,0). + auto p0 = bp(0); + CHECK_ULP_CLOSE(Real(0), p0[0], 3); + CHECK_ULP_CLOSE(Real(0), p0[1], 3); + auto p1 = bp(1); + CHECK_ULP_CLOSE(Real(1), p1[0], 3); + CHECK_ULP_CLOSE(Real(0), p1[1], 3); + + for (Real t = 0; t <= 1; t += Real(1)/32) + { + auto p = bp(t); + CHECK_LE(p[0], Real(1)); + CHECK_LE(Real(0), p[0]); + CHECK_LE(p[1], Real(1)); + CHECK_LE(Real(0), p[1]); + } +} + +int main() +{ + test_linear("float"); + test_linear("double"); + + test_quadratic("float"); + test_quadratic("double"); + + test_convex_hull("float"); + test_convex_hull("double"); + + return boost::math::test::report_errors(); +} diff --git a/test/bilinear_uniform_test.cpp b/test/test_bilinear_uniform.cpp similarity index 100% rename from test/bilinear_uniform_test.cpp rename to test/test_bilinear_uniform.cpp diff --git a/test/test_bilinear_uniform_module.cpp b/test/test_bilinear_uniform_module.cpp new file mode 100644 index 0000000000..7316c44246 --- /dev/null +++ b/test/test_bilinear_uniform_module.cpp @@ -0,0 +1,102 @@ +// Copyright Nick Thompson, 2021 +// 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) +// +// Module build check for bilinear_uniform. Exercises the exported interpolator +// through `import boost.math;` so that its templates (and the std::shared_ptr / +// std::vector members they rely on) resolve when the test is compiled against +// the boost.math named module. The assertions use only mathematically certain +// properties of bilinear interpolation: a constant field is reproduced +// everywhere, the interpolant reproduces its node values exactly, and bilinear +// interpolation is exact for functions of the form a + b*x + c*y + d*x*y. The +// unit-square expected values reuse the formula from test_bilinear_uniform.cpp. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif +#include "math_unit_test.hpp" + +using boost::math::interpolators::bilinear_uniform; + +template +void test_bilinear(const char* type_name) +{ + std::cout << "Testing bilinear_uniform on type " << type_name << std::endl; + + // A constant field is reproduced exactly at every query point. + { + const Real value = static_cast(1.5); + std::vector v(2 * 2, value); + auto ub = bilinear_uniform>(std::move(v), 2, 2); + CHECK_ULP_CLOSE(value, ub(static_cast(0), static_cast(0)), 0); + CHECK_ULP_CLOSE(value, ub(static_cast(0.5), static_cast(0.25)), 1); + CHECK_ULP_CLOSE(value, ub(static_cast(1), static_cast(1)), 0); + } + + // Unit square with corner values {1, 2, 3, 4} stored row major: + // f(x0 + i*dx, y0 + j*dy) lives at f[j*cols + i], so this is + // f[0]=1 at (0,0), f[1]=2 at (1,0), f[2]=3 at (0,1), f[3]=4 at (1,1). + // Expected values follow the unit-square bilinear formula used in + // test_bilinear_uniform.cpp: + // f(x,y) = v0*(1-x)*(1-y) + v1*x*(1-y) + v2*(1-x)*y + v3*x*y + { + std::vector v { static_cast(1), static_cast(2), + static_cast(3), static_cast(4) }; + auto ub = bilinear_uniform>(std::move(v), 2, 2); + + // Node reproduction at the four corners. + CHECK_ULP_CLOSE(static_cast(1), ub(static_cast(0), static_cast(0)), 0); + CHECK_ULP_CLOSE(static_cast(2), ub(static_cast(1), static_cast(0)), 0); + CHECK_ULP_CLOSE(static_cast(3), ub(static_cast(0), static_cast(1)), 0); + CHECK_ULP_CLOSE(static_cast(4), ub(static_cast(1), static_cast(1)), 0); + + // Center and edge midpoints (all dyadic, so bit-exact in practice). + CHECK_ULP_CLOSE(static_cast(2.5), ub(static_cast(0.5), static_cast(0.5)), 1); + CHECK_ULP_CLOSE(static_cast(1.5), ub(static_cast(0.5), static_cast(0)), 1); + CHECK_ULP_CLOSE(static_cast(3.5), ub(static_cast(0.5), static_cast(1)), 1); + CHECK_ULP_CLOSE(static_cast(2), ub(static_cast(0), static_cast(0.5)), 1); + CHECK_ULP_CLOSE(static_cast(3), ub(static_cast(1), static_cast(0.5)), 1); + + // Interior dyadic point (0.25, 0.75) -> 2.75. + CHECK_ULP_CLOSE(static_cast(2.75), ub(static_cast(0.25), static_cast(0.75)), 2); + } + + // Bilinear interpolation is exact for f(x,y) = 1 + 2x + 3y + 4xy. + // Sample it on a 3x3 unit grid (x,y in {0,1,2}); interior queries must + // reproduce f exactly. Node layout f[j*cols + i]: + // j=0: 1, 3, 5 j=1: 4, 10, 16 j=2: 7, 17, 27 + { + std::vector v { static_cast(1), static_cast(3), static_cast(5), + static_cast(4), static_cast(10), static_cast(16), + static_cast(7), static_cast(17), static_cast(27) }; + auto ub = bilinear_uniform>(std::move(v), 3, 3); + + // Node reproduction. + CHECK_ULP_CLOSE(static_cast(10), ub(static_cast(1), static_cast(1)), 0); + CHECK_ULP_CLOSE(static_cast(27), ub(static_cast(2), static_cast(2)), 0); + + // Interior points where bilinear interpolation reproduces f exactly. + CHECK_ULP_CLOSE(static_cast(4.5), ub(static_cast(0.5), static_cast(0.5)), 2); + CHECK_ULP_CLOSE(static_cast(8.5), ub(static_cast(1.5), static_cast(0.5)), 2); + CHECK_ULP_CLOSE(static_cast(9.5), ub(static_cast(0.5), static_cast(1.5)), 2); + CHECK_ULP_CLOSE(static_cast(17.5), ub(static_cast(1.5), static_cast(1.5)), 2); + } +} + +int main() +{ + test_bilinear("float"); + test_bilinear("double"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_binomial.cpp b/test/test_binomial.cpp index b76c8e03e4..edbfe55699 100644 --- a/test/test_binomial.cpp +++ b/test/test_binomial.cpp @@ -819,6 +819,15 @@ void test_spots(RealType T) check_out_of_range >(1, 1); // (All) valid constructor parameter values. + { + // The quantile is beyond 1/epsilon, where k + 1 == k: this must return, + // even on platforms where the value itself is inaccurate (see below). + using namespace boost::math::policies; + binomial_distribution > > up(9079765771874083840, 0.561815); + binomial_distribution > > down(9079765771874083840, 0.561815); + BOOST_CHECK(quantile(up, RealType(0.0365346)) >= 0); + BOOST_CHECK(quantile(down, RealType(0.0365346)) >= 0); + } #if !(defined(__clang__) && defined( __APPLE__)) // See bug reported here: https://github.com/boostorg/math/pull/1007 // @@ -836,6 +845,26 @@ void test_spots(RealType T) #endif } // template void test_spots(RealType) +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType b, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(entropy(binomial_distribution(a, b)), h, tol); + }; + check(static_cast(20.0L), static_cast(0.25L), static_cast(2.07287436578888442287876627787179281960353742L)); + check(static_cast(1.0L), static_cast(0.5L), static_cast(0.693147180559945309417232121458176568075500134L)); + check(static_cast(1000.0L), static_cast(0.5L), static_cast(4.17966890863526857777743155825925363260293286L)); + check(static_cast(1000000.0L), static_cast(0.125L), static_cast(7.22020691646115941001106073174051289066355791L)); + check(static_cast(1000000000.0L), static_cast(0.00000095367431640625L), static_cast(4.84901174228382418930529560338738967408482415L)); + check(static_cast(1000000000000.0L), static_cast(0.5L), static_cast(14.5413019106090015364710462597202929838925063L)); + BOOST_CHECK_EQUAL(entropy(binomial_distribution(10, 1)), RealType(0)); + BOOST_CHECK_EQUAL(entropy(binomial_distribution(0, 0.5)), RealType(0)); +} + BOOST_AUTO_TEST_CASE( test_main ) { BOOST_MATH_CONTROL_FP; @@ -850,17 +879,21 @@ BOOST_AUTO_TEST_CASE( test_main ) // (Parameter value, arbitrarily zero, only communicates the floating point type). #ifdef TEST_FLOAT test_spots(0.0F); // Test float. + test_entropy(0.0F); #endif #ifdef TEST_DOUBLE test_spots(0.0); // Test double. + test_entropy(0.0); #endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS #ifdef TEST_LDOUBLE test_spots(0.0L); // Test long double. + test_entropy(0.0L); #endif #if !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) #ifdef TEST_REAL_CONCEPT test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #endif #else diff --git a/test/test_binomial_coeff.cpp b/test/test_binomial_coeff.cpp index 552fcda946..3659da55ee 100644 --- a/test/test_binomial_coeff.cpp +++ b/test/test_binomial_coeff.cpp @@ -36,7 +36,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_bivariate_statistics.cpp b/test/test_bivariate_statistics.cpp new file mode 100644 index 0000000000..60682aabfe --- /dev/null +++ b/test/test_bivariate_statistics.cpp @@ -0,0 +1,658 @@ +/* + * (C) Copyright Nick Thompson 2018. + * (C) Copyright Matt Borland 2021. + * 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) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include + +using boost::multiprecision::cpp_bin_float_50; +using boost::multiprecision::cpp_complex_50; + +/* + * Test checklist: + * 1) Does it work with multiprecision? + * 2) Does it work with .cbegin()/.cend() if the data is not altered? + * 3) Does it work with ublas and std::array? (Checking Eigen and Armadillo will make the CI system really unhappy.) + * 4) Does it work with std::forward_list if a forward iterator is all that is required? + * 5) Does it work with complex data if complex data is sensible? + */ + +using boost::math::statistics::means_and_covariance; +using boost::math::statistics::covariance; + +#ifndef BOOST_NO_CXX17_HDR_EXECUTION +#include + +template +void test_covariance(ExecutionPolicy&& exec) +{ + std::cout << std::setprecision(std::numeric_limits::digits10+1); + Real tol = std::numeric_limits::epsilon(); + using std::abs; + + // Covariance of a single thing is zero: + std::array u1{8}; + std::array v1{17}; + std::tuple temp = means_and_covariance(exec, u1, v1); + Real mu_u1 = std::get<0>(temp); + Real mu_v1 = std::get<1>(temp); + Real cov1 = std::get<2>(temp); + + CHECK_LE(abs(cov1), tol); + CHECK_LE(abs(mu_u1 - 8), tol); + CHECK_LE(abs(mu_v1 - 17), tol); + + + std::array u2{8, 4}; + std::array v2{3, 7}; + temp = means_and_covariance(exec, u2, v2); + Real mu_u2 = std::get<0>(temp); + Real mu_v2 = std::get<1>(temp); + Real cov2 = std::get<2>(temp); + + CHECK_LE(abs(cov2+4), tol); + CHECK_LE(abs(mu_u2 - 6), tol); + CHECK_LE(abs(mu_v2 - 5), tol); + + std::vector u3{1,2,3}; + std::vector v3{1,1,1}; + + temp = means_and_covariance(exec, u3, v3); + Real mu_u3 = std::get<0>(temp); + Real mu_v3 = std::get<1>(temp); + Real cov3 = std::get<2>(temp); + + // Since v is constant, covariance(u,v) = 0 against everything any u: + CHECK_LE(abs(cov3), tol); + CHECK_LE(abs(mu_u3 - 2), tol); + CHECK_LE(abs(mu_v3 - 1), tol); + // Make sure we pull the correct symbol out of means_and_covariance: + cov3 = covariance(exec, u3, v3); + CHECK_LE(abs(cov3), tol); + + cov3 = covariance(exec, v3, u3); + // Covariance is symmetric: cov(u,v) = cov(v,u) + CHECK_LE(abs(cov3), tol); + + // cov(u,u) = sigma(u)^2: + cov3 = covariance(exec, u3, u3); + Real expected = Real(2)/Real(3); + + CHECK_LE(abs(cov3 - expected), tol); + + std::mt19937 gen(15); + // Can't template standard library on multiprecision, so use double and cast back: + std::uniform_real_distribution dis(-1.0, 1.0); + std::vector u(500); + std::vector v(500); + for(size_t i = 0; i < u.size(); ++i) + { + u[i] = (Real) dis(gen); + v[i] = (Real) dis(gen); + } + + Real mu_u = boost::math::statistics::mean(u); + Real mu_v = boost::math::statistics::mean(v); + Real sigma_u_sq = boost::math::statistics::variance(u); + Real sigma_v_sq = boost::math::statistics::variance(v); + + temp = means_and_covariance(exec, u, v); + Real mu_u_ = std::get<0>(temp); + Real mu_v_ = std::get<1>(temp); + Real cov_uv = std::get<2>(temp); + + CHECK_LE(abs(mu_u - mu_u_), tol); + CHECK_LE(abs(mu_v - mu_v_), tol); + + // Cauchy-Schwartz inequality: + CHECK_LE(cov_uv*cov_uv, sigma_u_sq*sigma_v_sq); + // cov(X, X) = sigma(X)^2: + Real cov_uu = covariance(exec, u, u); + CHECK_LE(abs(cov_uu - sigma_u_sq), tol); + Real cov_vv = covariance(exec, v, v); + CHECK_LE(abs(cov_vv - sigma_v_sq), tol); +} + +template +void test_integer_covariance(ExecutionPolicy&& exec) +{ + std::cout << std::setprecision(std::numeric_limits::digits10+1); + double tol = std::numeric_limits::epsilon(); + using std::abs; + + // Covariance of a single thing is zero: + std::array u1{8}; + std::array v1{17}; + std::tuple temp = means_and_covariance(exec, u1, v1); + double mu_u1 = std::get<0>(temp); + double mu_v1 = std::get<1>(temp); + double cov1 = std::get<2>(temp); + + CHECK_LE(abs(cov1), tol); + CHECK_LE(abs(mu_u1 - 8), tol); + CHECK_LE(abs(mu_v1 - 17), tol); + + + std::array u2{8, 4}; + std::array v2{3, 7}; + temp = means_and_covariance(exec, u2, v2); + double mu_u2 = std::get<0>(temp); + double mu_v2 = std::get<1>(temp); + double cov2 = std::get<2>(temp); + + CHECK_LE(abs(cov2+4), tol); + CHECK_LE(abs(mu_u2 - 6), tol); + CHECK_LE(abs(mu_v2 - 5), tol); + + std::vector u3{1,2,3}; + std::vector v3{1,1,1}; + + temp = means_and_covariance(exec, u3, v3); + double mu_u3 = std::get<0>(temp); + double mu_v3 = std::get<1>(temp); + double cov3 = std::get<2>(temp); + + // Since v is constant, covariance(u,v) = 0 against everything any u: + CHECK_LE(abs(cov3), tol); + CHECK_LE(abs(mu_u3 - 2), tol); + CHECK_LE(abs(mu_v3 - 1), tol); + // Make sure we pull the correct symbol out of means_and_covariance: + cov3 = covariance(exec, u3, v3); + CHECK_LE(abs(cov3), tol); + + cov3 = covariance(exec, v3, u3); + // Covariance is symmetric: cov(u,v) = cov(v,u) + CHECK_LE(abs(cov3), tol); + + // cov(u,u) = sigma(u)^2: + cov3 = covariance(exec, u3, u3); + double expected = double(2)/double(3); + + CHECK_LE(abs(cov3 - expected), tol); + + std::mt19937 gen(15); + // Can't template standard library on multiprecision, so use double and cast back: + std::uniform_real_distribution dis(-1.0, 1.0); + std::vector u(500); + std::vector v(500); + for(size_t i = 0; i < u.size(); ++i) + { + u[i] = (Z) dis(gen); + v[i] = (Z) dis(gen); + } + + double mu_u = boost::math::statistics::mean(u); + double mu_v = boost::math::statistics::mean(v); + double sigma_u_sq = boost::math::statistics::variance(u); + double sigma_v_sq = boost::math::statistics::variance(v); + + temp = means_and_covariance(exec, u, v); + double mu_u_ = std::get<0>(temp); + double mu_v_ = std::get<1>(temp); + double cov_uv = std::get<2>(temp); + + CHECK_LE(abs(mu_u - mu_u_), tol); + CHECK_LE(abs(mu_v - mu_v_), tol); + + // Cauchy-Schwartz inequality: + CHECK_LE(cov_uv*cov_uv, sigma_u_sq*sigma_v_sq); + // cov(X, X) = sigma(X)^2: + double cov_uu = covariance(exec, u, u); + CHECK_LE(abs(cov_uu - sigma_u_sq), tol); + double cov_vv = covariance(exec, v, v); + CHECK_LE(abs(cov_vv - sigma_v_sq), tol); +} + +template +void test_correlation_coefficient(ExecutionPolicy&& exec) +{ + using boost::math::statistics::correlation_coefficient; + using std::abs; + using std::sqrt; + + Real tol = std::numeric_limits::epsilon(); + std::vector u{1}; + std::vector v{1}; + Real rho_uv = correlation_coefficient(exec, u, v); + CHECK_NAN(rho_uv); + + u = {1,1}; + v = {1,1}; + rho_uv = correlation_coefficient(exec, u, v); + CHECK_NAN(rho_uv); + + u = {1, 2, 3}; + v = {1, 2, 3}; + rho_uv = correlation_coefficient(exec, u, v); + CHECK_LE(abs(rho_uv - 1), tol); + + u = {1, 2, 3}; + v = {-1, -2, -3}; + rho_uv = correlation_coefficient(exec, u, v); + CHECK_LE(abs(rho_uv + 1), tol); + + rho_uv = correlation_coefficient(exec, v, u); + CHECK_LE(abs(rho_uv + 1), tol); + + u = {1, 2, 3}; + v = {0, 0, 0}; + rho_uv = correlation_coefficient(exec, v, u); + CHECK_NAN(rho_uv); + + u = {1, 2, 3}; + v = {0, 0, 3}; + rho_uv = correlation_coefficient(exec, v, u); + // mu_u = 2, sigma_u^2 = 2/3, mu_v = 1, sigma_v^2 = 2, cov(u,v) = 1. + CHECK_LE(abs(rho_uv - sqrt(Real(3))/Real(2)), tol); +} + +template +void test_integer_correlation_coefficient(ExecutionPolicy&& exec) +{ + using boost::math::statistics::correlation_coefficient; + using std::abs; + using std::sqrt; + + double tol = std::numeric_limits::epsilon(); + std::vector u{1}; + std::vector v{1}; + double rho_uv = correlation_coefficient(exec, u, v); + CHECK_NAN(rho_uv); + + u = {1,1}; + v = {1,1}; + rho_uv = correlation_coefficient(exec, u, v); + CHECK_NAN(rho_uv); + + u = {1, 2, 3}; + v = {1, 2, 3}; + rho_uv = correlation_coefficient(exec, u, v); + CHECK_LE(abs(rho_uv - 1.0), tol); + + rho_uv = correlation_coefficient(exec, v, u); + CHECK_LE(abs(rho_uv - 1.0), tol); + + u = {1, 2, 3}; + v = {0, 0, 0}; + rho_uv = correlation_coefficient(exec, v, u); + CHECK_NAN(rho_uv); + + u = {1, 2, 3}; + v = {0, 0, 3}; + rho_uv = correlation_coefficient(exec, v, u); + // mu_u = 2, sigma_u^2 = 2/3, mu_v = 1, sigma_v^2 = 2, cov(u,v) = 1. + CHECK_LE(abs(rho_uv - sqrt(double(3))/double(2)), tol); +} + +void test_parallel_correlation_merge() +{ + using boost::math::statistics::correlation_coefficient; + // Exceed the parallel dispatch threshold, even on a two-thread machine. + std::vector u(65536); + std::vector v(u.size()); + for (std::size_t i = 0; i < u.size(); ++i) + { + u[i] = static_cast(i % 4); + v[i] = u[i] + static_cast((i / 4) % 4); + } + // Each pair of independent uniform values in {0, 1, 2, 3} occurs equally often. + // Var(u) = 5/4, Var(v) = 5/2, and Cov(u, v) = 5/4. + const double expected = 1 / std::sqrt(2.0); + const double tol = 1000 * std::numeric_limits::epsilon(); + CHECK_MOLLIFIED_CLOSE(expected, correlation_coefficient(std::execution::par, u, v), tol); + CHECK_MOLLIFIED_CLOSE(expected, correlation_coefficient(std::execution::par, v, u), tol); +} + +int main() +{ + test_covariance(std::execution::seq); + test_covariance(std::execution::par); + test_covariance(std::execution::seq); + test_covariance(std::execution::par); + test_covariance(std::execution::seq); + test_covariance(std::execution::par); + test_covariance(std::execution::seq); + test_covariance(std::execution::par); + + test_integer_covariance(std::execution::seq); + test_integer_covariance(std::execution::par); + test_integer_covariance(std::execution::seq); + test_integer_covariance(std::execution::par); + test_integer_covariance(std::execution::seq); + test_integer_covariance(std::execution::par); + test_integer_covariance(std::execution::seq); + test_integer_covariance(std::execution::par); + + test_correlation_coefficient(std::execution::seq); + test_correlation_coefficient(std::execution::par); + test_correlation_coefficient(std::execution::seq); + test_correlation_coefficient(std::execution::par); + test_correlation_coefficient(std::execution::seq); + test_correlation_coefficient(std::execution::par); + test_correlation_coefficient(std::execution::seq); + test_correlation_coefficient(std::execution::par); + test_parallel_correlation_merge(); + + test_integer_correlation_coefficient(std::execution::seq); + test_integer_correlation_coefficient(std::execution::par); + test_integer_correlation_coefficient(std::execution::seq); + test_integer_correlation_coefficient(std::execution::par); + test_integer_correlation_coefficient(std::execution::seq); + test_integer_correlation_coefficient(std::execution::par); + test_integer_correlation_coefficient(std::execution::seq); + test_integer_correlation_coefficient(std::execution::par); + + return boost::math::test::report_errors(); +} + +#else + +template +void test_covariance() +{ + std::cout << std::setprecision(std::numeric_limits::digits10+1); + Real tol = std::numeric_limits::epsilon(); + using std::abs; + + // Covariance of a single thing is zero: + std::array u1{8}; + std::array v1{17}; + std::tuple temp = means_and_covariance(u1, v1); + Real mu_u1 = std::get<0>(temp); + Real mu_v1 = std::get<1>(temp); + Real cov1 = std::get<2>(temp); + + CHECK_LE(abs(cov1), tol); + CHECK_LE(abs(mu_u1 - 8), tol); + CHECK_LE(abs(mu_v1 - 17), tol); + + + std::array u2{8, 4}; + std::array v2{3, 7}; + temp = means_and_covariance(u2, v2); + Real mu_u2 = std::get<0>(temp); + Real mu_v2 = std::get<1>(temp); + Real cov2 = std::get<2>(temp); + + CHECK_LE(abs(cov2+4), tol); + CHECK_LE(abs(mu_u2 - 6), tol); + CHECK_LE(abs(mu_v2 - 5), tol); + + std::vector u3{1,2,3}; + std::vector v3{1,1,1}; + + temp = means_and_covariance(u3, v3); + Real mu_u3 = std::get<0>(temp); + Real mu_v3 = std::get<1>(temp); + Real cov3 = std::get<2>(temp); + + // Since v is constant, covariance(u,v) = 0 against everything any u: + CHECK_LE(abs(cov3), tol); + CHECK_LE(abs(mu_u3 - 2), tol); + CHECK_LE(abs(mu_v3 - 1), tol); + // Make sure we pull the correct symbol out of means_and_covariance: + cov3 = covariance(u3, v3); + CHECK_LE(abs(cov3), tol); + + cov3 = covariance(v3, u3); + // Covariance is symmetric: cov(u,v) = cov(v,u) + CHECK_LE(abs(cov3), tol); + + // cov(u,u) = sigma(u)^2: + cov3 = covariance(u3, u3); + Real expected = Real(2)/Real(3); + + CHECK_LE(abs(cov3 - expected), tol); + + std::mt19937 gen(15); + // Can't template standard library on multiprecision, so use double and cast back: + std::uniform_real_distribution dis(-1.0, 1.0); + std::vector u(500); + std::vector v(500); + for(size_t i = 0; i < u.size(); ++i) + { + u[i] = (Real) dis(gen); + v[i] = (Real) dis(gen); + } + + Real mu_u = boost::math::statistics::mean(u); + Real mu_v = boost::math::statistics::mean(v); + Real sigma_u_sq = boost::math::statistics::variance(u); + Real sigma_v_sq = boost::math::statistics::variance(v); + + temp = means_and_covariance(u, v); + Real mu_u_ = std::get<0>(temp); + Real mu_v_ = std::get<1>(temp); + Real cov_uv = std::get<2>(temp); + + CHECK_LE(abs(mu_u - mu_u_), tol); + CHECK_LE(abs(mu_v - mu_v_), tol); + + // Cauchy-Schwartz inequality: + CHECK_LE(cov_uv*cov_uv, sigma_u_sq*sigma_v_sq); + // cov(X, X) = sigma(X)^2: + Real cov_uu = covariance(u, u); + CHECK_LE(abs(cov_uu - sigma_u_sq), tol); + Real cov_vv = covariance(v, v); + CHECK_LE(abs(cov_vv - sigma_v_sq), tol); +} + +template +void test_integer_covariance() +{ + std::cout << std::setprecision(std::numeric_limits::digits10+1); + double tol = std::numeric_limits::epsilon(); + using std::abs; + + // Covariance of a single thing is zero: + std::array u1{8}; + std::array v1{17}; + std::tuple temp = means_and_covariance(u1, v1); + double mu_u1 = std::get<0>(temp); + double mu_v1 = std::get<1>(temp); + double cov1 = std::get<2>(temp); + + CHECK_LE(abs(cov1), tol); + CHECK_LE(abs(mu_u1 - 8), tol); + CHECK_LE(abs(mu_v1 - 17), tol); + + + std::array u2{8, 4}; + std::array v2{3, 7}; + temp = means_and_covariance(u2, v2); + double mu_u2 = std::get<0>(temp); + double mu_v2 = std::get<1>(temp); + double cov2 = std::get<2>(temp); + + CHECK_LE(abs(cov2+4), tol); + CHECK_LE(abs(mu_u2 - 6), tol); + CHECK_LE(abs(mu_v2 - 5), tol); + + std::vector u3{1,2,3}; + std::vector v3{1,1,1}; + + temp = means_and_covariance(u3, v3); + double mu_u3 = std::get<0>(temp); + double mu_v3 = std::get<1>(temp); + double cov3 = std::get<2>(temp); + + // Since v is constant, covariance(u,v) = 0 against everything any u: + CHECK_LE(abs(cov3), tol); + CHECK_LE(abs(mu_u3 - 2), tol); + CHECK_LE(abs(mu_v3 - 1), tol); + // Make sure we pull the correct symbol out of means_and_covariance: + cov3 = covariance(u3, v3); + CHECK_LE(abs(cov3), tol); + + cov3 = covariance(v3, u3); + // Covariance is symmetric: cov(u,v) = cov(v,u) + CHECK_LE(abs(cov3), tol); + + // cov(u,u) = sigma(u)^2: + cov3 = covariance(u3, u3); + double expected = double(2)/double(3); + + CHECK_LE(abs(cov3 - expected), tol); + + std::mt19937 gen(15); + // Can't template standard library on multiprecision, so use double and cast back: + std::uniform_real_distribution dis(-1.0, 1.0); + std::vector u(500); + std::vector v(500); + for(size_t i = 0; i < u.size(); ++i) + { + u[i] = (Z) dis(gen); + v[i] = (Z) dis(gen); + } + + double mu_u = boost::math::statistics::mean(u); + double mu_v = boost::math::statistics::mean(v); + double sigma_u_sq = boost::math::statistics::variance(u); + double sigma_v_sq = boost::math::statistics::variance(v); + + temp = means_and_covariance(u, v); + double mu_u_ = std::get<0>(temp); + double mu_v_ = std::get<1>(temp); + double cov_uv = std::get<2>(temp); + + CHECK_LE(abs(mu_u - mu_u_), tol); + CHECK_LE(abs(mu_v - mu_v_), tol); + + // Cauchy-Schwartz inequality: + CHECK_LE(cov_uv*cov_uv, sigma_u_sq*sigma_v_sq); + // cov(X, X) = sigma(X)^2: + double cov_uu = covariance(u, u); + CHECK_LE(abs(cov_uu - sigma_u_sq), tol); + double cov_vv = covariance(v, v); + CHECK_LE(abs(cov_vv - sigma_v_sq), tol); +} + +template +void test_correlation_coefficient() +{ + using boost::math::statistics::correlation_coefficient; + using std::abs; + using std::sqrt; + + Real tol = std::numeric_limits::epsilon(); + std::vector u{1}; + std::vector v{1}; + Real rho_uv = correlation_coefficient(u, v); + CHECK_NAN(rho_uv); + + u = {1,1}; + v = {1,1}; + rho_uv = correlation_coefficient(u, v); + CHECK_NAN(rho_uv); + + u = {1, 2, 3}; + v = {1, 2, 3}; + rho_uv = correlation_coefficient(u, v); + CHECK_LE(abs(rho_uv - 1), tol); + + u = {1, 2, 3}; + v = {-1, -2, -3}; + rho_uv = correlation_coefficient(u, v); + CHECK_LE(abs(rho_uv + 1), tol); + + rho_uv = correlation_coefficient(v, u); + CHECK_LE(abs(rho_uv + 1), tol); + + u = {1, 2, 3}; + v = {0, 0, 0}; + rho_uv = correlation_coefficient(v, u); + CHECK_NAN(rho_uv); + + u = {1, 2, 3}; + v = {0, 0, 3}; + rho_uv = correlation_coefficient(v, u); + // mu_u = 2, sigma_u^2 = 2/3, mu_v = 1, sigma_v^2 = 2, cov(u,v) = 1. + CHECK_LE(abs(rho_uv - sqrt(Real(3))/Real(2)), tol); +} + +template +void test_integer_correlation_coefficient() +{ + using boost::math::statistics::correlation_coefficient; + using std::abs; + using std::sqrt; + + double tol = std::numeric_limits::epsilon(); + std::vector u{1}; + std::vector v{1}; + double rho_uv = correlation_coefficient(u, v); + CHECK_NAN(rho_uv); + + u = {1,1}; + v = {1,1}; + rho_uv = correlation_coefficient(u, v); + CHECK_NAN(rho_uv); + + u = {1, 2, 3}; + v = {1, 2, 3}; + rho_uv = correlation_coefficient(u, v); + CHECK_LE(abs(rho_uv - 1.0), tol); + + rho_uv = correlation_coefficient(v, u); + CHECK_LE(abs(rho_uv - 1.0), tol); + + u = {1, 2, 3}; + v = {0, 0, 0}; + rho_uv = correlation_coefficient(v, u); + CHECK_NAN(rho_uv); + + u = {1, 2, 3}; + v = {0, 0, 3}; + rho_uv = correlation_coefficient(v, u); + // mu_u = 2, sigma_u^2 = 2/3, mu_v = 1, sigma_v^2 = 2, cov(u,v) = 1. + CHECK_LE(abs(rho_uv - sqrt(double(3))/double(2)), tol); +} + +int main() +{ + test_covariance(); + test_covariance(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_covariance(); +#endif + test_covariance(); + + test_integer_covariance(); + test_integer_covariance(); + test_integer_covariance(); + test_integer_covariance(); + + test_correlation_coefficient(); + test_correlation_coefficient(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_correlation_coefficient(); +#endif + test_correlation_coefficient(); + + test_integer_correlation_coefficient(); + test_integer_correlation_coefficient(); + test_integer_correlation_coefficient(); + test_integer_correlation_coefficient(); + + return boost::math::test::report_errors(); +} + +#endif diff --git a/test/test_bivariate_statistics_module.cpp b/test/test_bivariate_statistics_module.cpp new file mode 100644 index 0000000000..9fb3ac030d --- /dev/null +++ b/test/test_bivariate_statistics_module.cpp @@ -0,0 +1,119 @@ +/* + * (C) Copyright Nick Thompson 2018. + * (C) Copyright Matt Borland 2021. + * 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) + * + * Module build check for boost::math::statistics::means_and_covariance, + * covariance and correlation_coefficient. It exercises the exported entry + * points when the test is built against the boost.math module. The double and + * float expected values mirror the assertions in test_bivariate_statistics.cpp. + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#endif +#include "math_unit_test.hpp" + +// means_and_covariance returns (mean_u, mean_v, covariance); covariance() pulls +// out the third element. All expected values below are exact for these inputs. +template +void test_covariance() +{ + using boost::math::statistics::means_and_covariance; + using boost::math::statistics::covariance; + + const Real tol = std::numeric_limits::epsilon(); + + // Covariance of a single element is zero; the means are the elements themselves. + std::vector u1{static_cast(8)}; + std::vector v1{static_cast(17)}; + auto temp = means_and_covariance(u1, v1); + CHECK_ABSOLUTE_ERROR(static_cast(8), std::get<0>(temp), tol); + CHECK_ABSOLUTE_ERROR(static_cast(17), std::get<1>(temp), tol); + CHECK_ABSOLUTE_ERROR(static_cast(0), std::get<2>(temp), tol); + + // u = {8,4}, v = {3,7}: mean_u = 6, mean_v = 5, covariance = -4. + std::vector u2{static_cast(8), static_cast(4)}; + std::vector v2{static_cast(3), static_cast(7)}; + temp = means_and_covariance(u2, v2); + CHECK_ABSOLUTE_ERROR(static_cast(6), std::get<0>(temp), tol); + CHECK_ABSOLUTE_ERROR(static_cast(5), std::get<1>(temp), tol); + CHECK_ABSOLUTE_ERROR(static_cast(-4), std::get<2>(temp), tol); + + // v is constant, so cov(u,v) = 0 for any u; mean_u = 2, mean_v = 1. + std::vector u3{static_cast(1), static_cast(2), static_cast(3)}; + std::vector v3{static_cast(1), static_cast(1), static_cast(1)}; + temp = means_and_covariance(u3, v3); + CHECK_ABSOLUTE_ERROR(static_cast(2), std::get<0>(temp), tol); + CHECK_ABSOLUTE_ERROR(static_cast(1), std::get<1>(temp), tol); + CHECK_ABSOLUTE_ERROR(static_cast(0), std::get<2>(temp), tol); + + // covariance() must agree with the third tuple element. + CHECK_ABSOLUTE_ERROR(static_cast(0), covariance(u3, v3), tol); + // Covariance is symmetric: cov(v,u) = cov(u,v). + CHECK_ABSOLUTE_ERROR(static_cast(0), covariance(v3, u3), tol); + // cov(u,u) = variance(u) = 2/3 for {1,2,3}. + CHECK_ABSOLUTE_ERROR(static_cast(2) / static_cast(3), covariance(u3, u3), tol); +} + +// correlation_coefficient returns rho in [-1, 1], or NaN when a sample is constant. +template +void test_correlation_coefficient() +{ + using boost::math::statistics::correlation_coefficient; + + const Real tol = std::numeric_limits::epsilon(); + + // A single sample has an undefined correlation coefficient. + std::vector a{static_cast(1)}; + std::vector b{static_cast(1)}; + CHECK_NAN(correlation_coefficient(a, b)); + + // Two constant samples are likewise undefined. + std::vector u{static_cast(1), static_cast(1)}; + std::vector v{static_cast(1), static_cast(1)}; + CHECK_NAN(correlation_coefficient(u, v)); + + // Perfectly correlated data: rho = 1. + u = {static_cast(1), static_cast(2), static_cast(3)}; + v = {static_cast(1), static_cast(2), static_cast(3)}; + CHECK_ABSOLUTE_ERROR(static_cast(1), correlation_coefficient(u, v), tol); + + // Perfectly anti-correlated data: rho = -1, and rho is symmetric in its arguments. + u = {static_cast(1), static_cast(2), static_cast(3)}; + v = {static_cast(-1), static_cast(-2), static_cast(-3)}; + CHECK_ABSOLUTE_ERROR(static_cast(-1), correlation_coefficient(u, v), tol); + CHECK_ABSOLUTE_ERROR(static_cast(-1), correlation_coefficient(v, u), tol); + + // One constant dataset => correlation is undefined. + u = {static_cast(1), static_cast(2), static_cast(3)}; + v = {static_cast(0), static_cast(0), static_cast(0)}; + CHECK_NAN(correlation_coefficient(v, u)); + + // v = {0,0,3} against u = {1,2,3}: rho = sqrt(3)/2. + u = {static_cast(1), static_cast(2), static_cast(3)}; + v = {static_cast(0), static_cast(0), static_cast(3)}; + CHECK_ABSOLUTE_ERROR(std::sqrt(static_cast(3)) / static_cast(2), correlation_coefficient(v, u), tol); +} + +int main() +{ + test_covariance(); + test_correlation_coefficient(); + + test_covariance(); + test_correlation_coefficient(); + + return boost::math::test::report_errors(); +} diff --git a/test/cardinal_b_spline_test.cpp b/test/test_cardinal_b_spline.cpp similarity index 100% rename from test/cardinal_b_spline_test.cpp rename to test/test_cardinal_b_spline.cpp diff --git a/test/test_cardinal_cubic_b_spline.cpp b/test/test_cardinal_cubic_b_spline.cpp new file mode 100644 index 0000000000..63cd0fa726 --- /dev/null +++ b/test/test_cardinal_cubic_b_spline.cpp @@ -0,0 +1,435 @@ +// Copyright Nick Thompson, 2017 +// 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) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "math_unit_test.hpp" + +#if __has_include() +# include +#endif + +using std::sin; +using std::abs; +using boost::multiprecision::cpp_bin_float_50; +using boost::math::constants::third; +using boost::math::constants::half; + +template +void test_b3_spline() +{ + std::cout << "Testing evaluation of spline basis functions on type " << boost::typeindex::type_id().pretty_name() << "\n"; + // Outside the support: + Real eps = std::numeric_limits::epsilon(); + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline(Real(2.5)), Real(0)); + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline(Real(-2.5)), Real(0)); + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline_prime(Real(2.5)), Real(0)); + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline_prime(Real(-2.5)), Real(0)); + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline_double_prime(Real(2.5)), Real(0)); + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline_double_prime(Real(-2.5)), Real(0)); + + + // On the boundary of support: + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline(2), Real(0)); + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline(-2), Real(0)); + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline_prime(2), Real(0)); + CHECK_EQUAL(boost::math::interpolators::detail::b3_spline_prime(-2), Real(0)); + + // Special values: + CHECK_ULP_CLOSE(third()*half(), boost::math::interpolators::detail::b3_spline(-1), 0); + CHECK_ULP_CLOSE(third()*half(), boost::math::interpolators::detail::b3_spline( 1), 0); + CHECK_ULP_CLOSE(2*third(), boost::math::interpolators::detail::b3_spline(0), 0); + + CHECK_ULP_CLOSE(half(), boost::math::interpolators::detail::b3_spline_prime(-1), 0); + CHECK_ULP_CLOSE(-half(), boost::math::interpolators::detail::b3_spline_prime( 1), 0); + CHECK_ABSOLUTE_ERROR(0, boost::math::interpolators::detail::b3_spline_prime(0), eps); + + // Properties: B3 is an even function, B3' is an odd function. + for (size_t i = 1; i < 200; ++i) + { + Real arg = i*Real(0.01); + CHECK_ULP_CLOSE(boost::math::interpolators::detail::b3_spline(arg), boost::math::interpolators::detail::b3_spline(-arg), 0); + CHECK_ULP_CLOSE(-boost::math::interpolators::detail::b3_spline_prime(arg), boost::math::interpolators::detail::b3_spline_prime(-arg), 0); + CHECK_ULP_CLOSE(boost::math::interpolators::detail::b3_spline_double_prime(arg), boost::math::interpolators::detail::b3_spline_double_prime(-arg), 0); + } + +} +/* + * This test ensures that the interpolant s(x_j) = f(x_j) at all grid points. + */ +template +void test_interpolation_condition() +{ + using std::sqrt; + std::cout << "Testing interpolation condition for cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; + std::random_device rd; + std::mt19937 gen(rd()); + boost::random::uniform_real_distribution dis(1, 10); + std::vector v(5000); + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = dis(gen); + } + + Real step = static_cast(0.01); + Real a = Real(5); + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), a, step); + + for (size_t i = 0; i < v.size(); ++i) + { + Real y = spline(i*step + a); + // This seems like a very large tolerance, but I don't know of any other interpolators + // that will be able to do much better on random data. + CHECK_ABSOLUTE_ERROR(v[i], y, Real(100*(sqrt(std::numeric_limits::epsilon()))*abs(v[i]))); + } + +} + + +template +void test_constant_function() +{ + std::cout << "Testing that constants are interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; + std::vector v(500); + const Real constant = Real(50.2); + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = constant; + } + + Real step = static_cast(0.02); + Real a = 5; + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), a, step); + + for (size_t i = 0; i < v.size(); ++i) + { + // Do not test at interpolation point; we already know it works there: + Real y = spline(i*step + a + Real(0.001)); + CHECK_ULP_CLOSE(constant, y, 0); + Real y_prime = spline.prime(i*step + a + Real(0.002)); + CHECK_ABSOLUTE_ERROR(0, y_prime, 5000*std::numeric_limits::epsilon()); + Real y_double_prime = spline.double_prime(i*step + a + Real(0.002)); + CHECK_ABSOLUTE_ERROR(0, y_double_prime, 5000*std::numeric_limits::epsilon()); + + } + + // Test that correctly specified left and right-derivatives work properly: + spline = boost::math::interpolators::cardinal_cubic_b_spline(v.data(), v.size(), a, step, 0, 0); + + for (size_t i = 0; i < v.size(); ++i) + { + Real y = spline(i*step + a + Real(0.002)); + CHECK_ULP_CLOSE(constant, y, 0); + Real y_prime = spline.prime(i*step + a + Real(0.002)); + CHECK_ABSOLUTE_ERROR(0, y_prime, std::numeric_limits::epsilon()); + } + + // + // Again with iterator constructor: + // + boost::math::interpolators::cardinal_cubic_b_spline spline2(v.begin(), v.end(), a, step); + + for (size_t i = 0; i < v.size(); ++i) + { + // Do not test at interpolation point; we already know it works there: + Real y = spline2(i*step + a + Real(0.001)); + CHECK_ULP_CLOSE(constant, y, 0); + Real y_prime = spline2.prime(i*step + a + Real(0.002)); + CHECK_ABSOLUTE_ERROR(0, y_prime, 5000 * std::numeric_limits::epsilon()); + } + + // Test that correctly specified left and right-derivatives work properly: + spline2 = boost::math::interpolators::cardinal_cubic_b_spline(v.begin(), v.end(), a, step, 0, 0); + + for (size_t i = 0; i < v.size(); ++i) + { + Real y = spline2(i*step + a + Real(0.002)); + CHECK_ULP_CLOSE(constant, y, 0); + Real y_prime = spline2.prime(i*step + a + Real(0.002)); + CHECK_ABSOLUTE_ERROR(0, y_prime, std::numeric_limits::epsilon()); + } +} + + +template +void test_affine_function() +{ + using std::sqrt; + std::cout << "Testing that affine functions are interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; + std::vector v(500); + Real a = 10; + Real b = 8; + Real step = static_cast(0.005); + + auto f = [a, b](Real x) { return a*x + b; }; + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = f(i*step); + } + + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), 0, step); + + for (size_t i = 0; i < v.size() - 1; ++i) + { + Real arg = static_cast(i*step + Real(0.0001)); + Real y = spline(arg); + CHECK_ABSOLUTE_ERROR(f(arg), y, Real((sqrt(std::numeric_limits::epsilon()))/100*abs(f(arg)))); + Real y_prime = spline.prime(arg); + CHECK_ABSOLUTE_ERROR(a, y_prime, Real((sqrt(std::numeric_limits::epsilon()))*abs(a))); + } + + // Test that correctly specified left and right-derivatives work properly: + spline = boost::math::interpolators::cardinal_cubic_b_spline(v.data(), v.size(), 0, step, a, a); + + for (size_t i = 0; i < v.size() - 1; ++i) + { + Real arg = static_cast(i*step + Real(0.0001)); + Real y = spline(arg); + CHECK_ABSOLUTE_ERROR(f(arg), y, Real((sqrt(std::numeric_limits::epsilon()))/100*abs(f(arg)))); + Real y_prime = spline.prime(arg); + CHECK_ABSOLUTE_ERROR(a, y_prime, Real((sqrt(std::numeric_limits::epsilon()))*abs(a))); + } +} + + +template +void test_quadratic_function() +{ + using std::sqrt; + std::cout << "Testing that quadratic functions are interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; + std::vector v(500); + Real a = static_cast(1.2); + Real b = static_cast(-3.4); + Real c = static_cast(-8.6); + Real step = static_cast(0.01); + + auto f = [a, b, c](Real x) { return a*x*x + b*x + c; }; + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = f(i*step); + } + + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), 0, step); + + for (size_t i = 0; i < v.size() -1; ++i) + { + Real arg = static_cast(i*step + Real(0.001)); + Real y = spline(arg); + CHECK_ABSOLUTE_ERROR(f(arg), y, Real(0.001*abs(f(arg)))); + Real y_prime = spline.prime(arg); + CHECK_ABSOLUTE_ERROR(2*a*arg + b, y_prime, Real(0.02*abs(2*a*arg + b))); + } +} + + +template +void test_circ_conic_function() +{ + using std::sqrt; + std::cout << "Testing that conic section of a circle is interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << '\n'; + std::vector v(500); + Real cv = Real(0.1); + Real w = Real(2.0); + Real step = Real(2 * w / (v.size() - 1)); + + auto f = [cv](Real x) { return cv * x * x / (1 + sqrt(1 - cv * cv * x * x)); }; + auto df = [cv](Real x) { return cv * x / sqrt(1 - cv * cv * x * x); }; + + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = f(-w + i * step); + } + + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), -w, step); + + Real tol = 100 * sqrt(std::numeric_limits::epsilon()); + if ((std::numeric_limits::digits > 100) || !std::numeric_limits::digits) + tol *= 500000; + // First check derivatives exactly at end points + CHECK_ABSOLUTE_ERROR(df(-w), spline.prime(-w), Real(tol/100*abs(df(-w)))); + CHECK_ABSOLUTE_ERROR(df(w), spline.prime(w), Real(tol/100*abs(df(w)))); + + for (size_t i = 0; i < v.size() - 1; ++i) + { + Real arg = -w + i * step + Real(0.001); + Real y = spline(arg); + CHECK_ABSOLUTE_ERROR(f(arg), y, Real(0.02*abs(f(arg)))); + Real y_prime = spline.prime(arg); + CHECK_ABSOLUTE_ERROR(df(arg), y_prime, Real(0.01*abs(df(arg)))); + } +} + + +template +void test_trig_function() +{ + std::cout << "Testing that sine functions are interpolated correctly by cubic b splines on type " << boost::typeindex::type_id().pretty_name() << "\n"; + std::mt19937 gen; + std::vector v(500); + Real x0 = 1; + Real step = Real(0.125); + + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = sin(x0 + step * i); + } + + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), x0, step); + + boost::random::uniform_real_distribution abscissa(x0, x0 + 499 * step); + + for (size_t i = 0; i < v.size(); ++i) + { + Real x = abscissa(gen); + Real y = spline(x); + CHECK_ABSOLUTE_ERROR(Real(sin(x)), y, Real(0.01*abs(Real(sin(x))))); + auto y_prime = spline.prime(x); + CHECK_ABSOLUTE_ERROR(Real(cos(x)), y_prime, Real(0.02*abs(Real(cos(x))))); + } +} + +template +void test_copy_move() +{ + std::cout << "Testing that copy/move operation succeed on cubic b spline\n"; + std::vector v(500); + Real x0 = 1; + Real step = static_cast(0.125); + constexpr Real tol = Real(0.01); + + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = sin(x0 + step * i); + } + + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), x0, step); + + + // Default constructor should compile so that splines can be member variables: + boost::math::interpolators::cardinal_cubic_b_spline d; + d = boost::math::interpolators::cardinal_cubic_b_spline(v.data(), v.size(), x0, step); + CHECK_ABSOLUTE_ERROR(Real(sin(x0)), d(x0), Real(tol/100*abs(Real(sin(x0))))); + // Passing to lambda should compile: + auto f = [=](Real x) { return d(x); }; + // Make sure this variable is used. + CHECK_ABSOLUTE_ERROR(Real(sin(x0)), f(x0), Real(tol/100*abs(Real(sin(x0))))); + + // Move operations should compile. + auto s = std::move(spline); + + // Copy operations should compile: + boost::math::interpolators::cardinal_cubic_b_spline c = d; + CHECK_ABSOLUTE_ERROR(Real(sin(x0)), c(x0), Real(tol/100*abs(Real(sin(x0))))); + + // Test with std::bind: + auto h = std::bind(&boost::math::interpolators::cardinal_cubic_b_spline::operator(), &s, std::placeholders::_1); + CHECK_ABSOLUTE_ERROR(Real(sin(x0)), h(x0), Real(tol/100*abs(Real(sin(x0))))); +} + +template +void test_outside_interval() +{ + std::cout << "Testing that the spline can be evaluated outside the interpolation interval\n"; + std::vector v(400); + Real x0 = 1; + Real step = Real(0.125); + + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = sin(x0 + step * i); + } + + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), x0, step); + + // There's no test here; it simply does it's best to be an extrapolator. + // + std::ostream cnull(0); + cnull << spline(0); + cnull << spline(2000); +} + +void test_cubic_b_spline() +{ + #ifdef __STDCPP_FLOAT32_T__ + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_circ_conic_function(); + test_trig_function(); + + #else + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_circ_conic_function(); + test_trig_function(); + + #endif + + #ifdef __STDCPP_FLOAT64_T__ + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_circ_conic_function(); + test_trig_function(); + test_copy_move(); + test_outside_interval(); + + #else + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_circ_conic_function(); + test_trig_function(); + test_copy_move(); + test_outside_interval(); + + #endif + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_circ_conic_function(); + test_trig_function(); + + #endif + + test_b3_spline(); + test_interpolation_condition(); + test_constant_function(); + test_affine_function(); + test_quadratic_function(); + test_trig_function(); +} + +int main() +{ + test_cubic_b_spline(); + return boost::math::test::report_errors(); +} diff --git a/test/test_cardinal_cubic_b_spline_module.cpp b/test/test_cardinal_cubic_b_spline_module.cpp new file mode 100644 index 0000000000..be3d3ef720 --- /dev/null +++ b/test/test_cardinal_cubic_b_spline_module.cpp @@ -0,0 +1,126 @@ +// Copyright Nick Thompson, 2017 +// 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) +// +// Module build check for cardinal_cubic_b_spline. Consuming the interpolator +// through `import boost.math;` confirms the exported class template and its +// operator()/prime/double_prime members are usable from a module consumer. +// The assertions below exercise only mathematically-certain spline properties +// (node reproduction, exact reproduction of constants and affine functions), +// with expected values taken from test_cardinal_cubic_b_spline.cpp. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#endif + +// s(x_j) == f(x_j) at every node: the defining interpolation condition, which +// holds regardless of the endpoint-derivative choice. +template +void test_interpolation_condition(const char* type_name) +{ + std::cout << "Testing cardinal_cubic_b_spline interpolation condition for type " << type_name << std::endl; + + using std::sin; + + const Real x0 {static_cast(1)}; + const Real step {static_cast(0.125)}; + + std::vector v(20); + for (std::size_t i {0}; i < v.size(); ++i) + { + v[i] = sin(x0 + step * static_cast(i)); + } + + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), x0, step); + + for (std::size_t i {0}; i < v.size(); ++i) + { + const Real y {spline(x0 + step * static_cast(i))}; + CHECK_ULP_CLOSE(v[i], y, 64); + } +} + +// Constants are reproduced exactly and their derivatives vanish. Specifying +// zero endpoint derivatives makes the reproduction exact. +template +void test_constant_function(const char* type_name) +{ + std::cout << "Testing cardinal_cubic_b_spline constant reproduction for type " << type_name << std::endl; + + const Real constant {static_cast(50.2)}; + const Real a {static_cast(5)}; + const Real step {static_cast(0.02)}; + + std::vector v(20, constant); + + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), a, step, static_cast(0), static_cast(0)); + + const Real eps {std::numeric_limits::epsilon()}; + for (std::size_t i {0}; i < v.size(); ++i) + { + const Real arg {a + step * static_cast(i) + static_cast(0.002)}; + CHECK_ULP_CLOSE(constant, spline(arg), 16); + CHECK_ABSOLUTE_ERROR(static_cast(0), spline.prime(arg), 16 * eps); + // double_prime carries a 1/h^2 factor, so the residual of the (exactly + // zero) second derivative is amplified; keep this tolerance loose. + CHECK_ABSOLUTE_ERROR(static_cast(0), spline.double_prime(arg), 5000 * eps); + } +} + +// Cubic b splines reproduce affine functions exactly, and the derivative of +// f(x) = m*x + b is the constant slope m. +template +void test_affine_function(const char* type_name) +{ + std::cout << "Testing cardinal_cubic_b_spline affine reproduction for type " << type_name << std::endl; + + using std::sqrt; + + const Real m {static_cast(3)}; + const Real b {static_cast(2)}; + const Real step {static_cast(0.05)}; + + std::vector v(20); + for (std::size_t i {0}; i < v.size(); ++i) + { + v[i] = m * (step * static_cast(i)) + b; + } + + // Specify the exact endpoint derivatives so the affine fit is exact. + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), static_cast(0), step, m, m); + + const Real tol {100 * sqrt(std::numeric_limits::epsilon())}; + for (std::size_t i {0}; i + 1 < v.size(); ++i) + { + const Real arg {step * static_cast(i) + static_cast(0.001)}; + CHECK_ABSOLUTE_ERROR(m * arg + b, spline(arg), tol); + CHECK_ABSOLUTE_ERROR(m, spline.prime(arg), tol); + } +} + +int main() +{ + test_interpolation_condition("float"); + test_interpolation_condition("double"); + + test_constant_function("float"); + test_constant_function("double"); + + test_affine_function("float"); + test_affine_function("double"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_cardinal_quadratic_b_spline.cpp b/test/test_cardinal_quadratic_b_spline.cpp new file mode 100644 index 0000000000..fef0d151fb --- /dev/null +++ b/test/test_cardinal_quadratic_b_spline.cpp @@ -0,0 +1,162 @@ +/* + * Copyright Nick Thompson, 2019 + * 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) + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#endif +using boost::math::interpolators::cardinal_quadratic_b_spline; + +#if !defined(BOOST_MATH_BUILD_MODULE) && __has_include() +# include +#endif + +template +void test_constant() +{ + Real c = Real(7.2); + Real t0 = 0; + Real h = Real(1)/Real(16); + size_t n = 512; + std::vector v(n, c); + auto qbs = cardinal_quadratic_b_spline(v.data(), v.size(), t0, h); + + size_t i = 0; + while (i < n) { + Real t = t0 + i*h; + CHECK_ULP_CLOSE(c, qbs(t), 2); + CHECK_MOLLIFIED_CLOSE(0, qbs.prime(t), (std::numeric_limits::digits > 100 ? 200 : 100) * std::numeric_limits::epsilon()); + ++i; + } + + i = 0; + while (i < n) { + Real t = t0 + i*h + h/2; + CHECK_ULP_CLOSE(c, qbs(t), 2); + CHECK_MOLLIFIED_CLOSE(0, qbs.prime(t), 300*std::numeric_limits::epsilon()); + t = t0 + i*h + h/4; + CHECK_ULP_CLOSE(c, qbs(t), 2); + CHECK_MOLLIFIED_CLOSE(0, qbs.prime(t), (std::numeric_limits::digits > 100 ? 300 : 200) * std::numeric_limits::epsilon()); + ++i; + } +} + +template +void test_linear() +{ + Real m = Real(8.3); + Real b = Real(7.2); + Real t0 = 0; + Real h = Real(1)/Real(16); + size_t n = 512; + std::vector y(n); + for (size_t i = 0; i < n; ++i) { + Real t = i*h; + y[i] = m*t + b; + } + auto qbs = cardinal_quadratic_b_spline(y.data(), y.size(), t0, h); + + size_t i = 0; + while (i < n) { + Real t = t0 + i*h; + // At the knots the spline has to reproduce the data it was built from: + CHECK_ULP_CLOSE(y[i], qbs(t), 2); + CHECK_ULP_CLOSE(m, qbs.prime(t), 820); + ++i; + } + + i = 0; + while (i < n) { + Real t = t0 + i*h + h/2; + CHECK_ULP_CLOSE(m*t+b, qbs(t), 3); + CHECK_MOLLIFIED_CLOSE(m, qbs.prime(t), 1500*std::numeric_limits::epsilon()); + t = t0 + i*h + h/4; + CHECK_ULP_CLOSE(m*t+b, qbs(t), 3); + CHECK_MOLLIFIED_CLOSE(m, qbs.prime(t), 1500*std::numeric_limits::epsilon()); + ++i; + } +} + +template +void test_quadratic() +{ + Real a = Real(8.2); + Real b = Real(7.2); + Real c = Real(-9.2); + Real t0 = 0; + Real h = Real(1)/Real(16); + size_t n = 513; + std::vector y(n); + for (size_t i = 0; i < n; ++i) { + Real t = i*h; + y[i] = a*t*t + b*t + c; + } + Real t_max = t0 + (n-1)*h; + auto qbs = cardinal_quadratic_b_spline(y, t0, h, b, 2*a*t_max + b); + + size_t i = 0; + while (i < n) { + Real t = t0 + i*h; + // At the knots the spline has to reproduce the data it was built from. + // Recomputing the polynomial here is not the same thing: it crosses zero + // inside the interval, and next to the root the result depends on whether + // the compiler fuses the multiplies and adds. + CHECK_ULP_CLOSE(y[i], qbs(t), 2); + ++i; + } + + i = 0; + while (i < n) { + Real t = t0 + i*h + h/2; + CHECK_ULP_CLOSE(a*t*t + b*t + c, qbs(t), 47); + + t = t0 + i*h + h/4; + if (!CHECK_ULP_CLOSE(a*t*t + b*t + c, qbs(t), 120)) { + std::cerr << " Problem abscissa t = " << t << "\n"; + } + ++i; + } +} + +int main() +{ + #ifdef __STDCPP_FLOAT32_T__ + test_constant(); + test_linear(); + #else + test_constant(); + test_linear(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_constant(); + test_linear(); + test_quadratic(); + #else + test_constant(); + test_linear(); + test_quadratic(); + #endif + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_constant(); + test_linear(); + test_quadratic(); +#endif + + return boost::math::test::report_errors(); +} diff --git a/test/cardinal_quintic_b_spline_test.cpp b/test/test_cardinal_quintic_b_spline.cpp similarity index 100% rename from test/cardinal_quintic_b_spline_test.cpp rename to test/test_cardinal_quintic_b_spline.cpp diff --git a/test/test_cardinal_quintic_b_spline_module.cpp b/test/test_cardinal_quintic_b_spline_module.cpp new file mode 100644 index 0000000000..1be68cbbf3 --- /dev/null +++ b/test/test_cardinal_quintic_b_spline_module.cpp @@ -0,0 +1,154 @@ +/* + * Copyright Nick Thompson, 2019 + * Copyright Matt Borland, 2026 + * 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) + */ +// +// Module build check for cardinal_quintic_b_spline. Consuming the interpolator +// through the boost.math module exercises both constructor overloads (the raw +// pointer form and the std::vector form), the estimate-derivatives path (NaN +// endpoint derivatives), and operator()/prime/double_prime/t_max from a module +// consumer. The reproduction properties used here are mathematically certain: +// a quintic B-spline reproduces polynomials up to degree five exactly. Expected +// values and tolerances are copied from test_cardinal_quintic_b_spline.cpp. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#endif +#include "math_unit_test.hpp" + +using boost::math::interpolators::cardinal_quintic_b_spline; + +// A quintic B-spline reproduces a straight line exactly. The raw pointer +// constructor is used with the endpoint derivatives supplied explicitly. +template +void test_linear() +{ + using std::abs; + Real m {Real(8.3)}; + Real b {Real(7.2)}; + Real t0 {0}; + Real h {Real(1)/Real(16)}; + std::size_t n {64}; + std::vector y(n); + for (std::size_t i {0}; i < n; ++i) + { + Real t {i*h}; + y[i] = m*t + b; + } + std::pair left_endpoint_derivatives {m, Real(0)}; + std::pair right_endpoint_derivatives {m, Real(0)}; + auto qbs = cardinal_quintic_b_spline(y.data(), y.size(), t0, h, left_endpoint_derivatives, right_endpoint_derivatives); + + for (std::size_t i {0}; i < n; ++i) + { + Real t {t0 + i*h}; + CHECK_ULP_CLOSE(m*t + b, qbs(t), 3); + CHECK_MOLLIFIED_CLOSE(m, qbs.prime(t), 100*abs(m*t + b)*std::numeric_limits::epsilon()); + CHECK_MOLLIFIED_CLOSE(Real(0), qbs.double_prime(t), 10000*abs(m*t + b)*std::numeric_limits::epsilon()); + } + + for (std::size_t i {0}; i < n - 1; ++i) + { + Real t {t0 + i*h + h/2}; + CHECK_ULP_CLOSE(m*t + b, qbs(t), 5); + CHECK_MOLLIFIED_CLOSE(m, qbs.prime(t), 1500*std::numeric_limits::epsilon()); + t = t0 + i*h + h/4; + CHECK_ULP_CLOSE(m*t + b, qbs(t), 5); + CHECK_MOLLIFIED_CLOSE(m, qbs.prime(t), 3000*std::numeric_limits::epsilon()); + } +} + +// A quintic B-spline reproduces a constant. The endpoint derivatives are left +// as their NaN default so the constructor estimates them by finite differences. +template +void test_constant_estimate_derivatives() +{ + Real c {Real(7.5)}; + Real t0 {0}; + Real h {Real(1)/Real(16)}; + std::size_t n {65}; + std::vector v(n, c); + auto qbs = cardinal_quintic_b_spline(v.data(), v.size(), t0, h); + + for (std::size_t i {0}; i < n; ++i) + { + Real t {t0 + i*h}; + CHECK_ULP_CLOSE(c, qbs(t), 3); + CHECK_MOLLIFIED_CLOSE(Real(0), qbs.prime(t), 1200*std::numeric_limits::epsilon()); + CHECK_MOLLIFIED_CLOSE(Real(0), qbs.double_prime(t), 200000*std::numeric_limits::epsilon()); + } + + for (std::size_t i {0}; i < n - 1; ++i) + { + Real t {t0 + i*h + h/2}; + CHECK_ULP_CLOSE(c, qbs(t), 8); + CHECK_MOLLIFIED_CLOSE(Real(0), qbs.prime(t), 1200*std::numeric_limits::epsilon()); + CHECK_MOLLIFIED_CLOSE(Real(0), qbs.double_prime(t), 80000*std::numeric_limits::epsilon()); + t = t0 + i*h + h/4; + CHECK_ULP_CLOSE(c, qbs(t), 5); + CHECK_MOLLIFIED_CLOSE(Real(0), qbs.prime(t), 1200*std::numeric_limits::epsilon()); + CHECK_MOLLIFIED_CLOSE(Real(0), qbs.double_prime(t), 38000*std::numeric_limits::epsilon()); + } +} + +// A quintic B-spline reproduces a quadratic exactly. The std::vector +// constructor is used, and t_max is verified against the known domain endpoint. +template +void test_quadratic() +{ + Real a {Real(1)/Real(16)}; + Real b {Real(-3.5)}; + Real c {Real(-9)}; + Real t0 {0}; + Real h {Real(1)/Real(16)}; + std::size_t n {65}; + std::vector y(n); + for (std::size_t i {0}; i < n; ++i) + { + Real t {i*h}; + y[i] = a*t*t + b*t + c; + } + Real t_max {t0 + (n - 1)*h}; + std::pair left_endpoint_derivatives {b, 2*a}; + std::pair right_endpoint_derivatives {2*a*t_max + b, 2*a}; + auto qbs = cardinal_quintic_b_spline(y, t0, h, left_endpoint_derivatives, right_endpoint_derivatives); + + CHECK_ULP_CLOSE(t_max, qbs.t_max(), 2); + + for (std::size_t i {0}; i < n; ++i) + { + Real t {t0 + i*h}; + CHECK_ULP_CLOSE(a*t*t + b*t + c, qbs(t), 3); + } + + for (std::size_t i {0}; i < n - 1; ++i) + { + Real t {t0 + i*h + h/2}; + CHECK_ULP_CLOSE(a*t*t + b*t + c, qbs(t), 5); + t = t0 + i*h + h/4; + CHECK_ULP_CLOSE(a*t*t + b*t + c, qbs(t), 5); + } +} + +int main() +{ + test_linear(); + test_linear(); + test_constant_estimate_derivatives(); + test_quadratic(); + + return boost::math::test::report_errors(); +} diff --git a/test/test_cardinal_trigonometric.cpp b/test/test_cardinal_trigonometric.cpp new file mode 100644 index 0000000000..5e607a01af --- /dev/null +++ b/test/test_cardinal_trigonometric.cpp @@ -0,0 +1,256 @@ +/* + * Copyright Nick Thompson, 2019 + * 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) + */ + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef BOOST_HAS_FLOAT128 +#include +#include +#endif + +#if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) && !defined(TEST4) && !defined(TEST5) +# define TEST1 +# define TEST2 +# define TEST3 +# define TEST4 +# define TEST5 +#endif + + +using std::sin; +using boost::math::constants::two_pi; +using boost::math::interpolators::cardinal_trigonometric; +using boost::multiprecision::cpp_bin_float_50; + +// distributions only accept the built-in floating point types. +template +using dist_type = typename std::conditional::value, Real, double>::type; + +template +void test_constant() +{ + Real t0 = 0; + Real h = 1; + for(size_t n = 1; n < 20; ++n) + { + Real c = 8; + std::vector v(n, c); + auto ct = cardinal_trigonometric(v, t0, h); + // The FFT of constant data leaves rounding error in the coefficients that should vanish, + // and the derivatives multiply the k-th of them by k and k^2. + CHECK_ULP_CLOSE(c, ct(0.3), 6); + CHECK_ULP_CLOSE(c*h*n, ct.integrate(), 3); + CHECK_ULP_CLOSE(c*c*h*n, ct.squared_l2(), 6); + CHECK_MOLLIFIED_CLOSE(Real(0), ct.prime(0.8), 75*std::numeric_limits::epsilon()); + CHECK_MOLLIFIED_CLOSE(Real(0), ct.double_prime(0.8), 150*std::numeric_limits::epsilon()); + } +} + +template +void test_interpolation_condition() +{ + std::mt19937 gen(1234); + std::uniform_real_distribution> dis(1, 10); + + for(size_t n = 1; n < 20; ++n) { + Real t0 = static_cast(dis(gen)); + Real h = static_cast(dis(gen)); + std::vector v(n); + for (size_t i = 0; i < n; ++i) { + v[i] = static_cast(dis(gen)); + } + auto ct = cardinal_trigonometric(v, t0, h); + for (size_t i = 0; i < n; ++i) { + Real arg = t0 + i*h; + Real expected = v[i]; + Real computed = ct(arg); + // The abscissa t0 + i*h is itself rounded, and the phase error it causes grows with n; + // 5n ulps was too tight for float with clang-cl at n = 11 (60 ulps). + if(!CHECK_ULP_CLOSE(expected, computed, 8*n)) + { + std::cerr << " Samples: " << n << "\n"; + } + } + } + +} + + +template +void test_sampled_sine() +{ + using std::sin; + using std::cos; + for (unsigned n = 15; n < 50; ++n) + { + Real t0 = 0; + Real T = 1; + Real h = T/n; + std::vector v(n); + auto s = [&](Real t) { return sin(two_pi()*(t-t0)/T);}; + auto s_prime = [&](Real t) { return two_pi()*cos(two_pi()*(t-t0)/T)/T;}; + auto s_double_prime = [&](Real t) { return -two_pi()*two_pi()*sin(two_pi()*(t-t0)/T)/(T*T);}; + for(size_t j = 0; j < v.size(); ++j) + { + Real t = t0 + j*h; + v[j] = s(t); + } + auto ct = cardinal_trigonometric(v, t0, h); + CHECK_ULP_CLOSE(T, ct.period(), 3); + std::mt19937 gen(1234); + std::uniform_real_distribution> dist(0, 500); + + unsigned j = 0; + while (j++ < 50) { + Real arg = static_cast(dist(gen)); + Real expected = s(arg); + Real computed = ct(arg); + CHECK_MOLLIFIED_CLOSE(expected, computed, std::numeric_limits::epsilon()*4000); + + expected = s_prime(arg); + computed = ct.prime(arg); + CHECK_MOLLIFIED_CLOSE(expected, computed, 18000*std::numeric_limits::epsilon()); + + expected = s_double_prime(arg); + computed = ct.double_prime(arg); + CHECK_MOLLIFIED_CLOSE(expected, computed, 100000*std::numeric_limits::epsilon()); + + } + CHECK_MOLLIFIED_CLOSE(Real(0), ct.integrate(), std::numeric_limits::epsilon()); + } +} + +template +void test_bump() +{ + using std::exp; + using std::abs; + using std::sqrt; + using std::pow; + auto bump = [](Real x)->Real { if (abs(x) >= 1) { return Real(0); } return exp(-Real(1)/(Real(1)-x*x)); }; + auto bump_prime = [](Real x)->Real { + if (abs(x) >= 1) { return Real(0); } + + return -2*x*exp(-Real(1)/(Real(1)-x*x))/pow(1-x*x,2); + }; + + auto bump_double_prime = [](Real x)->Real { + if (abs(x) >= 1) { return Real(0); } + + return (6*pow(x,4)-2)*exp(-Real(1)/(Real(1)-x*x))/pow(1-x*x,4); + }; + + + Real t0 = -1; + size_t n = 4096; + Real h = Real(2)/Real(n); + + std::vector v(n); + for(size_t i = 0; i < n; ++i) + { + Real t = t0 + i*h; + v[i] = bump(t); + } + + auto ct = cardinal_trigonometric(v, t0, h); + // With 4096 samples the interpolant differs from the bump by about 1e-37 (1e-33 and 1e-30 for the derivatives), + // which only matters for types with more than 113 bits. + using std::max; + Real eps = std::numeric_limits::epsilon(); + Real tol0 = (max)(Real(2*eps), Real(1e-35)); + Real tol1 = (max)(Real(4000*eps), Real(1e-31)); + Real tol2 = (max)(Real(4000*4000*eps), Real(1e-28)); + std::mt19937 gen(323723); + std::uniform_real_distribution dis(-0.9, 0.9); + + size_t i = 0; + while (i++ < 1000) + { + Real t = static_cast(dis(gen)); + Real expected = bump(t); + Real computed = ct(t); + if(!CHECK_MOLLIFIED_CLOSE(expected, computed, tol0)) { + std::cerr << " Problem occurred at abscissa " << t << "\n"; + } + + expected = bump_prime(t); + computed = ct.prime(t); + if(!CHECK_MOLLIFIED_CLOSE(expected, computed, tol1)) { + std::cerr << " Problem occurred at abscissa " << t << "\n"; + } + + expected = bump_double_prime(t); + computed = ct.double_prime(t); + if(!CHECK_MOLLIFIED_CLOSE(expected, computed, tol2)) { + std::cerr << " Problem occurred at abscissa " << t << "\n"; + } + + + } + + // Wolfram Alpha: + // NIntegrate[Exp[-1/(1-x*x)],{x,-1,1}] + CHECK_ULP_CLOSE(BOOST_MATH_TEST_VALUE(Real, 0.443993816168079437823048921170552663761201789045697497307484553947041), ct.integrate(), 3); + + // NIntegrate[Exp[-2/(1-x*x)],{x,-1,1}] + CHECK_ULP_CLOSE(BOOST_MATH_TEST_VALUE(Real, 0.133086120844994271556947327955328571362579155162813005534500258889539), ct.squared_l2(), 1); + + +} + + +int main() +{ + +#ifdef TEST1 + test_constant(); + test_sampled_sine(); + test_bump(); + test_interpolation_condition(); +#endif + + +#ifdef TEST2 + test_constant(); + test_sampled_sine(); + test_bump(); + test_interpolation_condition(); +#endif + +#ifdef TEST3 + test_constant(); + test_sampled_sine(); + test_bump(); + test_interpolation_condition(); +#endif + +#ifdef TEST4 +#ifdef BOOST_HAS_FLOAT128 + using boost::multiprecision::float128; + test_constant(); + test_sampled_sine(); + test_bump(); + test_interpolation_condition(); +#endif +#endif + +#ifdef TEST5 + test_constant(); + test_sampled_sine(); + test_bump(); + test_interpolation_condition(); +#endif + + return boost::math::test::report_errors(); +} diff --git a/test/test_carlson.cpp b/test/test_carlson.cpp index 41b16fae61..e4512f980a 100644 --- a/test/test_carlson.cpp +++ b/test/test_carlson.cpp @@ -43,7 +43,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_catmull_rom.cpp b/test/test_catmull_rom.cpp new file mode 100644 index 0000000000..9e4ba4e2d2 --- /dev/null +++ b/test/test_catmull_rom.cpp @@ -0,0 +1,463 @@ +/* + * Copyright Nick Thompson, 2017 + * 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) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "math_unit_test.hpp" + +#if __has_include() +# include +#endif + +using std::abs; +using boost::multiprecision::cpp_bin_float_50; +using boost::math::catmull_rom; + +template +void test_alpha_distance() +{ + std::array v1 = {0,0,0}; + std::array v2 = {1,0,0}; + Real alpha = 0.5; + Real d = boost::math::detail::alpha_distance>(v1, v2, alpha); + CHECK_ULP_CLOSE(1, d, 2); + + d = boost::math::detail::alpha_distance>(v1, v2, 0.0); + CHECK_ULP_CLOSE(1, d, 2); + + d = boost::math::detail::alpha_distance>(v1, v2, 1.0); + CHECK_ULP_CLOSE(1, d, 2); + + v2[0] = 2; + d = boost::math::detail::alpha_distance>(v1, v2, alpha); + CHECK_ULP_CLOSE(pow(2, (Real)1/ (Real) 2), d, 2); + + d = boost::math::detail::alpha_distance>(v1, v2, 0.0); + CHECK_ULP_CLOSE(1, d, 2); + + d = boost::math::detail::alpha_distance>(v1, v2, 1.0); + CHECK_ULP_CLOSE(2, d, 2); +} + + +template +void test_linear() +{ + std::cout << "Testing that the Catmull-Rom spline interpolates linear functions correctly on type " + << boost::typeindex::type_id().pretty_name() << "\n"; + + Real tol = 10*std::numeric_limits::epsilon(); + std::vector> v(4); + v[0] = {0,0,0}; + v[1] = {1,0,0}; + v[2] = {2,0,0}; + v[3] = {3,0,0}; + catmull_rom> cr(std::move(v)); + + // Test that the interpolation condition is obeyed: + CHECK_ULP_CLOSE(3, cr.max_parameter(), 4); + auto p0 = cr(0.0); + CHECK_ABSOLUTE_ERROR(0, p0[0], tol); + CHECK_ABSOLUTE_ERROR(0, p0[1], tol); + CHECK_ABSOLUTE_ERROR(0, p0[2], tol); + auto p1 = cr(1.0); + CHECK_ULP_CLOSE(1, p1[0], 4); + CHECK_ABSOLUTE_ERROR(0, p1[1], tol); + CHECK_ABSOLUTE_ERROR(0, p1[2], tol); + + auto p2 = cr(2.0); + CHECK_ULP_CLOSE(2, p2[0], 4); + CHECK_ABSOLUTE_ERROR(0, p2[1], tol); + CHECK_ABSOLUTE_ERROR(0, p2[2], tol); + + + auto p3 = cr(3.0); + CHECK_ULP_CLOSE(3, p3[0], 4); + CHECK_ABSOLUTE_ERROR(0, p3[1], tol); + CHECK_ABSOLUTE_ERROR(0, p3[2], tol); + + Real s = cr.parameter_at_point(0); + CHECK_ABSOLUTE_ERROR(0, s, tol); + + s = cr.parameter_at_point(1); + CHECK_ULP_CLOSE(1, s, 4); + + s = cr.parameter_at_point(2); + CHECK_ULP_CLOSE(2, s, 4); + + s = cr.parameter_at_point(3); + CHECK_ULP_CLOSE(3, s, 4); + + // Test that the function is linear on the interval [1,2]: + for (double s = 1; s < 2; s += 0.01) + { + auto p = cr(s); + CHECK_ULP_CLOSE(Real(s), p[0], 4); + CHECK_ABSOLUTE_ERROR(0, p[1], tol); + CHECK_ABSOLUTE_ERROR(0, p[2], tol); + + auto tangent = cr.prime(s); + CHECK_ULP_CLOSE(1, tangent[0], 8); + CHECK_ABSOLUTE_ERROR(0, tangent[1], tol); + CHECK_ABSOLUTE_ERROR(0, tangent[2], tol); + } + +} + +template +void test_circle() +{ + using boost::math::constants::pi; + using std::cos; + using std::sin; + + std::cout << "Testing that the Catmull-Rom spline interpolates circles correctly on type " + << boost::typeindex::type_id().pretty_name() << "\n"; + + Real tol = 10*std::numeric_limits::epsilon(); + std::vector> v(20*sizeof(Real)); + std::vector> u(20*sizeof(Real)); + for (size_t i = 0; i < v.size(); ++i) + { + Real theta = ((Real) i/ (Real) v.size())*2*pi(); + v[i] = {cos(theta), sin(theta)}; + u[i] = v[i]; + } + catmull_rom> circle(std::move(v), true); + + // Interpolation condition (v was moved from, so iterate over its copy u): + for (size_t i = 0; i < u.size(); ++i) + { + Real s = circle.parameter_at_point(i); + auto p = circle(s); + Real x = p[0]; + Real y = p[1]; + if (abs(x) < std::numeric_limits::epsilon()) + { + CHECK_ABSOLUTE_ERROR(0, u[i][0], tol); + } + if (abs(y) < std::numeric_limits::epsilon()) + { + CHECK_ABSOLUTE_ERROR(0, u[i][1], tol); + } + else + { + CHECK_ULP_CLOSE(u[i][0], x, 12); + CHECK_ULP_CLOSE(u[i][1], y, 12); + } + } + + Real max_s = circle.max_parameter(); + for(Real s = 0; s < max_s; s += Real(0.01)) + { + auto p = circle(s); + Real x = p[0]; + Real y = p[1]; + CHECK_ABSOLUTE_ERROR(1, x*x+y*y, Real(0.001)); + } +} + + +template +void test_affine_invariance() +{ + std::cout << "Testing that the Catmull-Rom spline is affine invariant in dimension " + << dimension << " on type " + << boost::typeindex::type_id().pretty_name() << "\n"; + + Real tol = 1000*std::numeric_limits::epsilon(); + std::vector> v(100); + std::vector> u(100); + std::mt19937_64 gen(438232); + Real inv_denom = (Real) 100/( (Real) (gen.max)() + (Real) 2); + for(size_t j = 0; j < dimension; ++j) + { + v[0][j] = gen()*inv_denom; + u[0][j] = v[0][j]; + } + + for (size_t i = 1; i < v.size(); ++i) + { + for(size_t j = 0; j < dimension; ++j) + { + v[i][j] = v[i-1][j] + gen()*inv_denom; + u[i][j] = v[i][j]; + } + } + std::array affine_shift; + for (size_t j = 0; j < dimension; ++j) + { + affine_shift[j] = gen()*inv_denom; + } + + catmull_rom> cr1(std::move(v)); + + for(size_t i = 0; i< u.size(); ++i) + { + for(size_t j = 0; j < dimension; ++j) + { + u[i][j] += affine_shift[j]; + } + } + + catmull_rom> cr2(std::move(u)); + + CHECK_ULP_CLOSE(cr2.max_parameter(), cr1.max_parameter(), 4); + + Real ds = cr1.max_parameter()/1024; + for (Real s = 0; s < cr1.max_parameter(); s += ds) + { + auto p0 = cr1(s); + auto p1 = cr2(s); + auto tangent0 = cr1.prime(s); + auto tangent1 = cr2.prime(s); + for (size_t j = 0; j < dimension; ++j) + { + CHECK_ULP_CLOSE(p1[j], p0[j] + affine_shift[j], 28); + if (abs(tangent0[j]) > 5000*tol) + { + CHECK_ULP_CLOSE(tangent1[j], tangent0[j], 1600868); + } + } + } +} + +template +void test_helix() +{ + using boost::math::constants::pi; + std::cout << "Testing that the Catmull-Rom spline interpolates helices correctly on type " + << boost::typeindex::type_id().pretty_name() << "\n"; + + Real tol = 0.001; + std::vector> v(400*sizeof(Real)); + for (size_t i = 0; i < v.size(); ++i) + { + Real theta = ((Real) i/ (Real) v.size())*2*pi(); + v[i] = {cos(theta), sin(theta), theta}; + } + const size_t num_points = v.size(); + catmull_rom> helix(std::move(v)); + + // Interpolation condition (v was moved from, so use the saved size): + for (size_t i = 0; i < num_points; ++i) + { + Real s = helix.parameter_at_point(i); + auto p = helix(s); + Real t = p[2]; + + Real x = p[0]; + Real y = p[1]; + if (abs(x) < tol) + { + CHECK_ABSOLUTE_ERROR(0, Real(cos(t)), tol); + } + else + { + CHECK_ABSOLUTE_ERROR(cos(t), x, Real(tol*abs(cos(t)))); + } + if (abs(y) < tol) + { + CHECK_ABSOLUTE_ERROR(0, Real(sin(t)), tol); + } + else + { + CHECK_ABSOLUTE_ERROR(sin(t), y, Real(tol*abs(sin(t)))); + } + } + + Real max_s = helix.max_parameter(); + for(Real s = helix.parameter_at_point(1); s < max_s; s += 0.01) + { + auto p = helix(s); + Real x = p[0]; + Real y = p[1]; + Real t = p[2]; + CHECK_ABSOLUTE_ERROR(Real(1), x*x+y*y, Real(0.01)); + if (abs(x) < 0.01) + { + CHECK_ABSOLUTE_ERROR(0, Real(cos(t)), (Real) 0.05); + } + if (abs(y) < 0.01) + { + CHECK_ABSOLUTE_ERROR(0, Real(sin(t)), (Real) 0.05); + } + else + { + CHECK_ABSOLUTE_ERROR(Real(cos(t)), x, Real(((Real) 0.05)*abs(Real(cos(t))))); + CHECK_ABSOLUTE_ERROR(Real(sin(t)), y, Real(((Real) 0.05)*abs(Real(sin(t))))); + } + } +} + + +template +class mypoint3d +{ +public: + // Must define a value_type: + typedef Real value_type; + + // Regular constructor: + mypoint3d(Real x, Real y, Real z) + { + m_vec[0] = x; + m_vec[1] = y; + m_vec[2] = z; + } + + // Must define a default constructor: + mypoint3d() {} + + // Must define array access: + Real operator[](size_t i) const + { + return m_vec[i]; + } + + // Array element assignment: + Real& operator[](size_t i) + { + return m_vec[i]; + } + + +private: + std::array m_vec; +}; + + +// Must define the free function "size()": +template +constexpr std::size_t size(const mypoint3d&) +{ + return 3; +} + +template +void test_data_representations() +{ + std::cout << "Testing that the Catmull-Rom spline works with multiple data representations.\n"; + mypoint3d p0(Real(0.1), Real(0.2), Real(0.3)); + mypoint3d p1(Real(0.2), Real(0.3), Real(0.4)); + mypoint3d p2(Real(0.3), Real(0.4), Real(0.5)); + mypoint3d p3(Real(0.4), Real(0.5), Real(0.6)); + mypoint3d p4(Real(0.5), Real(0.6), Real(0.7)); + mypoint3d p5(Real(0.6), Real(0.7), Real(0.8)); + + + // Tests initializer_list: + catmull_rom> cat({p0, p1, p2, p3, p4, p5}); + + Real tol = Real(0.001); + auto p = cat(cat.parameter_at_point(0)); + CHECK_ABSOLUTE_ERROR(p0[0], p[0], Real(tol*abs(p0[0]))); + CHECK_ABSOLUTE_ERROR(p0[1], p[1], Real(tol*abs(p0[1]))); + CHECK_ABSOLUTE_ERROR(p0[2], p[2], Real(tol*abs(p0[2]))); + p = cat(cat.parameter_at_point(1)); + CHECK_ABSOLUTE_ERROR(p1[0], p[0], Real(tol*abs(p1[0]))); + CHECK_ABSOLUTE_ERROR(p1[1], p[1], Real(tol*abs(p1[1]))); + CHECK_ABSOLUTE_ERROR(p1[2], p[2], Real(tol*abs(p1[2]))); +} + +template +void test_random_access_container() +{ + std::cout << "Testing that the Catmull-Rom spline works with multiple data representations.\n"; + mypoint3d p0(0.1, 0.2, 0.3); + mypoint3d p1(0.2, 0.3, 0.4); + mypoint3d p2(0.3, 0.4, 0.5); + mypoint3d p3(0.4, 0.5, 0.6); + mypoint3d p4(0.5, 0.6, 0.7); + mypoint3d p5(0.6, 0.7, 0.8); + + boost::numeric::ublas::vector> u(6); + u[0] = p0; + u[1] = p1; + u[2] = p2; + u[3] = p3; + u[4] = p4; + u[5] = p5; + + // Tests initializer_list: + catmull_rom, decltype(u)> cat(std::move(u)); + + Real tol = Real(0.001); + auto p = cat(cat.parameter_at_point(0)); + CHECK_ABSOLUTE_ERROR(p0[0], p[0], Real(tol*abs(p0[0]))); + CHECK_ABSOLUTE_ERROR(p0[1], p[1], Real(tol*abs(p0[1]))); + CHECK_ABSOLUTE_ERROR(p0[2], p[2], Real(tol*abs(p0[2]))); + p = cat(cat.parameter_at_point(1)); + CHECK_ABSOLUTE_ERROR(p1[0], p[0], Real(tol*abs(p1[0]))); + CHECK_ABSOLUTE_ERROR(p1[1], p[1], Real(tol*abs(p1[1]))); + CHECK_ABSOLUTE_ERROR(p1[2], p[2], Real(tol*abs(p1[2]))); +} + +void catmull_rom_test() +{ +#if !defined(TEST) || (TEST == 1) + + #ifdef __STDCPP_FLOAT32_T__ + test_circle(); + test_data_representations(); + #else + test_circle(); + test_data_representations(); + #endif + + #ifdef __STDCPP_FLOAT64_T__ + test_alpha_distance(); + test_linear(); + test_circle(); + #else + test_alpha_distance(); + test_linear(); + test_circle(); + #endif + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_linear(); + #endif + +#endif + +#if !defined(TEST) || (TEST == 2) + + #ifdef __STDCPP_FLOAT64_T__ + test_helix(); + test_affine_invariance(); + test_affine_invariance(); + test_affine_invariance(); + test_affine_invariance(); + test_random_access_container(); + #else + test_helix(); + test_affine_invariance(); + test_affine_invariance(); + test_affine_invariance(); + test_affine_invariance(); + test_random_access_container(); + #endif + +#endif + +#if !defined(TEST) || (TEST == 3) + test_affine_invariance(); +#endif +} + +int main() +{ + catmull_rom_test(); + return boost::math::test::report_errors(); +} diff --git a/test/test_catmull_rom_module.cpp b/test/test_catmull_rom_module.cpp new file mode 100644 index 0000000000..cfa1b4f13f --- /dev/null +++ b/test/test_catmull_rom_module.cpp @@ -0,0 +1,138 @@ +/* + * Copyright Nick Thompson, 2017 + * Copyright Matt Borland, 2026 + * 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) + */ +// +// Module build check for catmull_rom. Consuming the interpolator through +// `import boost.math;` confirms the exported class template and its +// max_parameter/parameter_at_point/operator()/prime members are usable from a +// module consumer, along with both the move-vector and initializer_list +// constructors. The assertions exercise only mathematically-certain properties: +// a Catmull-Rom spline passes through every control point (the interpolation +// condition), and on collinear, equally spaced points it reproduces the +// straight line through them exactly, so both the value and the tangent are +// exact. Expected values are taken from the test_linear case of +// test_catmull_rom.cpp. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#endif + +using boost::math::catmull_rom; + +// Four equally spaced, collinear points on the x-axis. The spline passes through +// every node, is the straight line s -> (s, 0, 0) on the interior segments, and +// has the constant unit tangent (1, 0, 0) there. +template +void test_linear(const char* type_name) +{ + std::cout << "Testing catmull_rom linear reproduction for type " << type_name << std::endl; + + const Real eps {std::numeric_limits::epsilon()}; + + std::vector> v(4); + v[0] = {Real(0), Real(0), Real(0)}; + v[1] = {Real(1), Real(0), Real(0)}; + v[2] = {Real(2), Real(0), Real(0)}; + v[3] = {Real(3), Real(0), Real(0)}; + + catmull_rom> cr(std::move(v)); + + // One unit of parameter between consecutive nodes, total length 3. + CHECK_ULP_CLOSE(Real(3), cr.max_parameter(), 4); + CHECK_ABSOLUTE_ERROR(Real(0), cr.parameter_at_point(0), eps); + CHECK_ULP_CLOSE(Real(1), cr.parameter_at_point(1), 4); + CHECK_ULP_CLOSE(Real(2), cr.parameter_at_point(2), 4); + CHECK_ULP_CLOSE(Real(3), cr.parameter_at_point(3), 4); + + // Interpolation condition: the curve passes through each control point. + const auto p0 = cr(Real(0)); + CHECK_ABSOLUTE_ERROR(Real(0), p0[0], eps); + CHECK_ABSOLUTE_ERROR(Real(0), p0[1], eps); + CHECK_ABSOLUTE_ERROR(Real(0), p0[2], eps); + + const auto p1 = cr(Real(1)); + CHECK_ULP_CLOSE(Real(1), p1[0], 4); + CHECK_ABSOLUTE_ERROR(Real(0), p1[1], eps); + CHECK_ABSOLUTE_ERROR(Real(0), p1[2], eps); + + const auto p2 = cr(Real(2)); + CHECK_ULP_CLOSE(Real(2), p2[0], 4); + CHECK_ABSOLUTE_ERROR(Real(0), p2[1], eps); + CHECK_ABSOLUTE_ERROR(Real(0), p2[2], eps); + + const auto p3 = cr(Real(3)); + CHECK_ULP_CLOSE(Real(3), p3[0], 4); + CHECK_ABSOLUTE_ERROR(Real(0), p3[1], eps); + CHECK_ABSOLUTE_ERROR(Real(0), p3[2], eps); + + // On the interior segment [1, 2] the curve is the line s -> (s, 0, 0) and + // its tangent is the constant (1, 0, 0). + const Real interior[3] {Real(1.25), Real(1.5), Real(1.75)}; + for (const Real s : interior) + { + const auto p = cr(s); + CHECK_ULP_CLOSE(s, p[0], 4); + CHECK_ABSOLUTE_ERROR(Real(0), p[1], eps); + CHECK_ABSOLUTE_ERROR(Real(0), p[2], eps); + + const auto tangent = cr.prime(s); + CHECK_ULP_CLOSE(Real(1), tangent[0], 4); + CHECK_ABSOLUTE_ERROR(Real(0), tangent[1], eps); + CHECK_ABSOLUTE_ERROR(Real(0), tangent[2], eps); + } +} + +// The initializer_list constructor produces the same interpolant, and the curve +// reproduces its node values at the parameter reported by parameter_at_point. +template +void test_initializer_list(const char* type_name) +{ + std::cout << "Testing catmull_rom initializer_list construction for type " << type_name << std::endl; + + const Real eps {std::numeric_limits::epsilon()}; + + const std::array a0 {Real(0), Real(0), Real(0)}; + const std::array a1 {Real(1), Real(0), Real(0)}; + const std::array a2 {Real(2), Real(0), Real(0)}; + const std::array a3 {Real(3), Real(0), Real(0)}; + + catmull_rom> cr({a0, a1, a2, a3}); + + const auto q0 = cr(cr.parameter_at_point(0)); + CHECK_ABSOLUTE_ERROR(Real(0), q0[0], eps); + CHECK_ABSOLUTE_ERROR(Real(0), q0[1], eps); + + const auto q1 = cr(cr.parameter_at_point(1)); + CHECK_ULP_CLOSE(Real(1), q1[0], 4); + CHECK_ABSOLUTE_ERROR(Real(0), q1[1], eps); + + const auto q2 = cr(cr.parameter_at_point(2)); + CHECK_ULP_CLOSE(Real(2), q2[0], 4); + CHECK_ABSOLUTE_ERROR(Real(0), q2[1], eps); +} + +int main() +{ + test_linear("float"); + test_linear("double"); + + test_initializer_list("float"); + test_initializer_list("double"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_cbrt.cpp b/test/test_cbrt.cpp index 3b662f909a..4f02a1583e 100644 --- a/test/test_cbrt.cpp +++ b/test/test_cbrt.cpp @@ -48,7 +48,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } diff --git a/test/ccmath_abs_test.cpp b/test/test_ccmath_abs.cpp similarity index 100% rename from test/ccmath_abs_test.cpp rename to test/test_ccmath_abs.cpp diff --git a/test/ccmath_ceil_test.cpp b/test/test_ccmath_ceil.cpp similarity index 100% rename from test/ccmath_ceil_test.cpp rename to test/test_ccmath_ceil.cpp diff --git a/test/ccmath_copysign_test.cpp b/test/test_ccmath_copysign.cpp similarity index 100% rename from test/ccmath_copysign_test.cpp rename to test/test_ccmath_copysign.cpp diff --git a/test/ccmath_div_test.cpp b/test/test_ccmath_div.cpp similarity index 100% rename from test/ccmath_div_test.cpp rename to test/test_ccmath_div.cpp diff --git a/test/ccmath_fdim_test.cpp b/test/test_ccmath_fdim.cpp similarity index 100% rename from test/ccmath_fdim_test.cpp rename to test/test_ccmath_fdim.cpp diff --git a/test/ccmath_floor_test.cpp b/test/test_ccmath_floor.cpp similarity index 100% rename from test/ccmath_floor_test.cpp rename to test/test_ccmath_floor.cpp diff --git a/test/ccmath_fma_test.cpp b/test/test_ccmath_fma.cpp similarity index 100% rename from test/ccmath_fma_test.cpp rename to test/test_ccmath_fma.cpp diff --git a/test/ccmath_fmax_test.cpp b/test/test_ccmath_fmax.cpp similarity index 100% rename from test/ccmath_fmax_test.cpp rename to test/test_ccmath_fmax.cpp diff --git a/test/ccmath_fmin_test.cpp b/test/test_ccmath_fmin.cpp similarity index 100% rename from test/ccmath_fmin_test.cpp rename to test/test_ccmath_fmin.cpp diff --git a/test/ccmath_fmod_test.cpp b/test/test_ccmath_fmod.cpp similarity index 100% rename from test/ccmath_fmod_test.cpp rename to test/test_ccmath_fmod.cpp diff --git a/test/ccmath_fpclassify_test.cpp b/test/test_ccmath_fpclassify.cpp similarity index 100% rename from test/ccmath_fpclassify_test.cpp rename to test/test_ccmath_fpclassify.cpp diff --git a/test/ccmath_frexp_test.cpp b/test/test_ccmath_frexp.cpp similarity index 100% rename from test/ccmath_frexp_test.cpp rename to test/test_ccmath_frexp.cpp diff --git a/test/test_ccmath_hypot.cpp b/test/test_ccmath_hypot.cpp new file mode 100644 index 0000000000..30f4ebb4f7 --- /dev/null +++ b/test/test_ccmath_hypot.cpp @@ -0,0 +1,154 @@ +// (C) Copyright Matt Borland 2021. +// 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) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_FLOAT128 +#include +#endif + +#if !defined(BOOST_MATH_NO_CONSTEXPR_DETECTION) && !defined(BOOST_MATH_USING_BUILTIN_CONSTANT_P) +template +constexpr void test() +{ + // Error Handling + if constexpr (std::numeric_limits::has_quiet_NaN) + { + static_assert(boost::math::ccmath::isnan(boost::math::ccmath::hypot(std::numeric_limits::quiet_NaN(), T(1))), "If x is NaN, NaN is returned"); + static_assert(boost::math::ccmath::isnan(boost::math::ccmath::hypot(T(1), std::numeric_limits::quiet_NaN())), "If y is NaN, NaN is returned"); + } + + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(std::numeric_limits::infinity(), T(1)))); + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(-std::numeric_limits::infinity(), T(1)))); + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(T(1), std::numeric_limits::infinity()))); + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(T(1), -std::numeric_limits::infinity()))); + + // Correct promoted types + if constexpr (!std::is_same_v) + { + constexpr auto test_type = boost::math::ccmath::hypot(T(1), 1.0f); + static_assert(std::is_same_v>); + } + else + { + constexpr auto test_type = boost::math::ccmath::hypot(1.0f, 1); + static_assert(std::is_same_v>); + } + + // Functionality + static_assert(boost::math::ccmath::hypot(T(1), T(1)) == boost::math::ccmath::sqrt(T(2))); + static_assert(boost::math::ccmath::hypot(T(-1), T(1)) == boost::math::ccmath::sqrt(T(2))); + static_assert(boost::math::ccmath::hypot(T(-1), T(-1)) == boost::math::ccmath::sqrt(T(2))); + static_assert(boost::math::ccmath::hypot(T(1), T(-1)) == boost::math::ccmath::sqrt(T(2))); + static_assert(boost::math::ccmath::hypot(T(1), T(2)) == boost::math::ccmath::sqrt(T(5))); + static_assert(boost::math::ccmath::hypot(T(2), T(2)) == boost::math::ccmath::sqrt(T(8))); +} + +template +constexpr void test_3_arg() +{ + constexpr T tol = 5 * std::numeric_limits::epsilon(); + + // Error Handling + if constexpr (std::numeric_limits::has_quiet_NaN) + { + static_assert(boost::math::ccmath::isnan(boost::math::ccmath::hypot(std::numeric_limits::quiet_NaN(), T(1), T(1))), "If x is NaN, NaN is returned"); + static_assert(boost::math::ccmath::isnan(boost::math::ccmath::hypot(T(1), std::numeric_limits::quiet_NaN(), T(1))), "If y is NaN, NaN is returned"); + static_assert(boost::math::ccmath::isnan(boost::math::ccmath::hypot(T(1), T(1), std::numeric_limits::quiet_NaN())), "If z is NaN, NaN is returned"); + } + + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(std::numeric_limits::infinity(), T(1), T(1)))); + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(-std::numeric_limits::infinity(), T(1), T(1)))); + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(T(1), std::numeric_limits::infinity(), T(1)))); + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(T(1), -std::numeric_limits::infinity(), T(1)))); + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(T(1), T(1), std::numeric_limits::infinity()))); + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(T(1), T(1), -std::numeric_limits::infinity()))); + + // Correct promoted types + if constexpr (!std::is_same_v) + { + constexpr auto test_type = boost::math::ccmath::hypot(T(1), T(1), 1.0f); + static_assert(std::is_same_v>); + } + else + { + constexpr auto test_type = boost::math::ccmath::hypot(1.0f, 1, 1); + static_assert(std::is_same_v>); + } + + // Functionality + static_assert(boost::math::ccmath::hypot(T(1), T(1), T(1)) == boost::math::ccmath::sqrt(T(3))); + static_assert(boost::math::ccmath::hypot(T(-1), T(1), T(1)) == boost::math::ccmath::sqrt(T(3))); + static_assert(boost::math::ccmath::hypot(T(2), T(2), T(1)) == T(3)); + static_assert(boost::math::ccmath::hypot(T(2), T(-2), T(1)) == T(3)); + static_assert(boost::math::ccmath::abs(boost::math::ccmath::hypot(T(1), T(2), T(3)) - boost::math::ccmath::sqrt(T(14))) < tol); + + // Zeros: no 0/0 + static_assert(boost::math::ccmath::hypot(T(0), T(0), T(0)) == T(0)); + static_assert(boost::math::ccmath::hypot(T(-0.0), T(-0.0), T(-0.0)) == T(0)); + static_assert(boost::math::ccmath::hypot(T(0), T(0), T(-3)) == T(3)); + + // inf wins over NaN, as for the two argument version + if constexpr (std::numeric_limits::has_quiet_NaN) + { + static_assert(boost::math::ccmath::isinf(boost::math::ccmath::hypot(std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN(), T(1)))); + } + + // No spurious overflow when the squares overflow + constexpr T big = (std::numeric_limits::max)() / 4; + static_assert(boost::math::ccmath::abs(boost::math::ccmath::hypot(big, big, big) / (big * boost::math::ccmath::sqrt(T(3))) - 1) < tol); +} + +template +bool test_3_arg_runtime() +{ + // Not constant evaluated, so this goes to std::hypot + volatile T x = 2; + volatile T y = 2; + volatile T z = 1; + return boost::math::ccmath::hypot(T(x), T(y), T(z)) == T(3); +} + +int main() +{ + test(); + test(); + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test(); + #endif + + #ifdef BOOST_HAS_FLOAT128 + test(); + #endif + + test_3_arg(); + test_3_arg(); + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_3_arg(); + #endif + + if (!test_3_arg_runtime() || !test_3_arg_runtime()) + { + return 1; + } + + return 0; +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/ccmath_ilogb_test.cpp b/test/test_ccmath_ilogb.cpp similarity index 100% rename from test/ccmath_ilogb_test.cpp rename to test/test_ccmath_ilogb.cpp diff --git a/test/ccmath_isfinite_test.cpp b/test/test_ccmath_isfinite.cpp similarity index 100% rename from test/ccmath_isfinite_test.cpp rename to test/test_ccmath_isfinite.cpp diff --git a/test/ccmath_isgreater_test.cpp b/test/test_ccmath_isgreater.cpp similarity index 100% rename from test/ccmath_isgreater_test.cpp rename to test/test_ccmath_isgreater.cpp diff --git a/test/ccmath_isgreaterequal_test.cpp b/test/test_ccmath_isgreaterequal.cpp similarity index 100% rename from test/ccmath_isgreaterequal_test.cpp rename to test/test_ccmath_isgreaterequal.cpp diff --git a/test/test_ccmath_isinf.cpp b/test/test_ccmath_isinf.cpp new file mode 100644 index 0000000000..cb773797e8 --- /dev/null +++ b/test/test_ccmath_isinf.cpp @@ -0,0 +1,84 @@ +// (C) Copyright Matt Borland 2021. +// 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) + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#endif +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif +#ifndef BOOST_MATH_STANDALONE +#include +#else +// Standalone/module builds cannot use Boost.Core; map lightweight_test onto math_unit_test.hpp. +#include "math_unit_test.hpp" +#define BOOST_TEST(expr) CHECK_TRUE((expr)) +namespace boost { inline int report_errors() { return ::boost::math::test::report_errors(); } } +#endif + +#ifdef BOOST_HAS_FLOAT128 +#include +#endif + +template +void test() +{ + using std::exp; + + // Integer types define infinity as 0 + // https://en.cppreference.com/w/cpp/types/numeric_limits/infinity + if constexpr(std::is_integral_v) + { + constexpr bool test_val = boost::math::ccmath::isinf(T(0)); + static_assert(test_val, "Not constexpr"); + } + else + { + constexpr bool test_val = boost::math::ccmath::isinf(T(0)); + static_assert(!test_val, "Not constexpr"); + } + + if constexpr (std::numeric_limits::has_quiet_NaN) + { + static_assert(!boost::math::ccmath::isinf(std::numeric_limits::quiet_NaN())); + } + static_assert(boost::math::ccmath::isinf(std::numeric_limits::infinity())); +} + +// Only test on platforms that provide BOOST_MATH_IS_CONSTANT_EVALUATED +#ifndef BOOST_MATH_NO_CONSTEXPR_DETECTION +int main() +{ + test(); + test(); + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test(); + #endif + + #if defined(BOOST_MATH_TEST_FLOAT128) && !defined(BOOST_MATH_USING_BUILTIN_CONSTANT_P) && defined(BOOST_MATH_TEST_FLOAT128) + test(); + #endif + + test(); + test(); + test(); + test(); + test(); + test(); + + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/ccmath_isless_test.cpp b/test/test_ccmath_isless.cpp similarity index 100% rename from test/ccmath_isless_test.cpp rename to test/test_ccmath_isless.cpp diff --git a/test/ccmath_islessequal_test.cpp b/test/test_ccmath_islessequal.cpp similarity index 100% rename from test/ccmath_islessequal_test.cpp rename to test/test_ccmath_islessequal.cpp diff --git a/test/test_ccmath_isnan.cpp b/test/test_ccmath_isnan.cpp new file mode 100644 index 0000000000..928aa095c9 --- /dev/null +++ b/test/test_ccmath_isnan.cpp @@ -0,0 +1,78 @@ +// (C) Copyright Matt Borland 2021. +// 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) + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#endif +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif +#ifndef BOOST_MATH_STANDALONE +#include +#else +// Standalone/module builds cannot use Boost.Core; map lightweight_test onto math_unit_test.hpp. +#include "math_unit_test.hpp" +#define BOOST_TEST(expr) CHECK_TRUE((expr)) +namespace boost { inline int report_errors() { return ::boost::math::test::report_errors(); } } +#endif +#include + +#ifdef BOOST_HAS_FLOAT128 +#include +#endif + +template +void test() +{ + constexpr bool test_val = boost::math::ccmath::isnan(T(0)); + static_assert(!test_val, "Not constexpr"); + + if constexpr (std::numeric_limits::has_quiet_NaN) + { + static_assert(boost::math::ccmath::isnan(std::numeric_limits::quiet_NaN()), "Quiet NAN failed"); + } + if constexpr (std::numeric_limits::has_signaling_NaN) + { + static_assert(boost::math::ccmath::isnan(std::numeric_limits::signaling_NaN()), "Signaling NAN failed"); + } + static_assert(!boost::math::ccmath::isnan(std::numeric_limits::infinity()), "Infinity failed"); + static_assert(!boost::math::ccmath::isnan(T(0)), "Real 0 failed"); +} + +// Only test on platforms that provide BOOST_MATH_IS_CONSTANT_EVALUATED +#ifndef BOOST_MATH_NO_CONSTEXPR_DETECTION +int main() +{ + test(); + test(); + + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test(); + #endif + + #if defined(BOOST_MATH_TEST_FLOAT128) && !defined(BOOST_MATH_USING_BUILTIN_CONSTANT_P) + test(); + #endif + + test(); + test(); + test(); + test(); + test(); + test(); + + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/ccmath_isnormal_test.cpp b/test/test_ccmath_isnormal.cpp similarity index 100% rename from test/ccmath_isnormal_test.cpp rename to test/test_ccmath_isnormal.cpp diff --git a/test/ccmath_isunordered_test.cpp b/test/test_ccmath_isunordered.cpp similarity index 100% rename from test/ccmath_isunordered_test.cpp rename to test/test_ccmath_isunordered.cpp diff --git a/test/ccmath_ldexp_test.cpp b/test/test_ccmath_ldexp.cpp similarity index 100% rename from test/ccmath_ldexp_test.cpp rename to test/test_ccmath_ldexp.cpp diff --git a/test/ccmath_logb_test.cpp b/test/test_ccmath_logb.cpp similarity index 100% rename from test/ccmath_logb_test.cpp rename to test/test_ccmath_logb.cpp diff --git a/test/ccmath_modf_test.cpp b/test/test_ccmath_modf.cpp similarity index 100% rename from test/ccmath_modf_test.cpp rename to test/test_ccmath_modf.cpp diff --git a/test/ccmath_next_test.cpp b/test/test_ccmath_next.cpp similarity index 100% rename from test/ccmath_next_test.cpp rename to test/test_ccmath_next.cpp diff --git a/test/test_ccmath_next_module.cpp b/test/test_ccmath_next_module.cpp new file mode 100644 index 0000000000..1000409fd6 --- /dev/null +++ b/test/test_ccmath_next_module.cpp @@ -0,0 +1,37 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// Module build check for ccmath::nextafter. Its detail dispatch defaults a +// template parameter to boost::math::tools::detail::has_backend_type_v, so +// building this against the boost.math module exercises the variable templates +// in tools/traits.hpp from a module consumer. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif +#include "math_unit_test.hpp" + +template +void test_spots(T, const char* type_name) +{ + std::cout << "Testing ccmath next for type " << type_name << std::endl; + + CHECK_EQUAL(boost::math::ccmath::nextafter(static_cast(1), static_cast(2)), std::nextafter(static_cast(1), static_cast(2))); + CHECK_EQUAL(boost::math::ccmath::nextafter(static_cast(1), static_cast(0)), std::nextafter(static_cast(1), static_cast(0))); +} + +int main() +{ + test_spots(0.0F, "float"); + test_spots(0.0, "double"); + + return boost::math::test::report_errors(); +} diff --git a/test/ccmath_remainder_test.cpp b/test/test_ccmath_remainder.cpp similarity index 100% rename from test/ccmath_remainder_test.cpp rename to test/test_ccmath_remainder.cpp diff --git a/test/ccmath_round_test.cpp b/test/test_ccmath_round.cpp similarity index 100% rename from test/ccmath_round_test.cpp rename to test/test_ccmath_round.cpp diff --git a/test/ccmath_scalbln_test.cpp b/test/test_ccmath_scalbln.cpp similarity index 100% rename from test/ccmath_scalbln_test.cpp rename to test/test_ccmath_scalbln.cpp diff --git a/test/ccmath_scalbn_test.cpp b/test/test_ccmath_scalbn.cpp similarity index 100% rename from test/ccmath_scalbn_test.cpp rename to test/test_ccmath_scalbn.cpp diff --git a/test/ccmath_signbit_test.cpp b/test/test_ccmath_signbit.cpp similarity index 100% rename from test/ccmath_signbit_test.cpp rename to test/test_ccmath_signbit.cpp diff --git a/test/ccmath_sqrt_test.cpp b/test/test_ccmath_sqrt.cpp similarity index 100% rename from test/ccmath_sqrt_test.cpp rename to test/test_ccmath_sqrt.cpp diff --git a/test/ccmath_trunc_test.cpp b/test/test_ccmath_trunc.cpp similarity index 100% rename from test/ccmath_trunc_test.cpp rename to test/test_ccmath_trunc.cpp diff --git a/test/centered_continued_fraction_test.cpp b/test/test_centered_continued_fraction.cpp similarity index 100% rename from test/centered_continued_fraction_test.cpp rename to test/test_centered_continued_fraction.cpp diff --git a/test/test_chatterjee_correlation.cpp b/test/test_chatterjee_correlation.cpp index 3443980eb9..e05c60b3b1 100644 --- a/test/test_chatterjee_correlation.cpp +++ b/test/test_chatterjee_correlation.cpp @@ -1,18 +1,27 @@ // (C) Copyright Matt Borland 2022. +// (C) Copyright Oleksandr Kornijcuk 2026. // 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) +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include #include #include #include #include #include #include -#include -#include -#include -#include "math_unit_test.hpp" +#endif // The Chatterjee correlation is invariant under: // - Shuffles. (X_i, Y_i) -> (X_sigma(i), Y_sigma(i)), where sigma is a permutation. @@ -20,6 +29,7 @@ // using boost::math::statistics::chatterjee_correlation; +using boost::math::statistics::chatterjee_correlation_mnn; template void properties() @@ -30,7 +40,7 @@ void properties() std::vector X(vector_size); std::vector Y(vector_size); - for (std::size_t i = 0; i < vector_size; ++i) + for (std::size_t i = 0; i < vector_size; ++i) { X[i] = unif(mt); Y[i] = unif(mt); @@ -42,7 +52,7 @@ void properties() CHECK_LE(coeff1, Real(1)); // Now apply a monotone function to the data - for (std::size_t i = 0; i < vector_size; ++i) + for (std::size_t i = 0; i < vector_size; ++i) { X[i] = Real(2.3)*X[i] - Real(7.3); Y[i] = Real(7.6)*Y[i] - Real(8.6); @@ -62,7 +72,7 @@ void properties() template void test_spots() -{ +{ // Rank Order: Result will be 1 - 3*3 / (4^2 - 1) = 1 - 9/15 = 0.6 std::vector x = {1, 2, 3, 4}; std::vector y = {1, 2, 3, 4}; @@ -81,7 +91,124 @@ void test_spots() CHECK_NAN(chatterjee_correlation(x, y)); } -#ifdef BOOST_MATH_EXEC_COMPATIBLE +// Closed forms for the M-NN statistic xi_{n,M} of Lin and Han (2021), Remark 2.5. +// These are exact (no external reference needed) and are used to validate the implementation. + +// Y = f(X) with f strictly increasing: xi_{n,M} = 1 - (3(M+1)/4) / (n + (M+1)/4). +template +Real xi_mnn_increasing(std::size_t n, std::size_t M) +{ + const Real nr = static_cast(n); + const Real Mr = static_cast(M); + return Real(1) - (Real(3)*(Mr + 1)/4) / (nr + (Mr + 1)/4); +} + +// Y = f(X) with f strictly decreasing: +// xi_{n,M} = 1 - 3(M+1)[(5n+1)/4 - (2M+1)/3] / ((n+1)(n + (M+1)/4)). +template +Real xi_mnn_decreasing(std::size_t n, std::size_t M) +{ + const Real nr = static_cast(n); + const Real Mr = static_cast(M); + return Real(1) - (Real(3)*(Mr + 1)*((Real(5)*nr + 1)/4 - (Real(2)*Mr + 1)/3)) + / ((nr + 1)*(nr + (Mr + 1)/4)); +} + +template +void test_mnn_spots() +{ + // Exact small spot values, computed independently as rationals. + std::vector x = {1, 2, 3, 4}; + std::vector y = {1, 2, 3, 4}; + + // M = 2: -2 + 6*20 / (5 * 9.5) = 10/19 + CHECK_ULP_CLOSE(chatterjee_correlation_mnn(x, y, 2), Real(10)/19, 4); + // M = 3: 2/5 + CHECK_ULP_CLOSE(chatterjee_correlation_mnn(x, y, 3), Real(2)/5, 4); + + // Reverse order, M = 2: -34/95. Note: unlike the M = 1 statistic, the M-NN statistic is NOT + // invariant under reversal of Y for M > 1 (min{.,.} is not reversal-symmetric). + y = {4, 3, 2, 1}; + CHECK_ULP_CLOSE(chatterjee_correlation_mnn(x, y, 2), Real(-34)/95, 4); + + // Alternating order, M = 2: 2/5 + y = {1, 3, 2, 4}; + CHECK_ULP_CLOSE(chatterjee_correlation_mnn(x, y, 2), Real(2)/5, 4); + + // n = 5 increasing, M = 2: 14/23 + std::vector x5 = {1, 2, 3, 4, 5}; + std::vector y5 = {1, 2, 3, 4, 5}; + CHECK_ULP_CLOSE(chatterjee_correlation_mnn(x5, y5, 2), Real(14)/23, 4); + + // Constant Y yields quiet NaN. + y = {1, 1, 1, 1}; + CHECK_NAN(chatterjee_correlation_mnn(x, y, 2)); +} + +template +void test_mnn_extremal() +{ + // Build an X sorted ascending with no ties. + const std::size_t n = 200; + std::vector x(n); + for (std::size_t i = 0; i < n; ++i) + { + x[i] = static_cast(i); + } + + // Strictly increasing dependence Y = X. + for (std::size_t M : {std::size_t(1), std::size_t(2), std::size_t(5), std::size_t(20), std::size_t(50)}) + { + const Real got = chatterjee_correlation_mnn(x, x, M); + CHECK_ULP_CLOSE(got, xi_mnn_increasing(n, M), 4); + } + + // Strictly decreasing dependence Y = -X. + std::vector y(n); + for (std::size_t i = 0; i < n; ++i) + { + y[i] = -x[i]; + } + for (std::size_t M : {std::size_t(1), std::size_t(2), std::size_t(5), std::size_t(20), std::size_t(50)}) + { + const Real got = chatterjee_correlation_mnn(x, y, M); + CHECK_ULP_CLOSE(got, xi_mnn_decreasing(n, M), 4); + } +} + +template +void test_mnn_properties() +{ + const std::size_t n = 256; + std::mt19937_64 mt(987654); + std::uniform_real_distribution unif(-1, 1); + std::vector X(n); + std::vector Y(n); + for (std::size_t i = 0; i < n; ++i) + { + X[i] = unif(mt); + Y[i] = unif(mt); + } + std::sort(X.begin(), X.end()); + + const std::size_t M = 16; + const Real coeff1 = chatterjee_correlation_mnn(X, Y, M); + + // The finite-sample range is [-1/2, 1] up to a bias of order M/n; use generous bounds. + CHECK_GE(coeff1, Real(-1)); + CHECK_LE(coeff1, Real(1)); + + // Invariance under strictly increasing transforms of X and Y. + for (std::size_t i = 0; i < n; ++i) + { + X[i] = Real(2.3)*X[i] - Real(7.3); + Y[i] = Real(7.6)*Y[i] - Real(8.6); + } + const Real coeff2 = chatterjee_correlation_mnn(X, Y, M); + CHECK_EQUAL(coeff1, coeff2); +} + +#if defined(BOOST_MATH_EXEC_COMPATIBLE) && !defined(BOOST_MATH_BUILD_MODULE) template void test_threaded(ExecutionPolicy&& exec) @@ -97,13 +224,31 @@ void test_threaded(ExecutionPolicy&& exec) CHECK_ULP_CLOSE(seq_ans, par_ans, 1); }; +template +void test_mnn_threaded(ExecutionPolicy&& exec) +{ + std::vector x = boost::math::generate_random_vector(1024, 2); + std::vector y = boost::math::generate_random_vector(1024, 1); + + std::sort(std::forward(exec), x.begin(), x.end()); + + for (std::size_t M : {std::size_t(1), std::size_t(8), std::size_t(32)}) + { + auto seq_ans = chatterjee_correlation_mnn(x, y, M); + auto par_ans = chatterjee_correlation_mnn(exec, x, y, M); + CHECK_ULP_CLOSE(seq_ans, par_ans, 1); + } +}; + #endif // BOOST_MATH_EXEC_COMPATIBLE +#ifndef BOOST_MATH_BUILD_MODULE + template void test_paper() { constexpr Real two_pi = boost::math::constants::two_pi(); - + // Page 9 figure (a) y = x size_t seed = 3; std::vector x = boost::math::generate_random_uniform_vector(100, seed, -two_pi, two_pi); @@ -131,17 +276,34 @@ void test_paper() CHECK_MOLLIFIED_CLOSE(result, Real(0.885), 0.012); } +#endif // BOOST_MATH_BUILD_MODULE + int main(void) { properties(); properties(); - properties(); test_spots(); test_spots(); + + test_mnn_spots(); + test_mnn_spots(); + + test_mnn_extremal(); + test_mnn_extremal(); + + test_mnn_properties(); + test_mnn_properties(); + + #ifndef BOOST_MATH_BUILD_MODULE + properties(); test_spots(); + test_mnn_spots(); + test_mnn_extremal(); + test_mnn_properties(); + #endif - #ifdef BOOST_MATH_EXEC_COMPATIBLE + #if defined(BOOST_MATH_EXEC_COMPATIBLE) && !defined(BOOST_MATH_BUILD_MODULE) test_threaded(std::execution::par); test_threaded(std::execution::par); @@ -150,11 +312,20 @@ int main(void) test_threaded(std::execution::par_unseq); test_threaded(std::execution::par_unseq); + test_mnn_threaded(std::execution::par); + test_mnn_threaded(std::execution::par); + test_mnn_threaded(std::execution::par); + test_mnn_threaded(std::execution::par_unseq); + test_mnn_threaded(std::execution::par_unseq); + test_mnn_threaded(std::execution::par_unseq); + #endif // BOOST_MATH_EXEC_COMPATIBLE + #ifndef BOOST_MATH_BUILD_MODULE test_paper(); test_paper(); test_paper(); + #endif return boost::math::test::report_errors(); } diff --git a/test/test_chebyshev.cpp b/test/test_chebyshev.cpp new file mode 100644 index 0000000000..ec9bd79114 --- /dev/null +++ b/test/test_chebyshev.cpp @@ -0,0 +1,205 @@ +/* + * Copyright Nick Thompson, 2017 + * 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) + */ + +#include +#include +#include +#include +#include +#include +#include +#include "math_unit_test.hpp" + +using boost::multiprecision::cpp_bin_float_quad; +using boost::math::chebyshev_t; +using boost::math::chebyshev_t_prime; +using boost::math::chebyshev_u; + +template +void test_polynomials() +{ + std::cout << "Testing explicit polynomial representations of the Chebyshev polynomials on type " << boost::typeindex::type_id().pretty_name() << "\n"; + + Real x = -2; + Real tol = 32*std::numeric_limits::epsilon(); + while (x < 2) + { + CHECK_MOLLIFIED_CLOSE(chebyshev_t(0, x), Real(1), tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_t(1, x), x, tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_t(2, x), 2*x*x - 1, tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_t(3, x), x*(4*x*x-3), tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_t(4, x), 8*x*x*(x*x - 1) + 1, tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_t(5, x), x*(16*x*x*x*x - 20*x*x + 5), tol); + x += 1/static_cast(1<<7); + } + + x = -2; + while (x < 2) + { + CHECK_MOLLIFIED_CLOSE(chebyshev_u(0, x), Real(1), tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_u(1, x), 2*x, tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_u(2, x), 4*x*x - 1, tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_u(3, x), 4*x*(2*x*x - 1), tol); + x += 1/static_cast(1<<7); + } +} + + +template +void test_derivatives() +{ + std::cout << "Testing explicit polynomial representations of the Chebyshev polynomial derivatives on type " << boost::typeindex::type_id().pretty_name() << "\n"; + + Real x = -2; + Real tol = 4*std::numeric_limits::epsilon(); + while (x < 2) + { + CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(0, x), Real(0), tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(1, x), Real(1), tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(2, x), 4*x, tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(3, x), 3*(4*x*x - 1), tol); + CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(4, x), 16*x*(2*x*x - 1), tol); + // This one makes the tolerance have to grow too large; the Chebyshev recurrence is more stable than naive polynomial evaluation anyway. + //CHECK_MOLLIFIED_CLOSE(chebyshev_t_prime(5, x), 5*(4*x*x*(4*x*x - 3) + 1), tol); + x += 1/static_cast(1<<7); + } +} + +template +void test_clenshaw_recurrence() +{ + using boost::math::chebyshev_clenshaw_recurrence; + std::array c0 = { {2, 0, 0, 0, 0} }; + // Check the size = 1 case: + std::array c01 = { {2} }; + // Check the size = 2 case: + std::array c02 = { {2, 0} }; + std::array c1 = { {0, 1, 0, 0} }; + std::array c2 = { {0, 0, 1, 0} }; + std::array c3 = { {0, 0, 0, 1, 0} }; + std::array c4 = { {0, 0, 0, 0, 1} }; + std::array c5 = { {0, 0, 0, 0, 0, 1} }; + std::array c6 = { {0, 0, 0, 0, 0, 0, 1} }; + + // + // Error handling checks: + // + CHECK_THROW(chebyshev_clenshaw_recurrence(c0.data(), c0.size(), Real(-1), Real(1), Real(-2)), std::domain_error); + CHECK_THROW(chebyshev_clenshaw_recurrence(c0.data(), c0.size(), Real(-1), Real(1), Real(2)), std::domain_error); + CHECK_EQUAL(chebyshev_clenshaw_recurrence(c0.data(), 0, Real(-1), Real(1), Real(0.5)), Real(0)); + + Real x = -1; + // It's not clear from this test which one is more accurate; higher precision cast testing is required, and is done elsewhere: + int ulps = 50; + while (x <= 1) + { + Real y = chebyshev_clenshaw_recurrence(c0.data(), c0.size(), x); + Real expected = chebyshev_t(0, x); + CHECK_ULP_CLOSE(expected, y, ulps); + y = chebyshev_clenshaw_recurrence(c0.data(), c0.size(), Real(-1), Real(1), x); + CHECK_ULP_CLOSE(expected, y, ulps); + + y = chebyshev_clenshaw_recurrence(c01.data(), c01.size(), x); + CHECK_ULP_CLOSE(expected, y, ulps); + y = chebyshev_clenshaw_recurrence(c01.data(), c01.size(), Real(-1), Real(1), x); + CHECK_ULP_CLOSE(expected, y, ulps); + + y = chebyshev_clenshaw_recurrence(c02.data(), c02.size(), x); + CHECK_ULP_CLOSE(expected, y, ulps); + y = chebyshev_clenshaw_recurrence(c02.data(), c02.size(), Real(-1), Real(1), x); + CHECK_ULP_CLOSE(expected, y, ulps); + + expected = chebyshev_t(1,x); + y = chebyshev_clenshaw_recurrence(c1.data(), c1.size(), x); + CHECK_ULP_CLOSE(expected, y, ulps); + y = chebyshev_clenshaw_recurrence(c1.data(), c1.size(), Real(-1), Real(1), x); + CHECK_ULP_CLOSE(expected, y, ulps); + + expected = chebyshev_t(2, x); + y = chebyshev_clenshaw_recurrence(c2.data(), c2.size(), x); + CHECK_ULP_CLOSE(expected, y, ulps); + y = chebyshev_clenshaw_recurrence(c2.data(), c2.size(), Real(-1), Real(1), x); + CHECK_ULP_CLOSE(expected, y, ulps); + + expected = chebyshev_t(3, x); + y = chebyshev_clenshaw_recurrence(c3.data(), c3.size(), x); + CHECK_ULP_CLOSE(expected, y, ulps); + y = chebyshev_clenshaw_recurrence(c3.data(), c3.size(), Real(-1), Real(1), x); + CHECK_ULP_CLOSE(expected, y, ulps); + + expected = chebyshev_t(4, x); + y = chebyshev_clenshaw_recurrence(c4.data(), c4.size(), x); + CHECK_ULP_CLOSE(expected, y, ulps); + y = chebyshev_clenshaw_recurrence(c4.data(), c4.size(), Real(-1), Real(1), x); + CHECK_ULP_CLOSE(expected, y, ulps); + + expected = chebyshev_t(5, x); + y = chebyshev_clenshaw_recurrence(c5.data(), c5.size(), x); + CHECK_ULP_CLOSE(expected, y, ulps); + y = chebyshev_clenshaw_recurrence(c5.data(), c5.size(), Real(-1), Real(1), x); + CHECK_ULP_CLOSE(expected, y, ulps); + + expected = chebyshev_t(6, x); + y = chebyshev_clenshaw_recurrence(c6.data(), c6.size(), x); + CHECK_ULP_CLOSE(expected, y, ulps); + y = chebyshev_clenshaw_recurrence(c6.data(), c6.size(), Real(-1), Real(1), x); + CHECK_ULP_CLOSE(expected, y, ulps); + + x += static_cast(1)/static_cast(1 << 7); + } +} + +template +void test_translated_clenshaw_recurrence() +{ + using boost::math::chebyshev_clenshaw_recurrence; + std::mt19937_64 mt(123242); + std::uniform_real_distribution dis(-1,1); + + std::vector c(32); + for (auto & d : c) { + d = dis(mt); + } + int samples = 0; + while (samples++ < 250) { + Real x = dis(mt); + Real expected = chebyshev_clenshaw_recurrence(c.data(), c.size(), x); + // The computed value, in this case, should actually be better, since it has more information to use. + // In any case, this test doesn't show Reinch's modification to the Clenshaw recurrence is better; + // it shows they are doing roughly the same thing. + Real computed = chebyshev_clenshaw_recurrence(c.data(), c.size(), Real(-1), Real(1), x); + if (!CHECK_ULP_CLOSE(expected, computed, 1000)) { + std::cerr << " Problem occurred at x = " << x << "\n"; + } + } +} + +int main() +{ + test_polynomials(); + test_polynomials(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_polynomials(); +#endif + test_polynomials(); + + test_derivatives(); + test_derivatives(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_derivatives(); +#endif + test_derivatives(); + + test_clenshaw_recurrence(); + test_clenshaw_recurrence(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_clenshaw_recurrence(); +#endif + + test_translated_clenshaw_recurrence(); + return boost::math::test::report_errors(); +} diff --git a/test/test_chebyshev_transform.cpp b/test/test_chebyshev_transform.cpp new file mode 100644 index 0000000000..dbc7752447 --- /dev/null +++ b/test/test_chebyshev_transform.cpp @@ -0,0 +1,289 @@ +/* + * Copyright Nick Thompson, 2017 + * 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) + */ +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef BOOST_HAS_FLOAT128 +#include +#include +#endif + +#if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) && !defined(TEST4) && !defined(TEST5) +# define TEST1 +# define TEST2 +# define TEST3 +# define TEST4 +# define TEST5 +#endif + +using boost::math::chebyshev_t; +using boost::math::chebyshev_t_prime; +using boost::math::chebyshev_u; +using boost::math::chebyshev_transform; + + +template +void test_sin_chebyshev_transform() +{ + using boost::math::chebyshev_transform; + using boost::math::constants::half_pi; + using std::sin; + using std::cos; + using std::abs; + + Real tol = std::numeric_limits::epsilon(); + auto f = [](Real x)->Real { return sin(x); }; + Real a = 0; + Real b = 1; + chebyshev_transform cheb(f, a, b, tol); + // Higher precision needs a longer series, and the rounding error of the derivative grows like its length squared. + Real slack = std::numeric_limits::digits > 64 ? 10 : 1; + + Real x = a; + while (x < b) + { + Real s = sin(x); + Real c = cos(x); + CHECK_ABSOLUTE_ERROR(s, cheb(x), slack*tol); + CHECK_ABSOLUTE_ERROR(c, cheb.prime(x), 200*slack*tol); + x += static_cast(1)/static_cast(1 << 7); + } + + Real Q = cheb.integrate(); + + CHECK_ABSOLUTE_ERROR(1 - cos(static_cast(1)), Q, 100*tol); +} + + +template +void test_sinc_chebyshev_transform() +{ + using std::cos; + using std::sin; + using std::abs; + using boost::math::sinc_pi; + using boost::math::chebyshev_transform; + using boost::math::constants::half_pi; + + Real tol = 100*std::numeric_limits::epsilon(); + auto f = [](Real x) { return boost::math::sinc_pi(x); }; + Real a = 0; + Real b = 1; + chebyshev_transform cheb(f, a, b, tol/50); + // See test_sin_chebyshev_transform. + Real slack = std::numeric_limits::digits > 64 ? 10 : 1; + + Real x = a; + while (x < b) + { + Real s = sinc_pi(x); + Real ds = (cos(x)-sinc_pi(x))/x; + if (x == 0) { ds = 0; } + + CHECK_ABSOLUTE_ERROR(s, cheb(x), tol); + CHECK_ABSOLUTE_ERROR(ds, cheb.prime(x), 10*slack*tol); + x += static_cast(1)/static_cast(1 << 7); + } + + Real Q = cheb.integrate(); + //NIntegrate[Sinc[x], {x, 0, 1}, WorkingPrecision -> 200, AccuracyGoal -> 150, PrecisionGoal -> 150, MaxRecursion -> 150] + Real Q_exp = BOOST_MATH_TEST_VALUE(Real, 0.94608307036718301494135331382317965781233795473811179047145477356668); + CHECK_ABSOLUTE_ERROR(Q_exp, Q, tol); +} + + + +//Examples taken from "Approximation Theory and Approximation Practice", by Trefethen +template +void test_atap_examples() +{ + using std::sin; + using std::exp; + using std::sqrt; + using boost::math::constants::half; + using boost::math::sinc_pi; + using boost::math::chebyshev_transform; + using boost::math::constants::half_pi; + + Real tol = 10*std::numeric_limits::epsilon(); + auto f1 = [](Real x) { return ((0 < x) - (x < 0)) - x/2; }; + auto f2 = [](Real x) { Real t = sin(6*x); Real s = sin(x + exp(2*x)); + Real u = (0 < s) - (s < 0); + return t + u; }; + + //auto f3 = [](Real x) { return sin(6*x) + sin(60*exp(x)); }; + //auto f4 = [](Real x) { return 1/(1+1000*(x+half())*(x+half())) + 1/sqrt(1+1000*(x-Real(1)/Real(2))*(x-Real(1)/Real(2)));}; + Real a = -1; + Real b = 1; + chebyshev_transform cheb1(f1, a, b, tol); + chebyshev_transform cheb2(f2, a, b, tol); + //chebyshev_transform cheb3(f3, a, b, tol); + + Real x = a; + while (x < b) + { + // f1 and f2 are not differentiable; standard convergence rate theorems don't apply. + // Basically, the max refinements are always hit; so the error is not related to the precision of the type. + Real acceptable_error = sqrt(tol); + Real acceptable_error_2 = 9e-4; + // The error is that of truncating the series of a discontinuous function (about 1/n at the + // maximum length n = 2^24), so it does not shrink with the precision beyond that of long double. + if (std::is_same::value || std::numeric_limits::digits > 64) + { + acceptable_error = 1.6e-5; + } + if (std::is_same::value) + { + acceptable_error *= 500; + } + CHECK_ABSOLUTE_ERROR(f1(x), cheb1(x), acceptable_error); + + CHECK_ABSOLUTE_ERROR(f2(x), cheb2(x), acceptable_error_2); + x += static_cast(1)/static_cast(1 << 7); + } +} + + +//Validate that the Chebyshev polynomials are well approximated by the Chebyshev transform. +template +void test_chebyshev_chebyshev_transform() +{ + Real tol = 500*std::numeric_limits::epsilon(); + // T_0 = 1: + auto t0 = [](Real) { return 1; }; + chebyshev_transform cheb0(t0, -1, 1); + CHECK_ABSOLUTE_ERROR(2, cheb0.coefficients()[0], tol); + + Real x = -1; + while (x < 1) + { + CHECK_ABSOLUTE_ERROR(1, cheb0(x), tol); + CHECK_ABSOLUTE_ERROR(Real(0), cheb0.prime(x), tol); + x += static_cast(1)/static_cast(1 << 7); + } + + // T_1 = x: + auto t1 = [](Real x) { return x; }; + chebyshev_transform cheb1(t1, -1, 1); + CHECK_ABSOLUTE_ERROR(Real(1), cheb1.coefficients()[1], tol); + + x = -1; + while (x < 1) + { + CHECK_ABSOLUTE_ERROR(x, cheb1(x), tol); + CHECK_ABSOLUTE_ERROR(Real(1), cheb1.prime(x), tol); + x += static_cast(1)/static_cast(1 << 7); + } + + + auto t2 = [](Real x) { return 2*x*x-1; }; + chebyshev_transform cheb2(t2, -1, 1); + CHECK_ABSOLUTE_ERROR(Real(1), cheb2.coefficients()[2], tol); + + x = -1; + while (x < 1) + { + CHECK_ABSOLUTE_ERROR(t2(x), cheb2(x), tol); + CHECK_ABSOLUTE_ERROR(4*x, cheb2.prime(x), tol); + x += static_cast(1)/static_cast(1 << 7); + } +} + +// The DCT-II behind chebyshev_transform, for odd and even n, against a naive sum in 50 digits; +// the in-place transform agrees with the out-of-place one to 0 ulps. +template +void test_dct_ii() +{ + using boost::multiprecision::cpp_bin_float_50; + std::mt19937_64 gen(5); + std::uniform_real_distribution dis(-1, 1); + for (std::size_t n : {1, 2, 3, 4, 5, 7, 8, 12, 17, 64, 100, 127, 1000}) + { + std::vector x(n); + for (auto& t : x) + { + t = Real(dis(gen)); + } + boost::math::detail::dct_ii dct(n); + std::vector y(n); + dct.execute(x.data(), y.data()); + std::vector z = x; + dct.execute(z.data()); + CHECK_EQUAL(z == y, true); + // y[k] = 2 sum_j x[j] cos(pi k (2j+1)/(2n)); the error bound is normwise, like the FFT's. + Real scale = 0; + std::vector ref(n); + for (std::size_t k = 0; k < n; ++k) + { + cpp_bin_float_50 sum = 0; + for (std::size_t j = 0; j < n; ++j) + { + sum += cpp_bin_float_50(x[j]) * boost::math::cos_pi(cpp_bin_float_50((2 * j + 1) * k) / (2 * n)); + } + ref[k] = 2 * sum; + scale = (std::max)(scale, static_cast(abs(ref[k]))); + } + Real L = static_cast(std::log2(static_cast(n)) + 1); + for (std::size_t k = 0; k < n; ++k) + { + CHECK_ABSOLUTE_ERROR(static_cast(ref[k]), y[k], 4 * std::numeric_limits::epsilon() * L * scale); + } + } +} + +int main() +{ +#ifdef TEST1 + test_dct_ii(); + test_chebyshev_chebyshev_transform(); + test_sin_chebyshev_transform(); + test_atap_examples(); + test_sinc_chebyshev_transform(); +#endif +#ifdef TEST2 + test_dct_ii(); + test_chebyshev_chebyshev_transform(); + test_sin_chebyshev_transform(); + test_atap_examples(); + test_sinc_chebyshev_transform(); +#endif +#ifdef TEST3 + test_chebyshev_chebyshev_transform(); + test_sin_chebyshev_transform(); + test_atap_examples(); + test_sinc_chebyshev_transform(); +#endif +#ifdef TEST4 +#ifdef BOOST_HAS_FLOAT128 + using boost::multiprecision::float128; + test_chebyshev_chebyshev_transform(); + test_sin_chebyshev_transform(); + test_atap_examples(); + test_sinc_chebyshev_transform(); +#endif +#endif +#ifdef TEST5 + // The atap examples are not smooth, so they run to the maximum length (2^23 points); too slow in software arithmetic. + using boost::multiprecision::cpp_bin_float_50; + test_chebyshev_chebyshev_transform(); + test_sin_chebyshev_transform(); + test_sinc_chebyshev_transform(); +#endif + + return boost::math::test::report_errors(); +} + + diff --git a/test/test_chi_squared.cpp b/test/test_chi_squared.cpp index 360f6947de..a418fa2890 100644 --- a/test/test_chi_squared.cpp +++ b/test/test_chi_squared.cpp @@ -597,6 +597,24 @@ void test_spots(RealType T) } } // template void test_spots(RealType) +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(entropy(chi_squared_distribution(a)), h, tol); + }; + check(static_cast(0.5L), static_cast(-0.93942044477417628927930504789461881902455563L)); + check(static_cast(3.0L), static_cast(2.05411995593541182679220184217590713942022721L)); + check(static_cast(10.0L), static_cast(2.84673033718068903815688874975150836778479511L)); + check(static_cast(30.0L), static_cast(3.4435151000475149854299635042609921451141595L)); + check(static_cast(1000000.0L), static_cast(8.67326673579978244845403140563239537184530854L)); + check(static_cast(1000000000000.0L), static_cast(15.5810226814482528339302275252408911694168676L)); +} + BOOST_AUTO_TEST_CASE( test_main ) { BOOST_MATH_CONTROL_FP; @@ -608,11 +626,15 @@ BOOST_AUTO_TEST_CASE( test_main ) // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. + test_entropy(0.0F); test_spots(0.0); // Test double. + test_entropy(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. + test_entropy(0.0L); #if !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #endif } // BOOST_AUTO_TEST_CASE( test_main ) diff --git a/test/test_classify.cpp b/test/test_classify.cpp index 609a355b04..5ac43ca3aa 100644 --- a/test/test_classify.cpp +++ b/test/test_classify.cpp @@ -4,16 +4,15 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#include - #include #include #include +#ifndef BOOST_MATH_STANDALONE #include +#endif #include #include // for has_denorm_now -#define BOOST_TEST_MAIN -#include +#include "math_unit_test.hpp" #include #include @@ -65,44 +64,44 @@ void test_classify(T t, const char* type) t = 2; T u = 2; - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); + CHECK_EQUAL((::boost::math::isfinite)(t), true); + CHECK_EQUAL((::boost::math::isfinite)(-t), true); + CHECK_EQUAL((::boost::math::isinf)(t), false); + CHECK_EQUAL((::boost::math::isinf)(-t), false); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), true); + CHECK_EQUAL((::boost::math::isnormal)(-t), true); if(std::numeric_limits::is_specialized) { t = (std::numeric_limits::max)(); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); + CHECK_EQUAL((::boost::math::isfinite)(t), true); + CHECK_EQUAL((::boost::math::isfinite)(-t), true); + CHECK_EQUAL((::boost::math::isinf)(t), false); + CHECK_EQUAL((::boost::math::isinf)(-t), false); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), true); + CHECK_EQUAL((::boost::math::isnormal)(-t), true); t = (std::numeric_limits::min)(); if(t != 0) { - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); + CHECK_EQUAL((::boost::math::isfinite)(t), true); + CHECK_EQUAL((::boost::math::isinf)(t), false); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), true); if(!std::numeric_limits::is_integer) { - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); + CHECK_EQUAL((::boost::math::isfinite)(-t), true); + CHECK_EQUAL((::boost::math::isinf)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), true); + CHECK_EQUAL((::boost::math::isnan)(-t), false); } } } @@ -112,30 +111,30 @@ void test_classify(T t, const char* type) t /= 2; if(t != 0) { - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL); + CHECK_EQUAL((::boost::math::isfinite)(t), true); + CHECK_EQUAL((::boost::math::isfinite)(-t), true); + CHECK_EQUAL((::boost::math::isinf)(t), false); + CHECK_EQUAL((::boost::math::isinf)(-t), false); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), false); } t = std::numeric_limits::denorm_min(); if((t != 0) && (t < (std::numeric_limits::min)())) { - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL); + CHECK_EQUAL((::boost::math::isfinite)(t), true); + CHECK_EQUAL((::boost::math::isfinite)(-t), true); + CHECK_EQUAL((::boost::math::isinf)(t), false); + CHECK_EQUAL((::boost::math::isinf)(-t), false); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), false); } } else @@ -143,71 +142,71 @@ void test_classify(T t, const char* type) std::cout << "Denormalised forms not tested" << std::endl; } t = 0; - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO); + CHECK_EQUAL((::boost::math::isfinite)(t), true); + CHECK_EQUAL((::boost::math::isfinite)(-t), true); + CHECK_EQUAL((::boost::math::isinf)(t), false); + CHECK_EQUAL((::boost::math::isinf)(-t), false); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), false); t /= -u; // create minus zero if it exists - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO); + CHECK_EQUAL((::boost::math::isfinite)(t), true); + CHECK_EQUAL((::boost::math::isfinite)(-t), true); + CHECK_EQUAL((::boost::math::isinf)(t), false); + CHECK_EQUAL((::boost::math::isinf)(-t), false); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), false); // infinity: if(std::numeric_limits::has_infinity) { // At least one std::numeric_limits::infinity)() returns zero // (Compaq true64 cxx), hence the check. t = (std::numeric_limits::infinity)(); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); + CHECK_EQUAL((::boost::math::isfinite)(t), false); + CHECK_EQUAL((::boost::math::isfinite)(-t), false); + CHECK_EQUAL((::boost::math::isinf)(t), true); + CHECK_EQUAL((::boost::math::isinf)(-t), true); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), false); #if !defined(BOOST_BORLANDC) && !(defined(__DECCXX) && !defined(_IEEE_FP)) // divide by zero on Borland triggers a C++ exception :-( // divide by zero on Compaq CXX triggers a C style signal :-( t = 2; u = 0; t /= u; - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); + CHECK_EQUAL((::boost::math::isfinite)(t), false); + CHECK_EQUAL((::boost::math::isfinite)(-t), false); + CHECK_EQUAL((::boost::math::isinf)(t), true); + CHECK_EQUAL((::boost::math::isinf)(-t), true); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), false); t = -2; t /= u; - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); + CHECK_EQUAL((::boost::math::isfinite)(t), false); + CHECK_EQUAL((::boost::math::isfinite)(-t), false); + CHECK_EQUAL((::boost::math::isinf)(t), true); + CHECK_EQUAL((::boost::math::isinf)(-t), true); + CHECK_EQUAL((::boost::math::isnan)(t), false); + CHECK_EQUAL((::boost::math::isnan)(-t), false); + CHECK_EQUAL((::boost::math::isnormal)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), false); #else std::cout << "Infinities from divide by zero not tested" << std::endl; #endif @@ -223,16 +222,16 @@ void test_classify(T t, const char* type) if(std::numeric_limits::has_quiet_NaN) { t = std::numeric_limits::quiet_NaN(); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN); + CHECK_EQUAL((::boost::math::isfinite)(t), false); + CHECK_EQUAL((::boost::math::isfinite)(-t), false); + CHECK_EQUAL((::boost::math::isinf)(t), false); + CHECK_EQUAL((::boost::math::isinf)(-t), false); + CHECK_EQUAL((::boost::math::isnan)(t), true); + CHECK_EQUAL((::boost::math::isnan)(-t), true); + CHECK_EQUAL((::boost::math::isnormal)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), false); } else { @@ -241,16 +240,16 @@ void test_classify(T t, const char* type) if(std::numeric_limits::has_signaling_NaN) { t = std::numeric_limits::signaling_NaN(); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN); - BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); - BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true); - BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); - BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN); + CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN); + CHECK_EQUAL((::boost::math::isfinite)(t), false); + CHECK_EQUAL((::boost::math::isfinite)(-t), false); + CHECK_EQUAL((::boost::math::isinf)(t), false); + CHECK_EQUAL((::boost::math::isinf)(-t), false); + CHECK_EQUAL((::boost::math::isnan)(t), true); + CHECK_EQUAL((::boost::math::isnan)(-t), true); + CHECK_EQUAL((::boost::math::isnormal)(t), false); + CHECK_EQUAL((::boost::math::isnormal)(-t), false); } else { @@ -260,9 +259,8 @@ void test_classify(T t, const char* type) } -BOOST_AUTO_TEST_SUITE(test_fpclassify) -BOOST_AUTO_TEST_CASE( test_main ) +void test_main() { BOOST_MATH_CONTROL_FP; // start by printing some information: @@ -287,14 +285,17 @@ BOOST_AUTO_TEST_CASE( test_main ) // long double support for fpclassify is considered "core" so we always test it // even when long double support is turned off via BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_classify((long double)(0), "long double"); +#ifndef BOOST_MATH_STANDALONE test_classify((boost::math::concepts::real_concept)(0), "real_concept"); +#endif // We should test with integer types as well: test_classify(int(0), "int"); test_classify(unsigned(0), "unsigned"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(fpclassify_autodiff, T, all_float_types) { +template +void fpclassify_autodiff() { test_classify(boost::math::differentiation::make_fvar(0), "autodiff float"); test_classify(boost::math::differentiation::make_fvar(0), "autodiff float"); test_classify(boost::math::differentiation::make_fvar(0), "autodiff float"); @@ -302,7 +303,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fpclassify_autodiff, T, all_float_types) { test_classify(boost::math::differentiation::make_fvar(0), "autodiff float"); } -BOOST_AUTO_TEST_SUITE_END() /* Autorun "i:\Boost-sandbox\math_toolkit\libs\math\test\MSVC80\debug\test_classify.exe" @@ -327,3 +327,10 @@ Test suite "Test Program" passed with: 79 assertions out of 79 passed */ + +int main() +{ + test_main(); + boost::mp11::mp_for_each>([](auto t) { fpclassify_autodiff(); }); + return boost::math::test::report_errors(); +} diff --git a/test/cma_es_test.cpp b/test/test_cma_es.cpp similarity index 100% rename from test/cma_es_test.cpp rename to test/test_cma_es.cpp diff --git a/test/cohen_acceleration_test.cpp b/test/test_cohen_acceleration.cpp similarity index 100% rename from test/cohen_acceleration_test.cpp rename to test/test_cohen_acceleration.cpp diff --git a/test/complex_test.cpp b/test/test_complex.cpp similarity index 100% rename from test/complex_test.cpp rename to test/test_complex.cpp diff --git a/test/test_complex_module.cpp b/test/test_complex_module.cpp new file mode 100644 index 0000000000..7131cfa04f --- /dev/null +++ b/test/test_complex_module.cpp @@ -0,0 +1,107 @@ +// (C) Copyright John Maddock 2005. +// (C) Copyright Matt Borland 2026. +// 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) +// +// Module build check for the complex component . +// Consuming boost.math as a named module, it exercises the exported entry +// points acos, asin, acosh, asinh, atan, atanh and fabs. Every expected value +// is mathematically certain: exact Pythagorean hypotenuses for fabs, the C99 +// special cases at the origin, and standard exact arc-function values. These +// mirror the double/float spot checks in test_complex.cpp. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif +#include "math_unit_test.hpp" + +// The boost::math complex overloads are deprecated in favour of the C++11 +// std:: versions but remain exported; silence the deprecation notice. +#if defined(_MSC_VER) +# pragma warning(disable : 4996) +#elif defined(__clang__) +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +template +void test_spots(const char* type_name) +{ + std::cout << "Testing complex functions for type " << type_name << std::endl; + + // Calls are fully qualified: an unqualified name plus a std::complex + // argument would be ambiguous with the C++11 std:: overload via ADL. + + // Reference angles held in double precision (the module and, textually, + // both make boost::math::constants available). + const double half_pi {boost::math::constants::half_pi()}; + const double third_pi {boost::math::constants::third_pi()}; + const double sixth_pi {boost::math::constants::sixth_pi()}; + const double quarter_pi {boost::math::constants::quarter_pi()}; + + using ct = std::complex; + const Real zero_tol {static_cast(1e-6)}; + + // fabs(z) = hypot(re, im): exact Pythagorean triples. + CHECK_ULP_CLOSE(5.0, boost::math::fabs(ct(3, 4)), 0); + CHECK_ULP_CLOSE(13.0, boost::math::fabs(ct(5, 12)), 2); + CHECK_EQUAL(static_cast(0), boost::math::fabs(ct(0, 0))); + + // acos(0) = pi/2 (C99 spot); acos(1/2) = pi/3. A real input stays real. + ct r {boost::math::acos(ct(0, 0))}; + CHECK_ULP_CLOSE(half_pi, r.real(), 2); + CHECK_ABSOLUTE_ERROR(0.0, r.imag(), zero_tol); + r = boost::math::acos(ct(0.5, 0)); + CHECK_ULP_CLOSE(third_pi, r.real(), 4); + CHECK_ABSOLUTE_ERROR(0.0, r.imag(), zero_tol); + + // asin(1/2) = pi/6; asin(0) = 0. + r = boost::math::asin(ct(0.5, 0)); + CHECK_ULP_CLOSE(sixth_pi, r.real(), 4); + CHECK_ABSOLUTE_ERROR(0.0, r.imag(), zero_tol); + r = boost::math::asin(ct(0, 0)); + CHECK_ABSOLUTE_ERROR(0.0, r.real(), zero_tol); + CHECK_ABSOLUTE_ERROR(0.0, r.imag(), zero_tol); + + // acosh(0) = i*pi/2 (C99 spot); asinh(0) = 0. + r = boost::math::acosh(ct(0, 0)); + CHECK_ABSOLUTE_ERROR(0.0, r.real(), zero_tol); + CHECK_ULP_CLOSE(half_pi, r.imag(), 2); + r = boost::math::asinh(ct(0, 0)); + CHECK_ABSOLUTE_ERROR(0.0, r.real(), zero_tol); + CHECK_ABSOLUTE_ERROR(0.0, r.imag(), zero_tol); + + // atan(1) = pi/4; atan(0) = 0; atanh(0) = 0. + r = boost::math::atan(ct(1, 0)); + CHECK_ULP_CLOSE(quarter_pi, r.real(), 2); + CHECK_ABSOLUTE_ERROR(0.0, r.imag(), zero_tol); + r = boost::math::atan(ct(0, 0)); + CHECK_ABSOLUTE_ERROR(0.0, r.real(), zero_tol); + CHECK_ABSOLUTE_ERROR(0.0, r.imag(), zero_tol); + r = boost::math::atanh(ct(0, 0)); + CHECK_ABSOLUTE_ERROR(0.0, r.real(), zero_tol); + CHECK_ABSOLUTE_ERROR(0.0, r.imag(), zero_tol); + + // Principal-branch identity: acos(z) + asin(z) = pi/2 for any z. + const ct z {static_cast(0.5), static_cast(0.25)}; + const ct s {boost::math::acos(z) + boost::math::asin(z)}; + CHECK_ULP_CLOSE(half_pi, s.real(), 4); + CHECK_ABSOLUTE_ERROR(0.0, s.imag(), zero_tol); +} + +int main() +{ + test_spots("double"); + test_spots("float"); + + return boost::math::test::report_errors(); +} diff --git a/test/condition_number_test.cpp b/test/test_condition_number.cpp similarity index 100% rename from test/condition_number_test.cpp rename to test/test_condition_number.cpp diff --git a/test/test_cstdfloat.cpp b/test/test_cstdfloat.cpp index 2091f9f6d2..32401e9040 100644 --- a/test/test_cstdfloat.cpp +++ b/test/test_cstdfloat.cpp @@ -527,6 +527,44 @@ namespace test_cstdfloat { test(); } + +#if defined(BOOST_MATH_TEST_FLOAT128) + void test_hexfloat_128_func() + { + const boost::float128_t x = + BOOST_FLOAT128_C(3.141592653589793238462643383279502884); + + std::stringstream low_precision; + low_precision << std::hexfloat << std::setprecision(1) << x; + + std::stringstream high_precision; + high_precision << std::hexfloat << std::setprecision(30) << x; + + // std::hexfloat ignores precision. + BOOST_CHECK_EQUAL(low_precision.str(), high_precision.str()); + BOOST_CHECK_EQUAL(low_precision.str().substr(0, 2), "0x"); + BOOST_CHECK(low_precision.str().find('p') != std::string::npos); + + // The emitted representation should round-trip exactly. + boost::float128_t round_trip = 0; + low_precision.seekg(0); + low_precision >> round_trip; + BOOST_CHECK(!low_precision.fail()); + BOOST_CHECK_EQUAL(round_trip, x); + + // Extraction should also accept hexadecimal floating-point input directly. + std::stringstream input("0x1.8p+1"); + boost::float128_t parsed = 0; + input >> parsed; + BOOST_CHECK(!input.fail()); + BOOST_CHECK_EQUAL(parsed, BOOST_FLOAT128_C(3.0)); + + std::stringstream uppercase; + uppercase << std::uppercase << std::hexfloat << x; + BOOST_CHECK_EQUAL(uppercase.str().substr(0, 2), "0X"); + BOOST_CHECK(uppercase.str().find('P') != std::string::npos); + } +#endif #endif // defined (BOOST_FLOAT128_C) } @@ -563,5 +601,9 @@ BOOST_AUTO_TEST_CASE(test_main) // Perform an extended check of boost::float128_t including // a variety of functions from the C++ standard library. test_cstdfloat::extend_check_128_func(); + +#if defined(BOOST_MATH_TEST_FLOAT128) + test_cstdfloat::test_hexfloat_128_func(); +#endif #endif // defined (BOOST_FLOAT128_C) } diff --git a/test/cubic_hermite_test.cpp b/test/test_cubic_hermite.cpp similarity index 100% rename from test/cubic_hermite_test.cpp rename to test/test_cubic_hermite.cpp diff --git a/test/test_cubic_hermite_module.cpp b/test/test_cubic_hermite_module.cpp new file mode 100644 index 0000000000..8f15e98ea2 --- /dev/null +++ b/test/test_cubic_hermite_module.cpp @@ -0,0 +1,163 @@ +// Copyright Nick Thompson, 2020 +// 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) +// +// Module build check for cubic_hermite. Consuming the interpolators through +// `import boost.math;` confirms the exported class templates cubic_hermite, +// cardinal_cubic_hermite and cardinal_cubic_hermite_aos, along with their +// operator()/prime/domain members, are usable from a module consumer. +// The assertions exercise only mathematically-certain spline properties: +// exact reproduction of constant, affine and quadratic functions (a cubic +// Hermite segment is the unique cubic matching value and derivative at both +// endpoints, so it reproduces any polynomial of degree <= 3), plus node +// reproduction. Expected values and tolerances are taken from +// test_cubic_hermite.cpp. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#endif + +using boost::math::interpolators::cubic_hermite; +using boost::math::interpolators::cardinal_cubic_hermite; +using boost::math::interpolators::cardinal_cubic_hermite_aos; + +// A constant is reproduced exactly and its derivative vanishes everywhere. +template +void test_constant() +{ + std::vector x {0, 1, 2, 3, 9, 22, 81}; + std::vector y(x.size(), static_cast(7)); + std::vector dydx(x.size(), static_cast(0)); + + auto s = cubic_hermite(std::move(x), std::move(y), std::move(dydx)); + + const Real nodes[] {0, 1, 2, 3, 9, 22, 81}; + for (auto node : nodes) + { + CHECK_ULP_CLOSE(static_cast(7), s(node), 2); + CHECK_ULP_CLOSE(static_cast(0), s.prime(node), 2); + } + + // Interior samples: the constant and its zero slope are reproduced there too. + CHECK_ULP_CLOSE(static_cast(7), s(static_cast(1.5)), 2); + CHECK_ULP_CLOSE(static_cast(7), s(static_cast(15)), 2); + CHECK_ULP_CLOSE(static_cast(0), s.prime(static_cast(1.5)), 2); + CHECK_ULP_CLOSE(static_cast(0), s.prime(static_cast(15)), 2); + + auto [lo, hi] = s.domain(); + CHECK_ULP_CLOSE(static_cast(0), lo, 0); + CHECK_ULP_CLOSE(static_cast(81), hi, 0); +} + +// f(x) = x with unit slope: nodes are reproduced exactly and the straight line +// is reproduced at interior points. +template +void test_linear() +{ + std::vector x {0, 1, 2, 3}; + std::vector y {0, 1, 2, 3}; + std::vector dydx {1, 1, 1, 1}; + + auto s = cubic_hermite(std::move(x), std::move(y), std::move(dydx)); + + CHECK_ULP_CLOSE(static_cast(0), s(static_cast(0)), 0); + CHECK_ULP_CLOSE(static_cast(1) / static_cast(2), s(static_cast(1) / static_cast(2)), 10); + CHECK_ULP_CLOSE(static_cast(1), s(static_cast(1)), 0); + CHECK_ULP_CLOSE(static_cast(3) / static_cast(2), s(static_cast(3) / static_cast(2)), 10); + CHECK_ULP_CLOSE(static_cast(2), s(static_cast(2)), 0); + CHECK_ULP_CLOSE(static_cast(5) / static_cast(2), s(static_cast(5) / static_cast(2)), 10); + CHECK_ULP_CLOSE(static_cast(3), s(static_cast(3)), 0); + + // The derivative of an affine function is the constant slope. + CHECK_ULP_CLOSE(static_cast(1), s.prime(static_cast(1) / static_cast(2)), 2); + CHECK_ULP_CLOSE(static_cast(1), s.prime(static_cast(5) / static_cast(2)), 2); +} + +// A cubic Hermite interpolant reproduces quadratics exactly, so with +// y = x*x/2 and dydx = x we recover s(t) = t*t/2 and s'(t) = t between nodes. +template +void test_quadratic() +{ + std::vector x {0, 1, 2, 3, 4}; + std::vector y {0, static_cast(0.5), 2, static_cast(4.5), 8}; + std::vector dydx {0, 1, 2, 3, 4}; + + auto s = cubic_hermite(std::move(x), std::move(y), std::move(dydx)); + + const Real samples[] {static_cast(0.5), static_cast(1.5), static_cast(2.5), static_cast(3.5)}; + for (auto t : samples) + { + CHECK_ULP_CLOSE(t * t / static_cast(2), s(t), 10); + CHECK_ULP_CLOSE(t, s.prime(t), 150); + } +} + +// The evenly spaced (cardinal) forms reproduce the same affine function, both +// the split y/dydx interface and the array-of-structs interface. +template +void test_cardinal_linear() +{ + const Real x0 {static_cast(0)}; + const Real dx {static_cast(1)}; + + std::vector y {0, 1, 2, 3}; + std::vector dydx {1, 1, 1, 1}; + + auto s = cardinal_cubic_hermite(std::move(y), std::move(dydx), x0, dx); + + CHECK_ULP_CLOSE(static_cast(0), s(static_cast(0)), 0); + CHECK_ULP_CLOSE(static_cast(1) / static_cast(2), s(static_cast(1) / static_cast(2)), 10); + CHECK_ULP_CLOSE(static_cast(1), s(static_cast(1)), 0); + CHECK_ULP_CLOSE(static_cast(3) / static_cast(2), s(static_cast(3) / static_cast(2)), 10); + CHECK_ULP_CLOSE(static_cast(2), s(static_cast(2)), 0); + CHECK_ULP_CLOSE(static_cast(5) / static_cast(2), s(static_cast(5) / static_cast(2)), 10); + CHECK_ULP_CLOSE(static_cast(3), s(static_cast(3)), 0); + CHECK_ULP_CLOSE(static_cast(1), s.prime(static_cast(3) / static_cast(2)), 2); + + // Array-of-structs interface: data[i] = {y_i, dydx_i}. + std::vector> data(4); + for (std::size_t i {0}; i < data.size(); ++i) + { + data[i][0] = static_cast(i); + data[i][1] = static_cast(1); + } + + auto saos = cardinal_cubic_hermite_aos(std::move(data), x0, dx); + + CHECK_ULP_CLOSE(static_cast(0), saos(static_cast(0)), 0); + CHECK_ULP_CLOSE(static_cast(1) / static_cast(2), saos(static_cast(1) / static_cast(2)), 10); + CHECK_ULP_CLOSE(static_cast(1), saos(static_cast(1)), 0); + CHECK_ULP_CLOSE(static_cast(2), saos(static_cast(2)), 0); + CHECK_ULP_CLOSE(static_cast(3), saos(static_cast(3)), 0); + CHECK_ULP_CLOSE(static_cast(1), saos.prime(static_cast(3) / static_cast(2)), 2); +} + +int main() +{ + test_constant(); + test_constant(); + + test_linear(); + test_linear(); + + test_quadratic(); + test_quadratic(); + + test_cardinal_linear(); + test_cardinal_linear(); + + return boost::math::test::report_errors(); +} diff --git a/test/test_cubic_roots.cpp b/test/test_cubic_roots.cpp new file mode 100644 index 0000000000..72e92e25c4 --- /dev/null +++ b/test/test_cubic_roots.cpp @@ -0,0 +1,187 @@ +/* + * Copyright Nick Thompson, 2021 + * 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) + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif +#ifdef BOOST_HAS_FLOAT128 +#include +using boost::multiprecision::float128; +#endif + +using boost::math::tools::cubic_root_condition_number; +using boost::math::tools::cubic_root_residual; +using boost::math::tools::cubic_roots; +using std::cbrt; +using std::abs; + +template void test_zero_coefficients() { + Real a = 0; + Real b = 0; + Real c = 0; + Real d = 0; + auto roots = cubic_roots(a, b, c, d); + CHECK_EQUAL(roots[0], Real(0)); + CHECK_EQUAL(roots[1], Real(0)); + CHECK_EQUAL(roots[2], Real(0)); + + a = 1; + roots = cubic_roots(a, b, c, d); + CHECK_EQUAL(roots[0], Real(0)); + CHECK_EQUAL(roots[1], Real(0)); + CHECK_EQUAL(roots[2], Real(0)); + + a = 1; + d = 1; + // x^3 + 1 = 0: + roots = cubic_roots(a, b, c, d); + CHECK_EQUAL(roots[0], Real(-1)); + CHECK_NAN(roots[1]); + CHECK_NAN(roots[2]); + d = -1; + // x^3 - 1 = 0: + roots = cubic_roots(a, b, c, d); + CHECK_EQUAL(roots[0], Real(1)); + CHECK_NAN(roots[1]); + CHECK_NAN(roots[2]); + + d = -2; + // x^3 - 2 = 0 + roots = cubic_roots(a, b, c, d); + CHECK_ULP_CLOSE(roots[0], cbrt(Real(2)), 2); + CHECK_NAN(roots[1]); + CHECK_NAN(roots[2]); + + d = -8; + roots = cubic_roots(a, b, c, d); + CHECK_EQUAL(roots[0], Real(2)); + CHECK_NAN(roots[1]); + CHECK_NAN(roots[2]); + + // (x-1)(x-2)(x-3) = x^3 - 6x^2 + 11x - 6 + roots = cubic_roots(Real(1), Real(-6), Real(11), Real(-6)); + CHECK_ULP_CLOSE(roots[0], Real(1), 2); + CHECK_ULP_CLOSE(roots[1], Real(2), 2); + CHECK_ULP_CLOSE(roots[2], Real(3), 2); + + // Double root: + // (x+1)^2(x-2) = x^3 - 3x - 2: + // Note: This test is unstable wrt to perturbations! + roots = cubic_roots(Real(1), Real(0), Real(-3), Real(-2)); + CHECK_ULP_CLOSE(Real(-1), roots[0], 2); + CHECK_ULP_CLOSE(Real(-1), roots[1], 2); + CHECK_ULP_CLOSE(Real(2), roots[2], 2); + + std::uniform_real_distribution dis(-2, 2); + std::mt19937 gen(12345); + // Expected roots + std::array r; + int trials = 10; + for (int i = 0; i < trials; ++i) { + // Mathematica: + // Expand[(x - r0)*(x - r1)*(x - r2)] + // - r0 r1 r2 + (r0 r1 + r0 r2 + r1 r2) x + // - (r0 + r1 + r2) x^2 + x^3 + for (auto &root : r) { + root = static_cast(dis(gen)); + } + std::sort(r.begin(), r.end()); + Real a = 1; + Real b = -(r[0] + r[1] + r[2]); + Real c = r[0] * r[1] + r[0] * r[2] + r[1] * r[2]; + Real d = -r[0] * r[1] * r[2]; + + auto roots = cubic_roots(a, b, c, d); + // I could check the condition number here, but this is fine right? + if (!CHECK_ULP_CLOSE(r[0], roots[0], (std::numeric_limits::digits > 100 ? 120 : 60))) { + std::cerr << " Polynomial x^3 + " << b << "x^2 + " << c << "x + " + << d << " has roots {"; + std::cerr << r[0] << ", " << r[1] << ", " << r[2] + << "}, but the computed roots are {"; + std::cerr << roots[0] << ", " << roots[1] << ", " << roots[2] + << "}\n"; + } + CHECK_ULP_CLOSE(r[1], roots[1], 100); + CHECK_ULP_CLOSE(r[2], roots[2], (std::numeric_limits::digits > 100 ? 120 : 80)); + for (auto root : roots) { + auto res = cubic_root_residual(a, b, c, d, root); + CHECK_LE(abs(res[0]), res[1]); + } + } +} + +void test_ill_conditioned() { + // An ill-conditioned root reported by SATovstun: + // "Exact" roots produced with a high-precision calculation on Wolfram Alpha: + // NSolve[x^3 + 10000*x^2 + 200*x +1==0,x] + std::array expected_roots{-9999.97999997, + -0.010010015026300100757327057, + -0.009990014973799899662674923}; + auto roots = cubic_roots(1, 10000, 200, 1); + CHECK_ABSOLUTE_ERROR(expected_roots[0], roots[0], + std::numeric_limits::epsilon()); + + if (!(boost::math::isnan)(roots[1])) + { + // This test is so ill-conditioned, that we can't always get here. + // Test case is Clang C++20 mode on MacOS Arm. Best guess is that + // fma is behaving differently there... + CHECK_ABSOLUTE_ERROR(expected_roots[1], roots[1], 1.01e-5); + CHECK_ABSOLUTE_ERROR(expected_roots[2], roots[2], 1.01e-5); + double cond = + cubic_root_condition_number(1, 10000, 200, 1, roots[1]); + double r1 = expected_roots[1]; + // The factor of 10 is a fudge factor to make the test pass. + // Nonetheless, it does show this is basically correct: + CHECK_LE(abs(r1 - roots[1]) / abs(r1), + 10 * std::numeric_limits::epsilon() * cond); + + cond = cubic_root_condition_number(1, 10000, 200, 1, roots[2]); + double r2 = expected_roots[2]; + // The factor of 10 is a fudge factor to make the test pass. + // Nonetheless, it does show this is basically correct: + CHECK_LE(abs(r2 - roots[2]) / abs(r2), + 10 * std::numeric_limits::epsilon() * cond); + } + else + { + CHECK_NAN(roots[2]); + } + // See https://github.com/boostorg/math/issues/757: + // The polynomial is ((x+1)^2+1)*(x+1) which has roots -1, and two complex + // roots: + roots = cubic_roots(1, 3, 4, 2); + CHECK_ULP_CLOSE(roots[0], -1.0, 3); + CHECK_NAN(roots[1]); + CHECK_NAN(roots[2]); + return; +} + +int main() { + test_zero_coefficients(); + test_zero_coefficients(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_zero_coefficients(); +#endif + test_ill_conditioned(); +#ifdef BOOST_HAS_FLOAT128 + // For some reason, the quadmath is way less accurate than the + // float/double/long double: + // test_zero_coefficients(); +#endif + + return boost::math::test::report_errors(); +} diff --git a/test/test_daubechies_scaling.cpp b/test/test_daubechies_scaling.cpp new file mode 100644 index 0000000000..18a41654d7 --- /dev/null +++ b/test/test_daubechies_scaling.cpp @@ -0,0 +1,616 @@ +/* + * Copyright Nick Thompson, John Maddock 2020 + * 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) + */ + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_FLOAT128 +#include +using boost::multiprecision::float128; +#endif + +using std::sqrt; +using std::abs; +// Mallat, Theorem 7.4, characterization number 3: +// A conjugate mirror filter has p vanishing moments iff h^{(n)}(pi) = 0 for 0 <= n < p. +template +void test_daubechies_filters() +{ + using std::sqrt; + + std::cout << "Testing Daubechies filters with " << p << " vanishing moments on type " << boost::core::demangle(typeid(Real).name()) << "\n"; + Real tol = 3*std::numeric_limits::epsilon(); + using boost::math::filters::daubechies_scaling_filter; + using boost::math::filters::daubechies_wavelet_filter; + + auto h = daubechies_scaling_filter(); + auto g = daubechies_wavelet_filter(); + + auto inner = std::inner_product(h.begin(), h.end(), g.begin(), Real(0)); + CHECK_MOLLIFIED_CLOSE(0, inner, tol); + + // This is implied by Fourier transform of the two-scale dilatation equation; + // If this doesn't hold, the infinite product for m_0 diverges. + Real H0 = 0; + for (size_t j = 0; j < h.size(); ++j) + { + H0 += h[j]; + } + CHECK_MOLLIFIED_CLOSE(sqrt(static_cast(2)), H0, tol); + + // This is implied if we choose the scaling function to be an orthonormal basis of V0. + Real scaling = 0; + for (size_t j = 0; j < h.size(); ++j) { + scaling += h[j]*h[j]; + } + CHECK_MOLLIFIED_CLOSE(1, scaling, tol); + + using std::pow; + // Daubechies wavelet of order p has p vanishing moments. + // Unfortunately, the condition number of the sum is infinite. + // Hence we must scale the tolerance by the summation condition number to ensure that we don't get spurious test failures. + for (size_t k = 1; k < p && k < 9; ++k) + { + Real hk = 0; + Real abs_hk = 0; + for (size_t n = 0; n < h.size(); ++n) + { + Real t = static_cast(pow(n, k)*h[n]); + if (n & 1) + { + hk -= t; + } + else + { + hk += t; + } + abs_hk += abs(t); + } + // Multiply the tolerance by the condition number: + Real cond = abs(hk) > 0 ? abs_hk/abs(hk) : 1/std::numeric_limits::epsilon(); + if (!CHECK_MOLLIFIED_CLOSE(0, hk, 2*cond*tol)) + { + std::cerr << " The " << k << "th moment of the p = " << p << " filter did not vanish\n"; + std::cerr << " Condition number = " << abs_hk/abs(hk) << "\n"; + } + } + + // For the scaling function to be orthonormal to its integer translates, + // sum h_k h_{k-2l} = \delta_{0,l}. + // See Theoretical Numerical Analysis, Atkinson, Exercise 4.5.2. + // This is the last condition we could test to ensure that the filters are correct, + // but I'm not gonna bother because it's painful! +} + +// Test that the filters agree with Daubechies, Ten Lenctures on Wavelets, Table 6.1: +void test_agreement_with_ten_lectures() +{ + std::cout << "Testing agreement with Ten Lectures\n"; + std::array h2 = {0.4829629131445341, 0.8365163037378077, 0.2241438680420134, -0.1294095225512603}; + auto h2_ = boost::math::filters::daubechies_scaling_filter(); + for (size_t i = 0; i < h2.size(); ++i) + { + CHECK_ULP_CLOSE(h2[i], h2_[i], 3); + } + + std::array h3 = {0.3326705529500825, 0.8068915093110924, 0.4598775021184914, -0.1350110200102546, -0.0854412738820267, 0.0352262918857095}; + auto h3_ = boost::math::filters::daubechies_scaling_filter(); + for (size_t i = 0; i < h3.size(); ++i) + { + CHECK_ULP_CLOSE(h3[i], h3_[i], 5); + } + + std::array h4 = {0.2303778133088964, 0.7148465705529154, 0.6308807679298587, -0.0279837694168599, -0.1870348117190931, 0.0308413818355607, 0.0328830116668852 , -0.010597401785069}; + auto h4_ = boost::math::filters::daubechies_scaling_filter(); + for (size_t i = 0; i < h4.size(); ++i) + { + if(!CHECK_ULP_CLOSE(h4[i], h4_[i], 18)) + { + std::cerr << " Index " << i << " incorrect.\n"; + } + } + +} + +template +void test_filter_ulp_distance() +{ + std::cout << "Testing filters ULP distance between types " + << boost::core::demangle(typeid(Real1).name()) << "and" + << boost::core::demangle(typeid(Real2).name()) << "\n"; + using boost::math::filters::daubechies_scaling_filter; + auto h1 = daubechies_scaling_filter(); + auto h2 = daubechies_scaling_filter(); + + for (size_t i = 0; i < h1.size(); ++i) + { + if(!CHECK_ULP_CLOSE(h1[i], h2[i], 0)) + { + std::cerr << " Index " << i << " at order " << p << " failed tolerance check\n"; + } + } +} + + +template +void test_integer_grid() +{ + std::cout << "Testing integer grid with " << p << " vanishing moments and " << order << " derivative on type " << boost::core::demangle(typeid(Real).name()) << "\n"; + using boost::math::detail::daubechies_scaling_integer_grid; + using boost::math::tools::summation_condition_number; + Real unit_roundoff = std::numeric_limits::epsilon()/2; + auto grid = daubechies_scaling_integer_grid(); + + if constexpr (order == 0) + { + auto cond = summation_condition_number(0); + for (auto & x : grid) + { + cond += x; + } + CHECK_MOLLIFIED_CLOSE(1, cond.sum(), 6*cond.l1_norm()*unit_roundoff); + } + + if constexpr (order == 1) + { + auto cond = summation_condition_number(0); + for (size_t i = 0; i < grid.size(); ++i) { + cond += i*grid[i]; + } + CHECK_MOLLIFIED_CLOSE(Real(-1), cond.sum(), 2*cond.l1_norm()*unit_roundoff); + + // Differentiate \sum_{k} \phi(x-k) = 1 to get this: + cond = summation_condition_number(0); + for (size_t i = 0; i < grid.size(); ++i) { + cond += grid[i]; + } + CHECK_MOLLIFIED_CLOSE(Real(0), cond.sum(), 2*cond.l1_norm()*unit_roundoff); + } + + if constexpr (order == 2) + { + auto cond = summation_condition_number(0); + for (size_t i = 0; i < grid.size(); ++i) + { + cond += i*i*grid[i]; + } + CHECK_MOLLIFIED_CLOSE(Real(2), cond.sum(), 2*cond.l1_norm()*unit_roundoff); + + // Differentiate \sum_{k} \phi(x-k) = 1 to get this: + cond = summation_condition_number(0); + for (size_t i = 0; i < grid.size(); ++i) + { + cond += grid[i]; + } + CHECK_MOLLIFIED_CLOSE(Real(0), cond.sum(), 2*cond.l1_norm()*unit_roundoff); + } + + if constexpr (order == 3) + { + auto cond = summation_condition_number(0); + for (size_t i = 0; i < grid.size(); ++i) + { + cond += i*i*i*grid[i]; + } + CHECK_MOLLIFIED_CLOSE(Real(-6), cond.sum(), 2*cond.l1_norm()*unit_roundoff); + + // Differentiate \sum_{k} \phi(x-k) = 1 to get this: + cond = summation_condition_number(0); + for (size_t i = 0; i < grid.size(); ++i) + { + cond += grid[i]; + } + CHECK_MOLLIFIED_CLOSE(Real(0), cond.sum(), 2*cond.l1_norm()*unit_roundoff); + } + + if constexpr (order == 4) + { + auto cond = summation_condition_number(0); + for (size_t i = 0; i < grid.size(); ++i) + { + cond += i*i*i*i*grid[i]; + } + CHECK_MOLLIFIED_CLOSE(24, cond.sum(), 2*cond.l1_norm()*unit_roundoff); + + // Differentiate \sum_{k} \phi(x-k) = 1 to get this: + cond = summation_condition_number(0); + for (size_t i = 0; i < grid.size(); ++i) + { + cond += grid[i]; + } + CHECK_MOLLIFIED_CLOSE(Real(0), cond.sum(), 2*cond.l1_norm()*unit_roundoff); + } +} + +template +void test_dyadic_grid() +{ + std::cout << "Testing dyadic grid on type " << boost::core::demangle(typeid(Real).name()) << "\n"; + auto f = [&](auto i) + { + auto phijk = boost::math::daubechies_scaling_dyadic_grid(0); + auto phik = boost::math::detail::daubechies_scaling_integer_grid(); + BOOST_ASSERT(phik.size() == phijk.size()); + + for (size_t k = 0; k < phik.size(); ++k) + { + CHECK_ULP_CLOSE(phik[k], phijk[k], 0); + } + + for (uint64_t j = 1; j < 10; ++j) + { + phijk = boost::math::daubechies_scaling_dyadic_grid(j); + phik = boost::math::detail::daubechies_scaling_integer_grid(); + for (uint64_t l = 0; l < static_cast(phik.size()); ++l) + { + CHECK_ULP_CLOSE(phik[l], phijk[l*(uint64_t(1)<(0); + for (uint64_t l = 0; l < static_cast(phik.size()); ++l) + { + uint64_t idx = l*(uint64_t(1)<::epsilon()); + } + } + if constexpr (std::numeric_limits::digits < 30) + { + CHECK_THROW((boost::math::daubechies_scaling_dyadic_grid)(24), std::logic_error); + } + }; + + boost::hana::for_each(std::make_index_sequence<18>(), f); +} + + +// Taken from Lin, 2005, doi:10.1016/j.amc.2004.12.038, +// "Direct algorithm for computation of derivatives of the Daubechies basis functions" +void test_first_derivative() +{ +#if LDBL_MANT_DIG > 64 + // Limited precision test data means we can't test long double here... +#else + auto phi1_3 = boost::math::detail::daubechies_scaling_integer_grid(); + std::array lin_3{0.0L, 1.638452340884085725014976113635604107L, -2.23275819046313739501774225255380757L, + 0.550159358274017614990556164200803310L, 0.044146491305034055012209974717400368L, 0.0L}; + for (size_t i = 0; i < lin_3.size(); ++i) + { + if(!CHECK_ULP_CLOSE(lin_3[i], phi1_3[i], 0)) + { + std::cerr << " Index " << i << " is incorrect\n"; + } + } + + auto phi1_4 = boost::math::detail::daubechies_scaling_integer_grid(); + std::array lin_4 = {0.0L, 1.776072007522184640093776071522502761L, -2.785349397229543142492784905731245880L, 1.192452536632278174347632339082851360L, + -0.131374515184672958793518896272545740L, -0.053571028220239235953599959390993709L,0.001770396479992522798495350789431024L, 0.0L}; + + for (size_t i = 0; i < lin_4.size(); ++i) + { + if(!CHECK_ULP_CLOSE(lin_4[i], phi1_4[i], 0)) + { + std::cerr << " Index " << i << " is incorrect\n"; + } + } + + std::array lin_5 = {0.0L, 1.558326313047001366564379221011472479L, -2.436012783189551921436895932290077033L, 1.235905129801454293947038906779457610L, -0.367437713693886635994756136622838186L, + -0.021780351175646546588845564309594589L,0.032347193508143688858158541500450925L,-0.001335619912770701035229330817898250L,-0.000012168384743544313849705250972915L,0.0L}; + auto phi1_5 = boost::math::detail::daubechies_scaling_integer_grid(); + for (size_t i = 0; i < lin_5.size(); ++i) + { + if(!CHECK_ULP_CLOSE(lin_5[i], phi1_5[i], 0)) + { + std::cerr << " Index " << i << " is incorrect\n"; + } + } +#endif +} + +// Building the default grid dominates the run time of this test, and none of the checks in +// test_quadratures need its full precision. Small p (cheap, and slow to converge) and the +// representative p = 10, 19 use the default constructor so that path stays covered; +// the rest use a grid of 2^10 points per integer interval. +template +constexpr int quadrature_grid_refinements() +{ + return (p <= 5 || p == 10 || p == 19) ? -1 : 10; +} + +template +void test_quadratures() +{ + std::cout << "Testing " << p << " vanishing moment scaling function quadratures on type " << boost::core::demangle(typeid(Real).name()) << "\n"; + using boost::math::quadrature::trapezoidal; + if constexpr (p == 2) + { + // 2phi is truly bizarre, because two successive trapezoidal estimates are always bitwise equal, + // whereas the third is way different. I don' t think that's a reasonable thing to optimize for, + // so one-off it is. + Real h = Real(1)/Real(256); + auto phi = boost::math::daubechies_scaling(); + std::cout << "Scaling functor size is " << phi.bytes() << " bytes" << std::endl; + Real t = 0; + Real Q = 0; + while (t < 3) { + Q += phi(t); + t += h; + } + Q *= h; + CHECK_ULP_CLOSE(Real(1), Q, 32); + + auto [a, b] = phi.support(); + // Now hit the boundary. Much can go wrong here; this just tests for segfaults: + int samples = 500; + Real xlo = a; + Real xhi = b; + for (int i = 0; i < samples; ++i) + { + CHECK_ULP_CLOSE(Real(0), phi(xlo), 0); + CHECK_ULP_CLOSE(Real(0), phi(xhi), 0); + xlo = std::nextafter(xlo, std::numeric_limits::lowest()); + xhi = std::nextafter(xhi, (std::numeric_limits::max)()); + } + + xlo = a; + xhi = b; + for (int i = 0; i < samples; ++i) { + CHECK_LE(std::abs(phi(xlo)), Real(5)); + CHECK_LE(std::abs(phi(xhi)), Real(5)); + xlo = std::nextafter(xlo, (std::numeric_limits::max)()); + xhi = std::nextafter(xhi, std::numeric_limits::lowest()); + } + + return; + } + else if constexpr (p > 2) + { + auto phi = boost::math::daubechies_scaling(quadrature_grid_refinements

    ()); + std::cout << "Scaling functor size is " << phi.bytes() << " bytes" << std::endl; + + Real tol = std::numeric_limits::epsilon(); + Real error_estimate = std::numeric_limits::quiet_NaN(); + Real L1 = std::numeric_limits::quiet_NaN(); + auto [a, b] = phi.support(); + Real Q = trapezoidal(phi, a, b, tol, 15, &error_estimate, &L1); + if (!CHECK_MOLLIFIED_CLOSE(Real(1), Q, Real(0.0001))) + { + std::cerr << " Quadrature of " << p << " vanishing moment scaling function is not equal 1.\n"; + std::cerr << " Error estimate is " << error_estimate << ", L1 norm is " << L1 << "\n"; + } + + auto phi_sq = [phi](Real x) { Real t = phi(x); return t*t; }; + Q = trapezoidal(phi_sq, a, b, tol, 15, &error_estimate, &L1); + if (!CHECK_MOLLIFIED_CLOSE(Real(1), Q, 20*std::sqrt(std::numeric_limits::epsilon())/(p*p))) + { + std::cerr << " L2 norm of " << p << " vanishing moment scaling function is not equal 1.\n"; + std::cerr << " Error estimate is " << error_estimate << ", L1 norm is " << L1 << "\n"; + } + + std::random_device rd; + Real t = static_cast(rd())/static_cast((rd.max)()); + Real S = phi(t); + Real dS = phi.prime(t); + while (t < b) + { + t += 1; + S += phi(t); + dS += phi.prime(t); + } + + if(!CHECK_ULP_CLOSE(Real(1), S, 64)) + { + std::cerr << " Normalizing sum for " << p << " vanishing moment scaling function is incorrect.\n"; + } + + // The p = 3, 4 convergence rate is very slow, making this produce false positives: + if constexpr(p > 4) + { + if(!CHECK_MOLLIFIED_CLOSE(Real(0), dS, 100*std::sqrt(std::numeric_limits::epsilon()))) + { + std::cerr << " Derivative of normalizing sum for " << p << " vanishing moment scaling function doesn't vanish.\n"; + } + } + + // Test boundary for segfaults: + int samples = 500; + Real xlo = a; + Real xhi = b; + for (int i = 0; i < samples; ++i) + { + CHECK_ULP_CLOSE(Real(0), phi(xlo), 0); + CHECK_ULP_CLOSE(Real(0), phi(xhi), 0); + if constexpr (p > 2) { + CHECK_LE(std::abs(phi.prime(xlo)), Real(5)); + CHECK_LE(std::abs(phi.prime(xhi)), Real(5)); + if constexpr (p > 5) { + CHECK_LE(std::abs(phi.double_prime(xlo)), Real(5)); + CHECK_LE(std::abs(phi.double_prime(xhi)), Real(5)); + } + } + xlo = std::nextafter(xlo, std::numeric_limits::lowest()); + xhi = std::nextafter(xhi, (std::numeric_limits::max)()); + } + + xlo = a; + xhi = b; + for (int i = 0; i < samples; ++i) { + CHECK_LE(std::abs(phi(xlo)), Real(5)); + CHECK_LE(std::abs(phi(xhi)), Real(5)); + xlo = std::nextafter(xlo, (std::numeric_limits::max)()); + xhi = std::nextafter(xhi, std::numeric_limits::lowest()); + } + } +} + +// Exercise both derivative-capable interpolators at points between grid nodes. +// Differentiating prime() checks double_prime() independently of the grid generator. +// Use coarse grids so the finite-difference stencil fits inside an interpolation interval. +template +void test_refinement_derivatives(int refinements) +{ + using boost::math::differentiation::finite_difference_derivative; + auto f = boost::math::daubechies_scaling(refinements); + auto value = [&](Real x) { return f(x); }; + auto prime = [&](Real x) { return f.prime(x); }; + const Real tolerance = std::is_same_v ? Real(0.005) : Real(0.000001); + for (int i = 0; i < 8; ++i) + { + Real x = Real(p/3) + Real(i)/8 + Real(1)/32; + auto d1 = finite_difference_derivative(value, x); + auto d2 = finite_difference_derivative(prime, x); + if constexpr (std::is_same_v) + { + // The automatic float step is too large for the curvature of these + // interpolants. This dyadic step stays well inside the grid cell. + Real h = Real(1)/1024; + d1 = (value(x + h) - value(x - h))/(2*h); + d2 = (prime(x + h) - prime(x - h))/(2*h); + } + CHECK_MOLLIFIED_CLOSE(d1, f.prime(x), tolerance); + CHECK_MOLLIFIED_CLOSE(d2, f.double_prime(x), tolerance); + } +} + +// At shared dyadic nodes, changing the refinement must preserve function values. +template +void test_explicit_refinement() +{ + auto coarse = boost::math::daubechies_scaling(3); + auto fine = boost::math::daubechies_scaling(4); + CHECK_EQUAL(true, fine.bytes() > coarse.bytes()); + auto [a, b] = coarse.support(); + for (Real x = a; x <= b; x += Real(1)/8) + { + CHECK_MOLLIFIED_CLOSE(coarse(x), fine(x), 32*std::numeric_limits::epsilon()); + if constexpr (p > 2) + { + CHECK_MOLLIFIED_CLOSE(coarse.prime(x), fine.prime(x), 32*std::numeric_limits::epsilon()); + } + if constexpr (p >= 6) + { + CHECK_MOLLIFIED_CLOSE(coarse.double_prime(x), fine.double_prime(x), 32*std::numeric_limits::epsilon()); + } + } +} + +int main() +{ + #ifndef __MINGW32__ + boost::hana::for_each(std::make_index_sequence<18>(), [&](auto i){ + test_quadratures(); + test_quadratures(); + }); + test_refinement_derivatives(4); + test_refinement_derivatives(-2); + test_refinement_derivatives(4); + test_refinement_derivatives(4); + boost::hana::for_each(std::make_index_sequence<18>(), [&](auto i) { + test_explicit_refinement(); + test_explicit_refinement(); + }); + + test_agreement_with_ten_lectures(); + + boost::hana::for_each(std::make_index_sequence<19>(), [&](auto i){ + test_daubechies_filters(); + test_daubechies_filters(); + test_daubechies_filters(); + }); + + test_first_derivative(); + + // All scaling functions have a first derivative. + boost::hana::for_each(std::make_index_sequence<18>(), [&](auto idx){ + test_integer_grid(); + test_integer_grid(); + test_integer_grid(); + test_integer_grid(); + test_integer_grid(); + test_integer_grid(); + #ifdef BOOST_HAS_FLOAT128 + test_integer_grid(); + test_integer_grid(); + #endif + }); + + // 4-tap (2 vanishing moment) scaling function does not have a second derivative; + // all other scaling functions do. + boost::hana::for_each(std::make_index_sequence<17>(), [&](auto idx){ + test_integer_grid(); + test_integer_grid(); + test_integer_grid(); + #ifdef BOOST_HAS_FLOAT128 + test_integer_grid(); + #endif + }); + + // 8-tap filter (4 vanishing moments) is the first to have a third derivative. + boost::hana::for_each(std::make_index_sequence<16>(), [&](auto idx){ + test_integer_grid(); + test_integer_grid(); + test_integer_grid(); + #ifdef BOOST_HAS_FLOAT128 + test_integer_grid(); + #endif + }); + + // 10-tap filter (5 vanishing moments) is the first to have a fourth derivative. + boost::hana::for_each(std::make_index_sequence<15>(), [&](auto idx){ + test_integer_grid(); + test_integer_grid(); + test_integer_grid(); + #ifdef BOOST_HAS_FLOAT128 + test_integer_grid(); + #endif + }); + + test_dyadic_grid(); + test_dyadic_grid(); + test_dyadic_grid(); + #ifdef BOOST_HAS_FLOAT128 + test_dyadic_grid(); + #endif + + + #ifdef BOOST_HAS_FLOAT128 + boost::hana::for_each(std::make_index_sequence<19>(), [&](auto i){ + test_filter_ulp_distance(); + test_filter_ulp_distance(); + test_filter_ulp_distance(); + }); + + boost::hana::for_each(std::make_index_sequence<19>(), [&](auto i){ + test_daubechies_filters(); + }); + #endif + #endif // compiler guard for CI + return boost::math::test::report_errors(); +} diff --git a/test/test_daubechies_wavelet.cpp b/test/test_daubechies_wavelet.cpp new file mode 100644 index 0000000000..bae2c8aebb --- /dev/null +++ b/test/test_daubechies_wavelet.cpp @@ -0,0 +1,231 @@ +/* + * Copyright Nick Thompson, 2020 + * 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) + */ + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_FLOAT128 +#include +using boost::multiprecision::float128; +#endif + + +using boost::math::constants::pi; +using boost::math::constants::root_two; + +template +void test_exact_value() +{ + // The global phase of the wavelet is not constrained by anything other than convention. + // Make sure that our conventions match the rest of the world: + auto psi = boost::math::daubechies_wavelet(2); + Real computed = psi(1); + Real expected = -1.366025403784439; + CHECK_MOLLIFIED_CLOSE(expected, computed, 0.0001); +} + +// Building the default grid dominates the run time of this test, and none of the checks in +// test_quadratures need its full precision. Small p (cheap, and slow to converge) and the +// representative p = 10, 19 use the default constructor so that path stays covered; +// the rest use a grid of 2^10 points per integer interval. +template +constexpr int quadrature_grid_refinements() +{ + return (p <= 5 || p == 10 || p == 19) ? -1 : 10; +} + +template +void test_quadratures() +{ + std::cout << "Testing quadratures of " << p << " vanishing moment Daubechies wavelet on type " << boost::core::demangle(typeid(Real).name()) << "\n"; + using boost::math::quadrature::trapezoidal; + auto psi = boost::math::daubechies_wavelet(quadrature_grid_refinements

    ()); + std::cout << "Wavelet functor size is " << psi.bytes() << " bytes" << std::endl; + + Real tol = std::numeric_limits::epsilon(); + Real error_estimate = std::numeric_limits::quiet_NaN(); + Real L1 = std::numeric_limits::quiet_NaN(); + auto [a, b] = psi.support(); + CHECK_ULP_CLOSE(Real(-p+1), a, 0); + CHECK_ULP_CLOSE(Real(p), b, 0); + // A wavelet is a function of zero average; ensure the quadrature over its support is zero. + Real Q = trapezoidal(psi, a, b, tol, 15, &error_estimate, &L1); + if (!CHECK_MOLLIFIED_CLOSE(Real(0), Q, Real(0.0001))) + { + std::cerr << " Quadrature of " << p << " vanishing moment wavelet does not vanish.\n"; + std::cerr << " Error estimate: " << error_estimate << ", L1 norm: " << L1 << "\n"; + } + auto psi_sq = [psi](Real x) { + Real t = psi(x); + return t*t; + }; + Q = trapezoidal(psi_sq, a, b, tol, 15, &error_estimate, &L1); + Real quad_tol = 2000*std::sqrt(std::numeric_limits::epsilon())/(p*p*p); + if (!CHECK_MOLLIFIED_CLOSE(Real(1), Q, quad_tol)) + { + std::cerr << " L2 norm of " << p << " vanishing moment wavelet does not vanish.\n"; + std::cerr << " Error estimate: " << error_estimate << ", L1 norm: " << L1 << "\n"; + } + // psi is orthogonal to its integer translates: \int \psi(x-k) \psi(x) \, \mathrm{d}x = 0 + // g_n = 1/sqrt(2) (Mallat, 7.55) + + // Now hit the boundary. Much can go wrong here; this just tests for segfaults: + int samples = 500; + Real xlo = a; + Real xhi = b; + for (int i = 0; i < samples; ++i) + { + CHECK_ULP_CLOSE(Real(0), psi(xlo), 0); + CHECK_ULP_CLOSE(Real(0), psi(xhi), 0); + if constexpr (p > 2) + { + CHECK_ULP_CLOSE(Real(0), psi.prime(xlo), 0); + CHECK_ULP_CLOSE(Real(0), psi.prime(xhi), 0); + if constexpr (p >= 6) { + CHECK_ULP_CLOSE(Real(0), psi.double_prime(xlo), 0); + CHECK_ULP_CLOSE(Real(0), psi.double_prime(xhi), 0); + } + } + xlo = std::nextafter(xlo, std::numeric_limits::lowest()); + xhi = std::nextafter(xhi, (std::numeric_limits::max)()); + } + + xlo = a; + xhi = b; + for (int i = 0; i < samples; ++i) { + std::cout << std::setprecision(std::numeric_limits::max_digits10); + CHECK_LE(std::abs(psi(xlo)), Real(5)); + CHECK_LE(std::abs(psi(xhi)), Real(5)); + if constexpr (p > 2) + { + CHECK_LE(std::abs(psi.prime(xlo)), Real(5)); + CHECK_LE(std::abs(psi.prime(xhi)), Real(5)); + if constexpr (p >= 6) + { + CHECK_LE(std::abs(psi.double_prime(xlo)), Real(5)); + CHECK_LE(std::abs(psi.double_prime(xhi)), Real(5)); + } + } + xlo = std::nextafter(xlo, (std::numeric_limits::max)()); + xhi = std::nextafter(xhi, std::numeric_limits::lowest()); + } +} + +// Exercise both derivative-capable interpolators at points between grid nodes. +// Differentiating prime() checks double_prime() independently of the grid generator. +// Use coarse grids so the finite-difference stencil fits inside an interpolation interval. +template +void test_refinement_derivatives(int refinements) +{ + using boost::math::differentiation::finite_difference_derivative; + auto f = boost::math::daubechies_wavelet(refinements); + auto value = [&](Real x) { return f(x); }; + auto prime = [&](Real x) { return f.prime(x); }; + const Real tolerance = std::is_same_v ? Real(0.005) : Real(0.000001); + for (int i = 0; i < 8; ++i) + { + Real x = Real(0) + Real(i)/8 + Real(1)/32; + auto d1 = finite_difference_derivative(value, x); + auto d2 = finite_difference_derivative(prime, x); + if constexpr (std::is_same_v) + { + // The automatic float step is too large for the curvature of these + // interpolants. This dyadic step stays well inside the grid cell. + Real h = Real(1)/1024; + d1 = (value(x + h) - value(x - h))/(2*h); + d2 = (prime(x + h) - prime(x - h))/(2*h); + } + CHECK_MOLLIFIED_CLOSE(d1, f.prime(x), tolerance); + CHECK_MOLLIFIED_CLOSE(d2, f.double_prime(x), tolerance); + } +} + +// At shared dyadic nodes, changing the refinement must preserve function values. +template +void test_explicit_refinement() +{ + auto coarse = boost::math::daubechies_wavelet(3); + auto fine = boost::math::daubechies_wavelet(4); + CHECK_EQUAL(true, fine.bytes() > coarse.bytes()); + auto [a, b] = coarse.support(); + for (Real x = a; x <= b; x += Real(1)/8) + { + CHECK_MOLLIFIED_CLOSE(coarse(x), fine(x), 32*std::numeric_limits::epsilon()); + if constexpr (p > 2) + { + CHECK_MOLLIFIED_CLOSE(coarse.prime(x), fine.prime(x), 32*std::numeric_limits::epsilon()); + } + if constexpr (p >= 6) + { + CHECK_MOLLIFIED_CLOSE(coarse.double_prime(x), fine.double_prime(x), 32*std::numeric_limits::epsilon()); + } + } +} + +template +void test_haar_wavelet() +{ + for (int refinements : {-2, -1, 3}) + { + auto psi = boost::math::daubechies_wavelet(refinements); + CHECK_EQUAL(Real(0), psi.support().first); + CHECK_EQUAL(Real(1), psi.support().second); + for (Real x : {Real(-1), Real(0), Real(0.5), Real(1), Real(2)}) + { + CHECK_EQUAL(Real(0), psi(x)); + } + CHECK_EQUAL(Real(1), psi(Real(0.25))); + CHECK_EQUAL(Real(-1), psi(Real(0.75))); + CHECK_EQUAL(Real(1), psi(std::nextafter(Real(0.5), Real(0)))); + CHECK_EQUAL(Real(-1), psi(std::nextafter(Real(0.5), Real(1)))); + } + CHECK_THROW((boost::math::daubechies_wavelet(0)), std::domain_error); +} + +int main() +{ + #ifndef __MINGW32__ + try + { + test_haar_wavelet(); + test_haar_wavelet(); + test_exact_value(); + + boost::hana::for_each(std::make_index_sequence<17>(), [&](auto i) { + test_quadratures(); + test_quadratures(); + }); + test_refinement_derivatives(4); + test_refinement_derivatives(-2); + test_refinement_derivatives(4); + test_refinement_derivatives(4); + boost::hana::for_each(std::make_index_sequence<18>(), [&](auto i) { + test_explicit_refinement(); + test_explicit_refinement(); + }); + } + catch (std::bad_alloc) + { + // not much we can do about this, this test uses lots of memory! + } + #endif + return boost::math::test::report_errors(); +} diff --git a/test/test_difference.cpp b/test/test_difference.cpp index 7f4ff4f8f2..55e34759ee 100644 --- a/test/test_difference.cpp +++ b/test/test_difference.cpp @@ -14,7 +14,7 @@ #include template -void test_value(const T& val, const char* name) +void test_value(const T& val, const char* /*name*/) { using namespace boost::math; using std::fabs; @@ -62,7 +62,7 @@ void test_value(const T& val, const char* name) } template -void test_values(const T& val, const char* name) +void test_values(const T& /*val*/, const char* name) { static const T a = static_cast(1.3456724e22); static const T b = static_cast(1.3456724e-22); diff --git a/test/test_differential_evolution.cpp b/test/test_differential_evolution.cpp new file mode 100644 index 0000000000..6f932ee0c6 --- /dev/null +++ b/test/test_differential_evolution.cpp @@ -0,0 +1,222 @@ +/* + * Copyright Nick Thompson, 2023 + * 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) + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" +#include "test_functions_for_optimization.hpp" +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif + +using boost::math::optimization::differential_evolution; +using boost::math::optimization::differential_evolution_parameters; +using boost::math::optimization::validate_differential_evolution_parameters; +using boost::math::optimization::detail::best_indices; +using boost::math::optimization::detail::random_initial_population; +using boost::math::optimization::detail::validate_initial_guess; + +// The default is one thread per hardware thread, and the library spawns and joins that many threads every +// generation. That is expensive on many-core machines and makes the random streams depend on the machine. +// A fixed small number still exercises the multithreaded path. +constexpr unsigned test_threads = 2; + +void test_random_initial_population() { + std::array lower_bounds = {-5, -5}; + std::array upper_bounds = {5, 5}; + size_t n = 500; + std::mt19937_64 gen(12345); + auto population = random_initial_population(lower_bounds, upper_bounds, n, gen); + CHECK_EQUAL(population.size(), n); + for (auto const & individual : population) { + validate_initial_guess(individual, lower_bounds, upper_bounds); + } + // Reproducibility: + gen.seed(12345); + auto population2 = random_initial_population(lower_bounds, upper_bounds, n, gen); + for (size_t i = 0; i < n; ++i) { + for (size_t j = 0; j < 2; ++j) { + CHECK_EQUAL(population[i][j], population2[i][j]); + } + } +} +void test_nan_sorting() { + auto nan = std::numeric_limits::quiet_NaN(); + std::vector v{-1.2, nan, -3.5, 2.3, nan, 8.7, -4.2}; + auto indices = best_indices(v); + CHECK_EQUAL(indices[0], size_t(6)); + CHECK_EQUAL(indices[1], size_t(2)); + CHECK_EQUAL(indices[2], size_t(0)); + CHECK_EQUAL(indices[3], size_t(3)); + CHECK_EQUAL(indices[4], size_t(5)); + CHECK_NAN(v[indices[5]]); + CHECK_NAN(v[indices[6]]); +} + +void test_parameter_checks() { + using ArgType = std::array; + auto de_params = differential_evolution_parameters(); + de_params.threads = 0; + bool caught = false; + try { + validate_differential_evolution_parameters(de_params); + } catch(std::exception const &) { + caught = true; + } + CHECK_TRUE(caught); + caught = false; + de_params = differential_evolution_parameters(); + de_params.NP = 1; + try { + validate_differential_evolution_parameters(de_params); + } catch(std::exception const &) { + caught = true; + } + CHECK_TRUE(caught); +} +template void test_ackley() { + std::cout << "Testing differential evolution on the Ackley function . . .\n"; + using ArgType = std::array; + auto de_params = differential_evolution_parameters(); + de_params.threads = test_threads; + de_params.lower_bounds = {-5, -5}; + de_params.upper_bounds = {5, 5}; + + std::mt19937_64 gen(12345); + auto local_minima = differential_evolution(ackley, de_params, gen); + CHECK_LE(std::abs(local_minima[0]), 10 * std::numeric_limits::epsilon()); + CHECK_LE(std::abs(local_minima[1]), 10 * std::numeric_limits::epsilon()); + + // Does it work with a lambda? + auto ack = [](std::array const &x) { return ackley(x); }; + local_minima = differential_evolution(ack, de_params, gen); + CHECK_LE(std::abs(local_minima[0]), 10 * std::numeric_limits::epsilon()); + CHECK_LE(std::abs(local_minima[1]), 10 * std::numeric_limits::epsilon()); + + // Test that if an intial guess is the exact solution, the returned solution is the exact solution: + std::array initial_guess{0, 0}; + de_params.initial_guess = &initial_guess; + local_minima = differential_evolution(ack, de_params, gen); + CHECK_EQUAL(local_minima[0], Real(0)); + CHECK_EQUAL(local_minima[1], Real(0)); +} + +template void test_rosenbrock_saddle() { + std::cout << "Testing differential evolution on the Rosenbrock saddle . . .\n"; + using ArgType = std::array; + auto de_params = differential_evolution_parameters(); + de_params.threads = test_threads; + de_params.lower_bounds = {0.5, 0.5}; + de_params.upper_bounds = {2.048, 2.048}; + std::mt19937_64 gen(234568); + auto local_minima = differential_evolution(rosenbrock_saddle, de_params, gen); + + CHECK_ABSOLUTE_ERROR(Real(1), local_minima[0], 10 * std::numeric_limits::epsilon()); + CHECK_ABSOLUTE_ERROR(Real(1), local_minima[1], 10 * std::numeric_limits::epsilon()); + + // Does cancellation work? + std::atomic cancel = true; + gen.seed(12345); + local_minima = + differential_evolution(rosenbrock_saddle, de_params, gen, std::numeric_limits::quiet_NaN(), &cancel); + CHECK_GE(std::abs(local_minima[0] - Real(1)), std::sqrt(std::numeric_limits::epsilon())); +} + +template void test_rastrigin() { + std::cout << "Testing differential evolution on the Rastrigin function . . .\n"; + using ArgType = std::vector; + auto de_params = differential_evolution_parameters(); + de_params.threads = test_threads; + de_params.lower_bounds.resize(8, static_cast(-5.12)); + de_params.upper_bounds.resize(8, static_cast(5.12)); + std::mt19937_64 gen(34567); + auto local_minima = differential_evolution(rastrigin, de_params, gen); + for (auto x : local_minima) { + CHECK_ABSOLUTE_ERROR(x, Real(0), Real(2e-4)); + } + + // By definition, the value of the function which a target value is provided must be <= target_value. + auto target_value = static_cast(1e-3); + local_minima = differential_evolution(rastrigin, de_params, gen, target_value); + CHECK_LE(rastrigin(local_minima), target_value); +} + +// Tests NaN return types and return type != input type: +void test_sphere() { + std::cout << "Testing differential evolution on the sphere function . . .\n"; + using ArgType = std::vector; + auto de_params = differential_evolution_parameters(); + de_params.threads = test_threads; + de_params.lower_bounds.resize(3, -1); + de_params.upper_bounds.resize(3, 1); + de_params.NP *= 10; + de_params.max_generations *= 10; + de_params.crossover_probability = 0.9; + double target_value = 1e-8; + de_params.threads = 1; + std::mt19937_64 gen(56789); + auto local_minima = differential_evolution(sphere, de_params, gen, target_value); + CHECK_LE(sphere(local_minima), target_value); + // Check computational reproducibility: + gen.seed(56789); + auto local_minima_2 = differential_evolution(sphere, de_params, gen, target_value); + for (size_t i = 0; i < local_minima.size(); ++i) { + CHECK_EQUAL(local_minima[i], local_minima_2[i]); + } +} + +template +void test_three_hump_camel() { + std::cout << "Testing differential evolution on the three hump camel . . .\n"; + using ArgType = std::array; + auto de_params = differential_evolution_parameters(); + de_params.threads = test_threads; + de_params.lower_bounds[0] = -5.0; + de_params.lower_bounds[1] = -5.0; + de_params.upper_bounds[0] = 5.0; + de_params.upper_bounds[1] = 5.0; + std::mt19937_64 gen(56789); + auto local_minima = differential_evolution(three_hump_camel, de_params, gen); + for (auto x : local_minima) { + CHECK_ABSOLUTE_ERROR(0.0f, x, 2e-4f); + } +} + +template +void test_beale() { + std::cout << "Testing differential evolution on the Beale function . . .\n"; + using ArgType = std::array; + auto de_params = differential_evolution_parameters(); + de_params.threads = test_threads; + de_params.lower_bounds[0] = -5.0; + de_params.lower_bounds[1] = -5.0; + de_params.upper_bounds[0]= 5.0; + de_params.upper_bounds[1]= 5.0; + std::mt19937_64 gen(56789); + auto local_minima = differential_evolution(beale, de_params, gen); + CHECK_ABSOLUTE_ERROR(Real(3), local_minima[0], Real(2e-4)); + CHECK_ABSOLUTE_ERROR(Real(1)/Real(2), local_minima[1], Real(2e-4)); +} + +int main() { + +#if defined(__clang__) || defined(_MSC_VER) + test_ackley(); + test_ackley(); + test_rosenbrock_saddle(); + test_rastrigin(); + test_three_hump_camel(); + test_beale(); +#endif + test_sphere(); + test_parameter_checks(); + return boost::math::test::report_errors(); +} diff --git a/test/test_digamma_simple.cpp b/test/test_digamma_simple.cpp index 30aeb29e4b..ab4af50b6e 100644 --- a/test/test_digamma_simple.cpp +++ b/test/test_digamma_simple.cpp @@ -8,7 +8,12 @@ #include "sycl/sycl.hpp" #endif +#ifndef BOOST_MATH_BUILD_MODULE #include +#else +import boost.math; +#endif + #include "math_unit_test.hpp" template diff --git a/test/test_dist_deduction_guides.cpp b/test/test_dist_deduction_guides.cpp index b814ee1503..a65d6a1e0e 100644 --- a/test/test_dist_deduction_guides.cpp +++ b/test/test_dist_deduction_guides.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include //#include //#include @@ -84,6 +85,10 @@ int main() test_deduction_guide(1); test_deduction_guide(1, 1); + test_deduction_guide(0); + test_deduction_guide(0, 1); + test_deduction_guide(0, 1, 0); + test_deduction_guide(1); test_deduction_guide(1); diff --git a/test/test_double_exponential_eigen.cpp b/test/test_double_exponential_eigen.cpp new file mode 100644 index 0000000000..18a0baefa8 --- /dev/null +++ b/test/test_double_exponential_eigen.cpp @@ -0,0 +1,262 @@ +// Copyright Nick Thompson, 2026 +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +#include +#include +#include +#include +#include +#include +#include +#include +#include "math_unit_test.hpp" + +namespace q = boost::math::quadrature; +using matrix = Eigen::MatrixXcd; +const matrix zero = matrix::Zero(2, 3); +const matrix value = (matrix(2, 3) << std::complex(1, 2), 2., -3., 4., 0., std::complex(-2, 1)).finished(); +const auto norm = [](const matrix& m) { return m.stableNorm(); }; +const auto scaled_norm = [](const matrix& m) { return 8*m.stableNorm(); }; +const double inf = std::numeric_limits::infinity(); +const double pi = boost::math::constants::pi(); + +void check(const matrix& actual, const matrix& expected, double tolerance = 1e-9) +{ + CHECK_EQUAL(actual.rows(), expected.rows()); + CHECK_EQUAL(actual.cols(), expected.cols()); + CHECK_ABSOLUTE_ERROR(0, (actual-expected).norm(), tolerance); +} + +void exp_sinh_matrices() +{ + q::exp_sinh integrator; + unsigned calls = 0; + const auto f = [&](double x) -> matrix { ++calls; return value*std::exp(-std::sqrt(x)); }; + double error = 0, l1 = 0; + std::size_t levels = 0; + matrix coarse = integrator.integrate(f, zero, norm, 1e-3); + const unsigned coarse_calls = calls; + calls = 0; + matrix result = integrator.integrate(f, zero, norm, 1e-11, &error, &l1, &levels); + check(result, value*2); + CHECK_TRUE(calls > coarse_calls); + CHECK_GE(levels, static_cast(2)); + CHECK_TRUE(error < 1e-9); + CHECK_ULP_CLOSE(norm(value)*2, l1, 8); + const unsigned refined_calls = calls; + calls = 0; + double scaled_error = 0, scaled_l1 = 0; + check(integrator.integrate(f, zero, scaled_norm, 1e-11, &scaled_error, &scaled_l1), result); + CHECK_EQUAL(calls, refined_calls); + CHECK_ULP_CLOSE(8*error, scaled_error, 4); + CHECK_ULP_CLOSE(8*l1, scaled_l1, 4); + check(integrator.integrate(f, 0., inf, zero, norm), value*2); + const auto shifted = [&](double x) -> matrix { return value*std::exp(-(x-2)); }; + check(integrator.integrate(shifted, 2., inf, zero, norm), value); + const auto left = [&](double x) -> matrix { return value*std::exp(x-2); }; + check(integrator.integrate(left, -inf, 2., zero, norm), value); + // Distinct entrywise decay rates have independently known integrals. + const auto mixed = [](double x) -> matrix { + matrix m(2, 3); + for (Eigen::Index i = 0; i < m.rows(); ++i) + for (Eigen::Index j = 0; j < m.cols(); ++j) + m(i, j) = value(i, j)*std::exp(-(1+i+2*j)*x); + return m; + }; + matrix expected(2, 3); + for (Eigen::Index i = 0; i < expected.rows(); ++i) + for (Eigen::Index j = 0; j < expected.cols(); ++j) + expected(i, j) = value(i, j)/double(1+i+2*j); + check(integrator.integrate(mixed, zero, norm), expected); + CHECK_THROW(integrator.integrate(f, 0., 1., zero, norm), std::domain_error); +} + +void sinh_sinh_matrices() +{ + q::sinh_sinh integrator; + unsigned calls = 0; + const auto f = [&](double x) -> matrix { ++calls; return value*std::exp(-x*x); }; + double error = 0, l1 = 0; + std::size_t levels = 0; + integrator.integrate(f, zero, norm, 1e-3); + const unsigned coarse_calls = calls; + calls = 0; + matrix result = integrator.integrate(f, zero, norm, 1e-11, &error, &l1, &levels); + check(result, value*std::sqrt(pi)); + CHECK_TRUE(calls > coarse_calls); + CHECK_GE(levels, static_cast(2)); + CHECK_TRUE(error < 1e-9); + CHECK_ULP_CLOSE(norm(value)*std::sqrt(pi), l1, 4); + const unsigned refined_calls = calls; + calls = 0; + double scaled_error = 0, scaled_l1 = 0; + check(integrator.integrate(f, zero, scaled_norm, 1e-11, &scaled_error, &scaled_l1), result); + CHECK_EQUAL(calls, refined_calls); + CHECK_ULP_CLOSE(8*error, scaled_error, 4); + CHECK_ULP_CLOSE(8*l1, scaled_l1, 4); + const auto constant = [&](double) -> matrix { return value; }; + CHECK_THROW(integrator.integrate(constant, zero, norm), std::domain_error); +} + +void tanh_sinh_matrices() +{ + q::tanh_sinh integrator; + unsigned calls = 0; + // A narrow analytic peak, with a known antiderivative, needs refinement. + const auto f = [&](double x) -> matrix { ++calls; return value/(1+10000*(x-0.37)*(x-0.37)); }; + const double exact = (std::atan(63.)+std::atan(37.))/100; + integrator.integrate(f, 0., 1., zero, norm, 1e-3); + const unsigned coarse_calls = calls; + calls = 0; + double error = 0, l1 = 0; + std::size_t levels = 0; + matrix result = integrator.integrate(f, 0., 1., zero, norm, 1e-11, &error, &l1, &levels); + check(result, value*exact); + CHECK_TRUE(calls > coarse_calls); + CHECK_TRUE(levels > 4); + CHECK_TRUE(error < 1e-9); + CHECK_ULP_CLOSE(norm(value)*exact, l1, 12); + const unsigned refined_calls = calls; + calls = 0; + double scaled_error = 0, scaled_l1 = 0; + check(integrator.integrate(f, 0., 1., zero, scaled_norm, 1e-11, &scaled_error, &scaled_l1), result); + CHECK_EQUAL(calls, refined_calls); + CHECK_ULP_CLOSE(8*error, scaled_error, 4); + CHECK_ULP_CLOSE(8*l1, scaled_l1, 4); + check(integrator.integrate(f, 1., 0., zero, norm, 1e-11), -result); + const auto smooth = [&](double x) -> matrix { return value*std::exp(x); }; + check(integrator.integrate(smooth, zero, norm), value*(std::exp(1.)-std::exp(-1.))); + const auto gaussian = [&](double x) -> matrix { return value*std::exp(-x*x); }; + check(integrator.integrate(gaussian, -inf, inf, zero, norm), value*std::sqrt(pi)); + const auto right = [&](double x) -> matrix { return value*std::exp(-x); }; + const auto left = [&](double x) -> matrix { return value*std::exp(x); }; + check(integrator.integrate(right, 0., inf, zero, norm), value); + check(integrator.integrate(left, -inf, 0., zero, norm), value); + // Endpoint-distance functor: avoids cancellation in 1-x*x near +/-1. + const auto endpoint = [&](double, double complement) -> matrix { + const double c = std::abs(complement); + return value/std::sqrt(c*(2-c)); + }; + check(integrator.integrate(endpoint, zero, norm), value*pi); + check(integrator.integrate(endpoint, -1., 1., zero, norm), value*pi); + check(integrator.integrate(endpoint, 1., -1., zero, norm), -value*pi); + const auto shifted_endpoint = [&](double x, double complement) -> matrix { + CHECK_GE(x, 2.); + CHECK_LE(x, 6.); // x can round to the endpoint; complement retains distance. + const double c = std::abs(complement); + return value/std::sqrt(c*(4-c)); + }; + check(integrator.integrate(shifted_endpoint, 2., 6., zero, norm, 1e-11, &error, &l1), value*pi); + CHECK_ULP_CLOSE(norm(value)*pi, l1, 4); + // An endpoint singularity in the ordinary one-argument interface. + const auto logarithm = [&](double x) -> matrix { return value*std::log(x); }; + check(integrator.integrate(logarithm, 0., 1., zero, norm), -value); + calls = 0; + check(integrator.integrate(f, 2., 2., zero, norm, 1e-11, &error, &l1, &levels), zero); + CHECK_EQUAL(calls, static_cast(0)); + CHECK_EQUAL(error, 0.0); + CHECK_EQUAL(l1, 0.0); + CHECK_EQUAL(levels, static_cast(0)); + check(integrator.integrate(endpoint, 2., 2., zero, norm), zero); +} + +void trapezoidal_matrices() +{ + unsigned calls = 0; + // Poisson kernel: its integral over one period is 2*pi. + const double r = 0.8; + const auto f = [&](double x) -> matrix { ++calls; return value*((1-r*r)/(1-2*r*std::cos(x)+r*r)); }; + q::trapezoidal(f, 0., 2*pi, zero, norm, 1e-3); + const unsigned coarse_calls = calls; + calls = 0; + double error = 0, l1 = 0; + matrix result = q::trapezoidal(f, 0., 2*pi, zero, norm, 1e-11, 12, &error, &l1); + check(result, value*(2*pi)); + CHECK_TRUE(calls > coarse_calls); + CHECK_TRUE(error < 1e-8); + CHECK_ULP_CLOSE(norm(value)*(2*pi), l1, 28); + const unsigned refined_calls = calls; + calls = 0; + double scaled_error = 0, scaled_l1 = 0; + check(q::trapezoidal(f, 0., 2*pi, zero, scaled_norm, 1e-11, 12, &scaled_error, &scaled_l1), result); + CHECK_EQUAL(calls, refined_calls); + CHECK_ULP_CLOSE(8*error, scaled_error, 4); + CHECK_ULP_CLOSE(8*l1, scaled_l1, 4); + check(q::trapezoidal(f, 2*pi, 0., zero, norm, 1e-11), -result); + calls = 0; + check(q::trapezoidal(f, 1., 1., zero, norm, 1e-11, 12, &error, &l1), zero); + CHECK_EQUAL(calls, static_cast(0)); + CHECK_EQUAL(error, 0.0); + CHECK_EQUAL(l1, 0.0); +} + +void nonthrowing_errors() +{ + using ignore = boost::math::policies::policy>; + const auto f = [&](double) -> matrix { return value; }; + const auto invalid = [](const matrix& m) { + CHECK_EQUAL(m.rows(), static_cast(2)); + CHECK_EQUAL(m.cols(), static_cast(3)); + for (Eigen::Index i = 0; i < m.size(); ++i) + CHECK_NAN(m.data()[i].real()); + }; + const double nan = std::numeric_limits::quiet_NaN(); + invalid(q::exp_sinh().integrate(f, 0., 1., zero, norm)); + invalid(q::exp_sinh().integrate(f, zero, norm, 2.)); + invalid(q::sinh_sinh().integrate(f, zero, norm)); + invalid(q::tanh_sinh().integrate(f, nan, 1., zero, norm)); + invalid(q::trapezoidal(f, 0., inf, zero, norm, 1e-10, 12, static_cast(nullptr), static_cast(nullptr), ignore())); +} + +void evaluation_errors_and_scalar_compatibility() +{ + const auto bad = [](double x) -> matrix { + if (std::abs(x) > 1e100) return zero; + matrix m = value; + m(0, 0) = std::numeric_limits::quiet_NaN(); + return m; + }; + CHECK_THROW(q::exp_sinh().integrate(bad, zero, norm), boost::math::evaluation_error); + CHECK_THROW(q::sinh_sinh().integrate(bad, zero, norm), boost::math::evaluation_error); + CHECK_THROW(q::tanh_sinh().integrate(bad, zero, norm), boost::math::evaluation_error); + using ignore = boost::math::policies::policy>; + // Non-throwing evaluation policies retain the concrete estimate, as in the + // existing interface, rather than trying to construct a matrix from a scalar. + matrix result = q::exp_sinh().integrate(bad, zero, norm); + CHECK_EQUAL(result.rows(), static_cast(2)); + CHECK_EQUAL(result.cols(), static_cast(3)); + CHECK_NAN(result(0, 0).real()); + result = q::sinh_sinh().integrate(bad, zero, norm); + CHECK_NAN(result(0, 0).real()); + result = q::tanh_sinh().integrate(bad, zero, norm); + CHECK_NAN(result(0, 0).real()); + + const auto f = [](double x) { return std::exp(-x*x); }; + const auto scalar_norm = [](double x) { return std::abs(x); }; + using function = decltype(f); + using exp_integrator = q::exp_sinh; + using sinh_integrator = q::sinh_sinh; + using tanh_integrator = q::tanh_sinh; + double (exp_integrator::*exp_original)(const function&, double, double*, double*, std::size_t*) const = &exp_integrator::integrate; + double (sinh_integrator::*sinh_original)(function, double, double*, double*, std::size_t*) const = &sinh_integrator::integrate; + double (tanh_integrator::*tanh_original)(function, double, double*, double*, std::size_t*) const = &tanh_integrator::integrate; + exp_integrator e; + sinh_integrator s; + tanh_integrator t; + CHECK_EQUAL((e.*exp_original)(f, 1e-10, nullptr, nullptr, nullptr), e.integrate(f, 0., scalar_norm, 1e-10)); + CHECK_EQUAL((s.*sinh_original)(f, 1e-10, nullptr, nullptr, nullptr), s.integrate(f, 0., scalar_norm, 1e-10)); + CHECK_EQUAL((t.*tanh_original)(f, 1e-10, nullptr, nullptr, nullptr), t.integrate(f, 0., scalar_norm, 1e-10)); + double (*trap_original)(function, double, double, double, std::size_t, double*, double*) = &q::trapezoidal; + CHECK_EQUAL(trap_original(f, -1., 1., 1e-10, 12, nullptr, nullptr), q::trapezoidal(f, -1., 1., 0., scalar_norm, 1e-10)); +} + +int main() +{ + exp_sinh_matrices(); + sinh_sinh_matrices(); + tanh_sinh_matrices(); + trapezoidal_matrices(); + nonthrowing_errors(); + evaluation_errors_and_scalar_compatibility(); + return boost::math::test::report_errors(); +} diff --git a/test/test_ellint_1.cpp b/test/test_ellint_1.cpp index 7e4f1bf4d8..2d02e85e48 100644 --- a/test/test_ellint_1.cpp +++ b/test/test_ellint_1.cpp @@ -50,7 +50,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_ellint_2.cpp b/test/test_ellint_2.cpp index 77c3007452..4338caa601 100644 --- a/test/test_ellint_2.cpp +++ b/test/test_ellint_2.cpp @@ -46,7 +46,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_ellint_2.hpp b/test/test_ellint_2.hpp index 3b565a493d..b477642c1d 100644 --- a/test/test_ellint_2.hpp +++ b/test/test_ellint_2.hpp @@ -166,6 +166,20 @@ void test_spots(T, const char* type_name) } }; do_test_ellint_e2(small_angles, type_name, "Elliptic Integral E: Small Angles"); // + // k near 1 and phi near pi/2, where 1 - k^2 and c - k^2 lost digits. Values from Arb, the inputs + // are doubles so we only test double: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + T near_one_tol = boost::math::tools::epsilon() * 20; + BOOST_CHECK_CLOSE_FRACTION(boost::math::ellint_2(T(0.99982354168451881), T(1.5324486420721517)), static_cast(0.999781247261809877237707915464176878750833L), near_one_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::ellint_2(T(-0.99982354168451881), T(1.5324486420721517)), static_cast(0.999781247261809877237707915464176878750833L), near_one_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::ellint_2(T(0.9999), T(1.5707)), static_cast(1.000513137840708950445877625147809092023445L), near_one_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::ellint_2(T(0.99999999), T(1.57079)), static_cast(1.000000096605569833326740569455842531840166L), near_one_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::ellint_2(T(0.999), T(1.5)), static_cast(0.999793406537408520821881945938968097695362L), near_one_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::ellint_2(T(0.99995), T(1.5706)), static_cast(1.000272612821377046854477086139187907740933L), near_one_tol); + } + // // Test error handling: // #ifndef BOOST_MATH_NO_EXCEPTIONS diff --git a/test/test_ellint_3.cpp b/test/test_ellint_3.cpp index 18b82e6488..bad1d342ba 100644 --- a/test/test_ellint_3.cpp +++ b/test/test_ellint_3.cpp @@ -41,7 +41,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } diff --git a/test/test_ellint_d.cpp b/test/test_ellint_d.cpp index adfd0b0509..c6f8939f68 100644 --- a/test/test_ellint_d.cpp +++ b/test/test_ellint_d.cpp @@ -47,7 +47,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/empirical_cumulative_distribution_test.cpp b/test/test_empirical_cumulative_distribution.cpp similarity index 100% rename from test/empirical_cumulative_distribution_test.cpp rename to test/test_empirical_cumulative_distribution.cpp diff --git a/test/engel_expansion_test.cpp b/test/test_engel_expansion.cpp similarity index 100% rename from test/engel_expansion_test.cpp rename to test/test_engel_expansion.cpp diff --git a/test/test_erf_limits.cpp b/test/test_erf_limits.cpp new file mode 100644 index 0000000000..ab1f60efaf --- /dev/null +++ b/test/test_erf_limits.cpp @@ -0,0 +1,82 @@ +// (C) Copyright John Maddock 2021. +// 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) + +// +// This test verifies that the limits we use in the numerical approximations to erf/erc +// are indeed correct. The values tested must of course match the values used in erf.hpp. +// See https://github.com/boostorg/math/issues/710 +// + + +#include +#include +#include "math_unit_test.hpp" + +#include + +void limits_53_digits() +{ + double arg = 5.93f; + + double t = (double)boost::math::erf(boost::multiprecision::cpp_bin_float_50(arg)); + CHECK_EQUAL(t, 1.0); + + arg = 5.9; + CHECK_TRUE((boost::math::erf(arg)) < (1.0)); + + arg = 28; + t = (double)boost::math::erfc(boost::multiprecision::cpp_bin_float_50(arg)); + CHECK_EQUAL(t, 0.0); + + arg = 27.2; + + CHECK_TRUE((boost::math::erfc(arg)) > (0.0)); +} + +void limits_64_digits() +{ + float arg = 6.6f; + + using ext_type = boost::multiprecision::cpp_bin_float_double_extended; + ext_type t = (ext_type)boost::math::erf(boost::multiprecision::cpp_bin_float_50(arg)); + CHECK_EQUAL(t, ext_type(1)); + +#if (LDBL_MANT_DIG == 64) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) + arg = 6.5; + CHECK_TRUE((boost::math::erf(static_cast(arg))) < (1.0L)); +#endif + arg = 110; + t = (ext_type)boost::math::erfc(boost::multiprecision::cpp_bin_float_50(arg)); + CHECK_EQUAL(t, ext_type(0)); + +#if (LDBL_MANT_DIG == 64) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) + arg = 106.5; + CHECK_TRUE((boost::math::erfc(static_cast(arg))) > (0.0L)); +#endif +} + +void limits_113_digits() +{ + // + // This limit is not actually used in the code, logged here for future reference... + // + float arg = 8.8f; + + using quad_type = boost::multiprecision::cpp_bin_float_quad; + quad_type t = (quad_type)boost::math::erf(boost::multiprecision::cpp_bin_float_50(arg)); + CHECK_EQUAL(t, quad_type(1)); + + arg = 110; + t = (quad_type)boost::math::erfc(boost::multiprecision::cpp_bin_float_50(arg)); + CHECK_EQUAL(t, quad_type(0)); +} + +int main() +{ + limits_53_digits(); + limits_64_digits(); + limits_113_digits(); + return boost::math::test::report_errors(); +} diff --git a/test/test_error_handling.cpp b/test/test_error_handling.cpp index 400a1647f7..7eef9375cb 100644 --- a/test/test_error_handling.cpp +++ b/test/test_error_handling.cpp @@ -340,6 +340,25 @@ BOOST_AUTO_TEST_CASE( test_main ) test_complex_error(std::complex(0)); test_complex_error(std::complex(0)); + // An in-range complex value has to come through checked_narrowing_cast unchanged. + // The per-component checks used to leave the result partly uninitialized, which clang + // at -O1 and above with -fno-inline turned into a spurious overflow error. + { + using namespace boost::math::policies; + std::complex z(0.53L, -0.99L); + std::complex r = checked_narrowing_cast, policy<> >(z, "test<%1%>"); + BOOST_CHECK_EQUAL(r.real(), static_cast(0.53L)); + BOOST_CHECK_EQUAL(r.imag(), static_cast(-0.99L)); + // When only one component is out of range the other one keeps its value: + if (std::numeric_limits::max_exponent > std::numeric_limits::max_exponent) + { + std::complex big((std::numeric_limits::max)(), 0.25L); + r = checked_narrowing_cast, policy > >(big, "test<%1%>"); + BOOST_CHECK((boost::math::isinf)(r.real())); + BOOST_CHECK_EQUAL(r.imag(), 0.25); + } + } + test_polynomial_error(boost::math::tools::polynomial()); } // BOOST_AUTO_TEST_CASE( test_main ) diff --git a/test/test_estrin_module.cpp b/test/test_estrin_module.cpp new file mode 100644 index 0000000000..26b804b86b --- /dev/null +++ b/test/test_estrin_module.cpp @@ -0,0 +1,90 @@ +// (C) Copyright Nick Thompson, John Maddock 2023. +// 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) +// +// Module build check for boost::math::tools::evaluate_polynomial_estrin. It +// consumes the exported Estrin polynomial evaluator through `import boost.math;` +// and confirms all three overloads (general container, std::array, explicit +// scratch space) resolve from a module consumer. Estrin evaluates +// p(z) = c[0] + c[1] z + c[2] z^2 + ... with coefficients in ascending order. +// The assertions use only mathematically-certain values: integer coefficients +// and integer arguments keep every intermediate exactly representable, so the +// results are exact. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif + +using boost::math::tools::evaluate_polynomial_estrin; + +// General RandomAccessContainer overload (allocates its own scratch vector). +template +void test_vector_overload() +{ + // p(z) = 2 + 3 z + 4 z^2. + std::vector coeffs {Real(2), Real(3), Real(4)}; + + CHECK_ULP_CLOSE(Real(2), evaluate_polynomial_estrin(coeffs, Real(0)), 0); // p(0) = c0 + CHECK_ULP_CLOSE(Real(9), evaluate_polynomial_estrin(coeffs, Real(1)), 0); // p(1) = sum(coeffs) + CHECK_ULP_CLOSE(Real(24), evaluate_polynomial_estrin(coeffs, Real(2)), 0); // 2 + 6 + 16 + CHECK_ULP_CLOSE(Real(3), evaluate_polynomial_estrin(coeffs, Real(-1)), 0); // 2 - 3 + 4 + + // A single coefficient is the constant polynomial p(z) = c0 for all z. + std::vector constant {Real(7)}; + CHECK_ULP_CLOSE(Real(7), evaluate_polynomial_estrin(constant, Real(0)), 0); + CHECK_ULP_CLOSE(Real(7), evaluate_polynomial_estrin(constant, Real(5)), 0); + + // No coefficients evaluates to zero for any argument. + std::vector empty; + CHECK_EQUAL(Real(0), evaluate_polynomial_estrin(empty, Real(3))); +} + +// std::array overload: same value, no heap allocation for the scratch space. +template +void test_array_overload() +{ + // p(z) = 1 + 2 z + 3 z^2 + 4 z^3. + std::array coeffs {Real(1), Real(2), Real(3), Real(4)}; + + CHECK_ULP_CLOSE(Real(1), evaluate_polynomial_estrin(coeffs, Real(0)), 0); // p(0) = c0 + CHECK_ULP_CLOSE(Real(10), evaluate_polynomial_estrin(coeffs, Real(1)), 0); // 1 + 2 + 3 + 4 + CHECK_ULP_CLOSE(Real(49), evaluate_polynomial_estrin(coeffs, Real(2)), 0); // 1 + 4 + 12 + 32 +} + +// Explicit scratch-space overload: the caller supplies working storage of at +// least (n + 1) / 2 elements whose value type matches the argument. +template +void test_scratch_overload() +{ + // p(z) = 5 + z^3. + std::vector coeffs {Real(5), Real(0), Real(0), Real(1)}; + std::vector scratch(2); + + CHECK_ULP_CLOSE(Real(5), evaluate_polynomial_estrin(coeffs, scratch, Real(0)), 0); // p(0) = 5 + CHECK_ULP_CLOSE(Real(6), evaluate_polynomial_estrin(coeffs, scratch, Real(1)), 0); // 5 + 1 + CHECK_ULP_CLOSE(Real(13), evaluate_polynomial_estrin(coeffs, scratch, Real(2)), 0); // 5 + 8 +} + +int main() +{ + test_vector_overload(); + test_vector_overload(); + + test_array_overload(); + test_array_overload(); + + test_scratch_overload(); + test_scratch_overload(); + + return boost::math::test::report_errors(); +} diff --git a/test/test_exp_sinh_module.cpp b/test/test_exp_sinh_module.cpp new file mode 100644 index 0000000000..992671f4e0 --- /dev/null +++ b/test/test_exp_sinh_module.cpp @@ -0,0 +1,77 @@ +// Copyright Nick Thompson, 2017 +// 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) +// +// Module build check for exp_sinh quadrature. The integrator is an exported +// class template whose member integrate() is instantiated on a user supplied +// functor; building this against the boost.math module confirms the exported +// template, its detail impl and the constants it pulls in are all reachable +// from a module consumer. The expected values are the closed-form results of +// the smooth half-infinite integrals used in test_exp_sinh_quadrature.cpp. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif +#include "math_unit_test.hpp" + +template +void test_spots(Real, const char* type_name) +{ + std::cout << "Testing exp_sinh quadrature for type " << type_name << std::endl; + + // root_epsilon: the default convergence tolerance the integrator requests. + const Real tol_conv {std::sqrt(std::numeric_limits::epsilon())}; + const Real inf {std::numeric_limits::infinity()}; + const int ulps {64}; + + const boost::math::quadrature::exp_sinh integrator {}; + + Real error {}; + Real L1 {}; + + // Integral of exp(-t)/sqrt(t) over (0, inf) is sqrt(pi). Default overload. + const auto f1 = [](Real t) -> Real { return std::exp(-t) / std::sqrt(t); }; + Real Q {integrator.integrate(f1, tol_conv, &error, &L1)}; + CHECK_ULP_CLOSE(static_cast(1.77245385090551602729816748334114518), Q, ulps); + // Integrand is strictly positive, so the L1 norm equals the integral. + CHECK_ULP_CLOSE(static_cast(1.77245385090551602729816748334114518), L1, ulps); + + // Integral of 1/(1+t*t) over (0, inf) is pi/2. Default overload. + const auto f2 = [](Real t) -> Real { return static_cast(1) / (1 + t * t); }; + Q = integrator.integrate(f2, tol_conv, &error, &L1); + CHECK_ULP_CLOSE(static_cast(1.57079632679489661923132169163975144), Q, ulps); + CHECK_ULP_CLOSE(static_cast(1.57079632679489661923132169163975144), L1, ulps); + + // Integral of 1/(sqrt(t)*(1+t)) over (0, inf) is pi. Default overload. + const auto f3 = [](Real t) -> Real { return static_cast(1) / (std::sqrt(t) * (1 + t)); }; + Q = integrator.integrate(f3, tol_conv, &error, &L1); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288), Q, ulps); + CHECK_ULP_CLOSE(static_cast(3.14159265358979323846264338327950288), L1, ulps); + + // Integral of 1/(1+t*t) over (1, inf) is pi/4. Bounded (right-infinite) overload. + Q = integrator.integrate(f2, static_cast(1), inf, tol_conv, &error, &L1); + CHECK_ULP_CLOSE(static_cast(0.785398163397448309615660845819875721), Q, ulps); + CHECK_ULP_CLOSE(static_cast(0.785398163397448309615660845819875721), L1, ulps); + + // Integral of 1/(1+t*t) over (-inf, 0) is pi/2. Bounded (left-infinite) overload. + Q = integrator.integrate(f2, -inf, static_cast(0), tol_conv, &error, &L1); + CHECK_ULP_CLOSE(static_cast(1.57079632679489661923132169163975144), Q, ulps); + CHECK_ULP_CLOSE(static_cast(1.57079632679489661923132169163975144), L1, ulps); +} + +int main() +{ + test_spots(0.0F, "float"); + test_spots(0.0, "double"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_exp_sinh_quadrature.cpp b/test/test_exp_sinh_quadrature.cpp new file mode 100644 index 0000000000..7185e7bd59 --- /dev/null +++ b/test/test_exp_sinh_quadrature.cpp @@ -0,0 +1,724 @@ +// Copyright Nick Thompson, 2017 +// 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) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "math_unit_test.hpp" + +#ifdef BOOST_HAS_FLOAT128 +#include +#endif + +#if __has_include() +# include +#endif + +using std::exp; +using std::cos; +using std::tan; +using std::log; +using std::sqrt; +using std::abs; +using std::sinh; +using std::cosh; +using std::pow; +using std::atan; +using boost::multiprecision::cpp_bin_float_50; +using boost::multiprecision::cpp_bin_float_100; +using boost::multiprecision::cpp_bin_float_quad; +using boost::math::constants::pi; +using boost::math::constants::half_pi; +using boost::math::constants::two_div_pi; +using boost::math::constants::half; +using boost::math::constants::third; +using boost::math::constants::half; +using boost::math::constants::third; +using boost::math::constants::catalan; +using boost::math::constants::ln_two; +using boost::math::constants::root_two; +using boost::math::constants::root_two_pi; +using boost::math::constants::root_pi; +using boost::math::quadrature::exp_sinh; + +#if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) && !defined(TEST4) && !defined(TEST5) && !defined(TEST6) && !defined(TEST7) && !defined(TEST8) && !defined(TEST9) && !defined(TEST10) +# define TEST1 +# define TEST2 +# define TEST3 +# define TEST4 +# define TEST5 +# define TEST6 +# define TEST7 +# define TEST8 +# define TEST9 +# define TEST10 +#endif + +#ifdef _MSC_VER +#pragma warning (disable:4127) +#endif + +// +// Coefficient generation code: +// +template +void print_levels(const T& v, const char* suffix) +{ + std::cout << "{\n"; + for (unsigned i = 0; i < v.size(); ++i) + { + std::cout << " { "; + for (unsigned j = 0; j < v[i].size(); ++j) + { + std::cout << v[i][j] << suffix << ", "; + } + std::cout << "},\n"; + } + std::cout << " };\n"; +} + +template +void print_levels(const std::pair& p, const char* suffix = "") +{ + std::cout << " static const std::vector > abscissa = "; + print_levels(p.first, suffix); + std::cout << " static const std::vector > weights = "; + print_levels(p.second, suffix); +} + +template +std::pair>, std::vector> > generate_constants(unsigned max_rows) +{ + using boost::math::constants::half_pi; + using boost::math::constants::two_div_pi; + using boost::math::constants::pi; + auto g = [](Real t)->Real { return exp(half_pi()*sinh(t)); }; + auto w = [](Real t)->Real { return cosh(t)*half_pi()*exp(half_pi()*sinh(t)); }; + + std::vector> abscissa, weights; + + std::vector temp; + + Real tmp = (Real(boost::math::tools::log_min_value()) + log(Real(boost::math::tools::epsilon())))*0.5f; + Real t_min = asinh(two_div_pi()*tmp); + // truncate t_min to an exact binary value: + t_min = floor(t_min * 128) / 128; + + std::cout << "m_t_min = " << t_min << ";\n"; + + // t_max is chosen to make g'(t_max) ~ sqrt(max) (g' grows faster than g). + // This will allow some flexibility on the users part; they can at least square a number function without overflow. + // But there is no unique choice; the further out we can evaluate the function, the better we can do on slowly decaying integrands. + const Real t_max = log(2 * two_div_pi()*log(2 * two_div_pi()*sqrt(Real(boost::math::tools::max_value())))); + + Real h = 1; + for (Real t = t_min; t < t_max; t += h) + { + temp.push_back(g(t)); + } + abscissa.push_back(temp); + temp.clear(); + + for (Real t = t_min; t < t_max; t += h) + { + temp.push_back(w(t * h)); + } + weights.push_back(temp); + temp.clear(); + + for (unsigned row = 1; row < max_rows; ++row) + { + h /= 2; + for (Real t = t_min + h; t < t_max; t += 2 * h) + temp.push_back(g(t)); + abscissa.push_back(temp); + temp.clear(); + } + h = 1; + for (unsigned row = 1; row < max_rows; ++row) + { + h /= 2; + for (Real t = t_min + h; t < t_max; t += 2 * h) + temp.push_back(w(t)); + weights.push_back(temp); + temp.clear(); + } + + return std::make_pair(abscissa, weights); +} + + +template +const exp_sinh& get_integrator() +{ + static const exp_sinh integrator(14); + return integrator; +} + +template +Real get_convergence_tolerance() +{ + return boost::math::tools::root_epsilon(); +} + +template +void test_right_limit_infinite() +{ + std::cout << "Testing right limit infinite for tanh_sinh in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real Q; + Real Q_expected; + Real error; + Real L1; + const auto& integrator = get_integrator(); + + // Example 12 + const auto f2 = [](const Real& t)->Real { return exp(-t)/sqrt(t); }; + Q = integrator.integrate(f2, get_convergence_tolerance(), &error, &L1); + Q_expected = root_pi(); + std::size_t tol_mult = 1; + // Multiprecision type have higher error rates, probably evaluation of f() is less accurate: + if (!std::numeric_limits::digits10 || (std::numeric_limits::digits10 > 25)) + tol_mult = 1200; + else if (std::numeric_limits::digits10 > std::numeric_limits::digits10) + tol_mult = 5; + CHECK_ULP_CLOSE(Q_expected, Q, 20 * tol_mult); + // The integrand is strictly positive, so it coincides with the value of the integral: + CHECK_ULP_CLOSE(Q_expected, L1, 20 * tol_mult); + + #ifdef BOOST_MATH_STANDALONE + BOOST_IF_CONSTEXPR (std::is_fundamental::value) + #endif + { + auto f3 = [](Real t)->Real { Real z = exp(-t); if (z == 0) { return z; } return z*cos(t); }; + Q = integrator.integrate(f3, get_convergence_tolerance(), &error, &L1); + Q_expected = half(); + CHECK_ULP_CLOSE(Q_expected, Q, 20); + Q = integrator.integrate(f3, 10, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); + Q_expected = BOOST_MATH_TEST_VALUE(Real, -6.6976341310426674140007086979326069121526743314567805278252392932e-6); + CHECK_ULP_CLOSE(Q_expected, Q, 68); + // Integrating through zero risks precision loss: + Q = integrator.integrate(f3, -10, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); + Q_expected = BOOST_MATH_TEST_VALUE(Real, -15232.3213626280525704332288302799653087046646639974940243044623285817777006); + CHECK_ULP_CLOSE(Q_expected, Q, std::numeric_limits::digits10 > 30 ? 20000 : 20); + + auto f4 = [](Real t)->Real { return 1/(1+t*t); }; + Q = integrator.integrate(f4, 1, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); + Q_expected = pi()/4; + CHECK_ULP_CLOSE(Q_expected, Q, 8); + CHECK_ULP_CLOSE(Q_expected, L1, 8); + Q = integrator.integrate(f4, 20, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); + Q_expected = BOOST_MATH_TEST_VALUE(Real, 0.0499583957219427614100062870348448814912770804235071744108534548299835954767); + CHECK_ULP_CLOSE(Q_expected, Q, 4); + CHECK_ULP_CLOSE(Q_expected, L1, 4); + Q = integrator.integrate(f4, 500, std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(), get_convergence_tolerance(), &error, &L1); + Q_expected = BOOST_MATH_TEST_VALUE(Real, 0.0019999973333397333150476759363217553199063513829126652556286269630); + CHECK_ULP_CLOSE(Q_expected, Q, 4); + CHECK_ULP_CLOSE(Q_expected, L1, 4); + } +} + +template +void test_left_limit_infinite() +{ + std::cout << "Testing left limit infinite for 1/(1+t^2) on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real Q; + Real Q_expected; + Real error; + Real L1; + const auto& integrator = get_integrator(); + + // Example 11: + #ifdef BOOST_MATH_STANDALONE + BOOST_IF_CONSTEXPR (std::is_fundamental::value) + #endif + { + auto f1 = [](const Real& t)->Real { return 1/(1+t*t);}; + Q = integrator.integrate(f1, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), 0, get_convergence_tolerance(), &error, &L1); + Q_expected = half_pi(); + CHECK_ULP_CLOSE(Q_expected, Q, 8); + CHECK_ULP_CLOSE(Q_expected, L1, 8); + Q = integrator.integrate(f1, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), -20, get_convergence_tolerance(), &error, &L1); + Q_expected = BOOST_MATH_TEST_VALUE(Real, 0.0499583957219427614100062870348448814912770804235071744108534548299835954767); + CHECK_ULP_CLOSE(Q_expected, Q, 4); + CHECK_ULP_CLOSE(Q_expected, L1, 4); + Q = integrator.integrate(f1, std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() : -boost::math::tools::max_value(), -500, get_convergence_tolerance(), &error, &L1); + Q_expected = BOOST_MATH_TEST_VALUE(Real, 0.0019999973333397333150476759363217553199063513829126652556286269630); + CHECK_ULP_CLOSE(Q_expected, Q, 4); + CHECK_ULP_CLOSE(Q_expected, L1, 4); + } +} + + +// Some examples of tough integrals from NR, section 4.5.4: +template +void test_nr_examples() +{ + using std::sin; + using std::cos; + using std::pow; + using std::exp; + using std::sqrt; + std::cout << "Testing type " << boost::typeindex::type_id().pretty_name() << "\n"; + std::cout << std::setprecision(std::numeric_limits::digits10); + Real Q; + Real Q_expected; + Real L1; + Real error; + const auto& integrator = get_integrator(); + + auto f0 = [] (Real)->Real { return (Real) 0; }; + Q = integrator.integrate(f0, get_convergence_tolerance(), &error, &L1); + Q_expected = 0; + CHECK_EQUAL(Q, Real(0)); + CHECK_EQUAL(L1, Real(0)); + + auto f = [](const Real& x)->Real { return 1/(1+x*x); }; + Q = integrator.integrate(f, get_convergence_tolerance(), &error, &L1); + Q_expected = half_pi(); + CHECK_ULP_CLOSE(Q_expected, Q, 8); + CHECK_ULP_CLOSE(Q_expected, L1, 8); + + auto f1 = [](Real x)->Real { + Real z1 = exp(-x); + if (z1 == 0) + { + return (Real) 0; + } + Real z2 = pow(x, -3*half())*z1; + if (z2 == 0) + { + return (Real) 0; + } + return sin(x*half())*z2; + }; + + Q = integrator.integrate(f1, get_convergence_tolerance(), &error, &L1); + Q_expected = sqrt(pi()*(sqrt((Real) 5) - 2)); + + // The integrand is oscillatory; the accuracy is low. + std::size_t tol_mul = 1; + if (std::numeric_limits::digits10 > 40) + tol_mul = 500000; + CHECK_ULP_CLOSE(Q_expected, Q, 20 * tol_mul); + + auto f2 = [](Real x)->Real { return x > boost::math::tools::log_max_value() ? Real(0) : Real(pow(x, -(Real) 2/(Real) 7)*exp(-x*x)); }; + Q = integrator.integrate(f2, get_convergence_tolerance(), &error, &L1); + Q_expected = half()*boost::math::tgamma((Real) 5/ (Real) 14); + tol_mul = 1; + if ((std::numeric_limits::is_specialized == false) || (std::numeric_limits::digits10 > 40)) + tol_mul = 500; + else + tol_mul = 3; + CHECK_ULP_CLOSE(Q_expected, Q, 20 * tol_mul); + CHECK_ULP_CLOSE(Q_expected, L1, 20 * tol_mul); + + auto f3 = [](Real x)->Real { return (Real) 1/ (sqrt(x)*(1+x)); }; + Q = integrator.integrate(f3, get_convergence_tolerance(), &error, &L1); + Q_expected = pi(); + + CHECK_ULP_CLOSE(Q_expected, Q, 8); + CHECK_ULP_CLOSE(Q_expected, L1, 8); + + auto f4 = [](const Real& t)->Real { return t > boost::math::tools::log_max_value() ? Real(0) : Real(exp(-t*t*half())); }; + Q = integrator.integrate(f4, get_convergence_tolerance(), &error, &L1); + Q_expected = root_two_pi()/2; + tol_mul = 1; + if (std::numeric_limits::digits10 > 40) + tol_mul = 5000; + CHECK_ULP_CLOSE(Q_expected, Q, 20 * tol_mul); + CHECK_ULP_CLOSE(Q_expected, L1, 20 * tol_mul); + + auto f5 = [](const Real& t)->Real { return 1/cosh(t);}; + Q = integrator.integrate(f5, get_convergence_tolerance(), &error, &L1); + Q_expected = half_pi(); + CHECK_ULP_CLOSE(Q_expected, Q, 240); // Fails at float precision without higher error rate + CHECK_ULP_CLOSE(Q_expected, L1, 240); +} + +// Definite integrals found in the CRC Handbook of Mathematical Formulas +template +void test_crc() +{ + using std::sin; + using std::pow; + using std::exp; + using std::sqrt; + using std::log; + using std::cos; + std::cout << "Testing integral from CRC handbook on type " << boost::typeindex::type_id().pretty_name() << "\n"; + std::cout << std::setprecision(std::numeric_limits::digits10); + Real Q; + Real Q_expected; + Real L1; + Real error; + const auto& integrator = get_integrator(); + + auto f0 = [](const Real& x)->Real { return x > boost::math::tools::log_max_value() ? Real(0) : Real(log(x)*exp(-x)); }; + Q = integrator.integrate(f0, get_convergence_tolerance(), &error, &L1); + Q_expected = -boost::math::constants::euler(); + CHECK_ULP_CLOSE(Q_expected, Q, 8); + + // Test the integral representation of the gamma function: + auto f1 = [](Real t)->Real { Real x = exp(-t); + if(x == 0) + { + return (Real) 0; + } + return pow(t, (Real) 12 - 1)*x; + }; + + Q = integrator.integrate(f1, get_convergence_tolerance(), &error, &L1); + Q_expected = boost::math::tgamma(12.0f); + CHECK_ULP_CLOSE(Q_expected, Q, 16); + + // Integral representation of the modified bessel function: + // K_5(12) + auto f2 = [](Real t)->Real { + Real x = 12*cosh(t); + if (x > boost::math::tools::log_max_value()) + { + return (Real) 0; + } + return exp(-x)*cosh(5*t); + }; + Q = integrator.integrate(f2, get_convergence_tolerance(), &error, &L1); + Q_expected = boost::math::cyl_bessel_k(5, 12); + CHECK_ULP_CLOSE(Q_expected, Q, 20); + // Laplace transform of cos(at) + Real a = 20; + Real s = 1; + auto f3 = [&](Real t)->Real { + Real x = s * t; + if (x > boost::math::tools::log_max_value()) + { + return (Real) 0; + } + return cos(a * t) * exp(-x); + }; + + // Since the integrand is oscillatory, we increase the tolerance: + std::size_t tol_mult = 10; + // Multiprecision type have higher error rates, probably evaluation of f() is less accurate: + if (!std::is_class::value) + { + // For high oscillation frequency, the quadrature sum is ill-conditioned. + Q = integrator.integrate(f3, get_convergence_tolerance(), &error, &L1); + Q_expected = s/(a*a+s*s); + if (std::numeric_limits::digits10 > std::numeric_limits::digits10) + tol_mult = 500000; // we should really investigate this more?? + CHECK_ULP_CLOSE(Q_expected, Q, 20 * tol_mult); + } + + // + // This one doesn't pass for real_concept.. + // + if (std::numeric_limits::is_specialized) + { + // Laplace transform of J_0(t): + auto f4 = [&](Real t)->Real { + Real x = s * t; + if (x > boost::math::tools::log_max_value()) + { + return (Real)0; + } + return boost::math::cyl_bessel_j(0, t) * exp(-x); + }; + + Q = integrator.integrate(f4, get_convergence_tolerance(), &error, &L1); + Q_expected = 1 / sqrt(1 + s*s); + tol_mult = 3; + // Multiprecision type have higher error rates, probably evaluation of f() is less accurate: + if ((std::numeric_limits::digits10 > std::numeric_limits::digits10) || (std::numeric_limits::digits > 100) || !std::numeric_limits::digits) + tol_mult = 50000; + CHECK_ULP_CLOSE(Q_expected, Q, 20 * tol_mult); + } + auto f6 = [](const Real& t)->Real { return t > boost::math::tools::log_max_value() ? Real(0) : Real(exp(-t*t)*log(t));}; + Q = integrator.integrate(f6, get_convergence_tolerance(), &error, &L1); + Q_expected = -boost::math::constants::root_pi()*(boost::math::constants::euler() + 2*ln_two())/4; + CHECK_ULP_CLOSE(Q_expected, Q, 20); + + // CRC Section 5.5, integral 591 + // The parameter p allows us to control the strength of the singularity. + // Rapid convergence is not guaranteed for this function, as the branch cut makes it non-analytic on a disk. + // This converges only when our test type has an extended exponent range as all the area of the integral + // occurs so close to 0 (or 1) that we need abscissa values exceptionally small to find it. + // "There's a lot of room at the bottom". + // This version is transformed via argument substitution (exp(-x) for x) so that the integral is spread + // over (0, INF). + const std::size_t ulps = 20 * (boost::math::tools::digits() > 100 ? 100000 : 75); + for (Real pn = 99; pn > 0; pn -= 10) { + Real p = pn / 100; + auto f = [&](Real x)->Real + { + return x > 1000 * boost::math::tools::log_max_value() ? Real(0) : Real(exp(-x * (1 - p) + p * log(-boost::math::expm1(-x)))); + }; + Q = integrator.integrate(f, get_convergence_tolerance(), &error, &L1); + Q_expected = 1 / boost::math::sinc_pi(p*pi()); + /* + std::cout << std::setprecision(std::numeric_limits::max_digits10) << p << std::endl; + std::cout << std::setprecision(std::numeric_limits::max_digits10) << Q << std::endl; + std::cout << std::setprecision(std::numeric_limits::max_digits10) << Q_expected << std::endl; + std::cout << fabs((Q - Q_expected) / Q_expected) << std::endl; + */ + CHECK_ULP_CLOSE(Q_expected, Q, ulps); + } + // and for p < 1: + for (Real p = -0.99; p < 0; p += 0.1) { + auto f = [&](Real x)->Real + { + return x > 1000 * boost::math::tools::log_max_value() ? Real(0) : Real(exp(-p * log(-boost::math::expm1(-x)) - (1 + p) * x)); + }; + Q = integrator.integrate(f, get_convergence_tolerance(), &error, &L1); + Q_expected = 1 / boost::math::sinc_pi(p*pi()); + CHECK_ULP_CLOSE(Q_expected, Q, ulps); + } +} + +template +void test_complex_modified_bessel() +{ + std::cout << "Testing complex modified Bessel function on type " << boost::typeindex::type_id().pretty_name() << "\n"; + typedef typename Complex::value_type Real; + Real error; + Real L1; + const auto& integrator = get_integrator(); + + // Integral Representation of Modified Complex Bessel function: + // https://en.wikipedia.org/wiki/Bessel_function#Modified_Bessel_functions + Complex z{2, 3}; + const auto f = [&z](const Real& t)->Complex + { + using std::cosh; + using std::exp; + Real cosht = cosh(t); + if (cosht > boost::math::tools::log_max_value()) + { + return Complex{0, 0}; + } + Complex arg = -z*cosht; + Complex res = exp(arg); + return res; + }; + + Complex K0 = integrator.integrate(f, get_convergence_tolerance(), &error, &L1); + + // Mathematica code: N[BesselK[0, 2 + 3 I], 140] + #ifdef BOOST_MATH_STANDALONE + BOOST_IF_CONSTEXPR (std::is_fundamental::value) + #endif + { + Real K0_x_expected = BOOST_MATH_TEST_VALUE(Real, -0.08296852656762551490517953520589186885781541203818846830385526187936132191822538822296497597191327722262903004145527496422090506197776994); + Real K0_y_expected = BOOST_MATH_TEST_VALUE(Real, 0.027949603635183423629723306332336002340909030265538548521150904238352846705644065168365102147901993976999717171115546662967229050834575193041); + CHECK_ULP_CLOSE(K0_x_expected, K0.real(), 132); + CHECK_ULP_CLOSE(K0_y_expected, K0.imag(), 200); + } +} + +template +void test_complex_exponential_integral_E1(){ + std::cout << "Testing complex exponential integral on type " << boost::typeindex::type_id().pretty_name() << "\n"; + typedef typename Complex::value_type Real; + Real error; + Real L1; + const auto& integrator = get_integrator(); + + Complex z{1.5,0.5}; + + // Integral representation of exponential integral E1, valid for Re z > 0 + // https://en.wikipedia.org/wiki/Exponential_integral#Definitions + auto f = [&z](const Real& t)->Complex + { + using std::exp; + return exp(-z*t)/t; + }; + + Real inf = std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : boost::math::tools::max_value(); + + Complex E1 = integrator.integrate(f,1,inf,get_convergence_tolerance(),&error,&L1); + + // Mathematica code: N[ExpIntegral[1,1.5 + 0.5 I],140] + #ifdef BOOST_MATH_STANDALONE + BOOST_IF_CONSTEXPR (std::is_fundamental::value) + #endif + { + Real E1_real_expected = BOOST_MATH_TEST_VALUE(Real, 0.071702995463938694845949672113596046091766639758473558841839765788732549949008866887694451956003503764943496943262401868244277788066634858393); + Real E1_imag_expected = BOOST_MATH_TEST_VALUE(Real, -0.065138628279238400564373880665751377423524428792583839078600260273866805818117625959446311737353882269129094759883720722150048944193926087208); + CHECK_ULP_CLOSE(E1_real_expected, E1.real(), 4); + CHECK_ULP_CLOSE(E1_imag_expected, E1.imag(), 4); + } +} + +template +void test_non_central_t() +{ + // + // Bug case from the non-central t distribution: + // + using std::pow; + using std::exp; + using std::sqrt; + + std::cout << "Testing non-central T PDF integral" << std::endl; + + T x = -1.882352352142334; + T v = 77.384613037109375; + T mu = 8.1538467407226562; + T expected = static_cast(4.5098555913703146875364186893655197e+49L); + + boost::math::quadrature::exp_sinh integrator; + T err; + T L1; + std::size_t levels; + T integral = integrator.integrate([&x, v, mu](T y) + { + return pow(y, v) * exp(boost::math::pow<2>((y - mu * x / sqrt(x * x + v))) / -2); + }, + boost::math::tools::root_epsilon(), &err, &L1, &levels); + + CHECK_ULP_CLOSE(expected, integral, 200); +} + + +void exp_sinh_quadrature_test() +{ + // + // Uncomment to generate the coefficients: + // + + /* + std::cout << std::scientific << std::setprecision(8); + print_levels(generate_constants(8), "f"); + std::cout << std::setprecision(18); + print_levels(generate_constants(8), ""); + std::cout << std::setprecision(35); + print_levels(generate_constants(8), "L"); + */ + +#ifdef TEST1 + +#ifdef __STDCPP_FLOAT32_T__ + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); + //test_non_central_t(); +#else + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); + //test_non_central_t(); +#endif + +#endif +#ifdef TEST2 + +#ifdef __STDCPP_FLOAT64_T__ + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); + test_non_central_t(); +#else + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); + test_non_central_t(); +#endif + +#endif +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS +#ifdef TEST3 +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); + test_non_central_t(); +#endif +#endif +#endif +#if defined(TEST4) && defined(BOOST_MATH_RUN_MP_TESTS) + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); +#endif + +#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) +#ifdef TEST5 + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); + test_non_central_t(); +#endif +#endif +#if defined(TEST6) && defined(BOOST_MATH_RUN_MP_TESTS) + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + test_crc(); +#endif +#if defined(TEST7) && defined(BOOST_MATH_RUN_MP_TESTS) + test_left_limit_infinite(); + test_right_limit_infinite(); + test_nr_examples(); + // + // This one causes stack overflows on the CI machine, but not locally, + // assume it's due to restricted resources on the server, and for now... + // +#if ! BOOST_WORKAROUND(BOOST_MSVC, == 1900) && defined(BOOST_MATH_RUN_MP_TESTS) + test_crc(); +#endif +#endif +#ifdef TEST8 + test_complex_modified_bessel>(); + test_complex_modified_bessel>(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_complex_modified_bessel>(); +#endif +#ifndef BOOST_MATH_NO_MP_TESTS + test_complex_modified_bessel(); +#endif +#endif +#ifdef TEST9 + test_complex_exponential_integral_E1>(); + test_complex_exponential_integral_E1>(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_complex_exponential_integral_E1>(); +#endif +#if defined(BOOST_MATH_RUN_MP_TESTS) + test_complex_exponential_integral_E1(); +#endif +#endif +#ifdef TEST10 +#if defined(BOOST_HAS_FLOAT128) && !defined(BOOST_MATH_NO_MP_TESTS) + test_complex_modified_bessel(); + test_complex_exponential_integral_E1(); +#endif +#endif +} + +int main() +{ + exp_sinh_quadrature_test(); + return boost::math::test::report_errors(); +} diff --git a/test/test_expint.hpp b/test/test_expint.hpp index ee1e170380..c6c250d6d7 100644 --- a/test/test_expint.hpp +++ b/test/test_expint.hpp @@ -182,6 +182,25 @@ void test_spots(T, const char* t) BOOST_CHECK_CLOSE(::boost::math::expint(22, static_cast(1.5F)), static_cast(0.0098864453561701486668317763826728620676449196215016L), tolerance); BOOST_CHECK_CLOSE(::boost::math::expint(22, static_cast(4.5F)), static_cast(0.00043257793497205419001613830279995985617548506505159L), tolerance); BOOST_CHECK_CLOSE(::boost::math::expint(22, static_cast(50.0F)), static_cast(2.6900194251201629500599598206345018300567305625080e-24L), tolerance); + + // + // Small n and z, where the continued fraction used to lose up to 100 eps. + // Values from Arb, with exactly representable arguments, and without promotion to long double: + // + typedef boost::math::policies::policy, boost::math::policies::promote_double > no_promote; + T fine_tolerance = boost::math::tools::epsilon() * 4; + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(2, static_cast(0.5234375L), no_promote()), static_cast(0.313849729892195947855048595503987330295L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(5, static_cast(0.765625L), no_promote()), static_cast(0.093986486497079385849351196976185361696L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(3, static_cast(0.546875L), no_promote()), static_cast(0.206887798968448296964906195937878966847L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(4, static_cast(0.6875L), no_promote()), static_cast(0.128875072258780982223489377343610090143L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(7, static_cast(0.84375L), no_promote()), static_cast(0.061611202574823970288571878649546543895L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(2, static_cast(0.8125L), no_promote()), static_cast(0.197012716206338050333499382725494520580L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(2, static_cast(1.25L), no_promote()), static_cast(0.103488081202802379458312298784846073324L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(10, static_cast(1.0625L), no_promote()), static_cast(0.033959400110090244027421921101310089047L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(3, static_cast(0.505859375L), no_promote()), static_cast(0.219700004051754511547025991804223456768L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(3, static_cast(0.5078125L), no_promote()), static_cast(0.219069446190807745449512957752318730531L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(2, static_cast(2.0390625L), no_promote()), static_cast(0.035674719779421774803516160152884417867L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::expint(5, static_cast(1.75L), no_promote()), static_cast(0.028626070441920717401063405140884849129L), fine_tolerance); // // Ei: // diff --git a/test/test_expm1_extra.cpp b/test/test_expm1_extra.cpp deleted file mode 100644 index 02e1c59ea3..0000000000 --- a/test/test_expm1_extra.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright John Maddock 2024. -// 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) - -#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error - -#define BOOST_TEST_MAIN -#include -#include -#include -#include - -#define SC_(x) static_cast(BOOST_STRINGIZE(x)) - -#include "log1p_expm1_test.hpp" - -// -// DESCRIPTION: -// ~~~~~~~~~~~~ -// -// This file tests the functions log1p and expm1 for -// simple multiprecision types which are able to utilize -// our own rational approximations. This tests those -// approximations even when float/double/long double -// are not using them. -// - -void expected_results() -{ - // - // Define the max and mean errors expected for - // various compilers and platforms. - // - - // - // Catch all cases come last: - // - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*", // test type(s) - ".*", // test data group - ".*", // test function - 4, // Max Peek error - 3); // Max mean error - - // - // Finish off by printing out the compiler/stdlib/platform names, - // we do this to make it easier to mark up expected error rates. - // - std::cout << "Tests run with " << BOOST_COMPILER << ", " - << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; -} - - -BOOST_AUTO_TEST_CASE( test_main ) -{ - expected_results(); - - test(boost::multiprecision::cpp_bin_float_double(0), "UDT double"); - test(boost::multiprecision::cpp_bin_float_double_extended(0), "UDT 80-bit long double"); - test(boost::multiprecision::cpp_bin_float_quad(0), "UDT quad-float"); - test(boost::multiprecision::number >(0), "UDT 36 digits"); -} - diff --git a/test/test_expm1_simple.cpp b/test/test_expm1_simple.cpp index 22b88a22cb..bf2c2688a9 100644 --- a/test/test_expm1_simple.cpp +++ b/test/test_expm1_simple.cpp @@ -7,9 +7,16 @@ #include "sycl/sycl.hpp" #endif +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE #include #include -#include +#endif #include "math_unit_test.hpp" constexpr int N = 50000; diff --git a/test/test_extreme_value.cpp b/test/test_extreme_value.cpp index dd0c32ae47..f257b4b92f 100644 --- a/test/test_extreme_value.cpp +++ b/test/test_extreme_value.cpp @@ -251,8 +251,13 @@ void test_spots(RealType) BOOST_CHECK_EQUAL(cdf(extreme_value_distribution(), inf), 1); BOOST_CHECK_EQUAL(cdf(complement(extreme_value_distribution(), -inf)), 1); BOOST_CHECK_EQUAL(cdf(complement(extreme_value_distribution(), inf)), 0); - BOOST_CHECK_EQUAL(logcdf(extreme_value_distribution(), -inf), 0); - BOOST_CHECK_EQUAL(logcdf(extreme_value_distribution(), inf), 1); + // log(0) is an exact -infinity, which goes to the overflow policy: + BOOST_CHECK_THROW(logcdf(extreme_value_distribution(), -inf), std::overflow_error); + BOOST_CHECK_THROW(logcdf(complement(extreme_value_distribution(), inf)), std::overflow_error); + BOOST_CHECK_EQUAL(logcdf(extreme_value_distribution(), inf), 0); + BOOST_CHECK_EQUAL(logcdf(complement(extreme_value_distribution(), -inf)), 0); + typedef boost::math::policies::policy > ignore_overflow; + BOOST_CHECK_EQUAL(logcdf(extreme_value_distribution(), -inf), -inf); // Test NaN policy using boost::math::policies::policy; @@ -326,6 +331,21 @@ void test_spots(RealType) } // template void test_spots(RealType) +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType b, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(entropy(extreme_value_distribution(a, b)), h, tol); + }; + check(static_cast(0.0L), static_cast(1.0L), static_cast(1.57721566490153286060651209008240243104215934L)); + check(static_cast(2.0L), static_cast(0.5L), static_cast(0.884068484341587551189279968624225862966659202L)); + check(static_cast(-1.0L), static_cast(1000.0L), static_cast(8.4849709438836699126604864541354950538454638L)); +} + BOOST_AUTO_TEST_CASE( test_main ) { @@ -336,11 +356,15 @@ BOOST_AUTO_TEST_CASE( test_main ) // Basic sanity-check spot values. // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. OK at decdigits = 0 tolerance = 0.0001 % + test_entropy(0.0F); test_spots(0.0); // Test double. OK at decdigits 7, tolerance = 1e07 % + test_entropy(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. + test_entropy(0.0L); #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x582)) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #else std::cout << "The long double tests have been disabled on this platform " diff --git a/test/test_fft.cpp b/test/test_fft.cpp new file mode 100644 index 0000000000..fcd9d41fee --- /dev/null +++ b/test/test_fft.cpp @@ -0,0 +1,630 @@ +/* + * Copyright Nick Thompson, 2026 + * 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) + */ + +#include +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Counts every allocation, so that the tests can check that transforms don't allocate after construction. +static std::size_t allocations = 0; + +void* operator new(std::size_t size) +{ + ++allocations; + if (void* p = std::malloc(size == 0 ? 1 : size)) + { + return p; + } + throw std::bad_alloc(); +} + +void operator delete(void* p) noexcept +{ + std::free(p); +} + +void operator delete(void* p, std::size_t) noexcept +{ + std::free(p); +} + +using boost::math::tools::fft; +using boost::math::tools::real_fft; +using boost::multiprecision::cpp_bin_float_50; +using boost::multiprecision::cpp_bin_float_100; +using boost::multiprecision::cpp_complex_50; +using boost::multiprecision::cpp_complex_100; +using boost::multiprecision::cpp_complex_quad; + +template +using real_t = typename fft::real_type; + +template +real_t squared_modulus(Complex const& z) +{ + return z.real() * z.real() + z.imag() * z.imag(); +} + +inline double log2_length(std::size_t n) +{ + return n < 2 ? 1.0 : std::log2(double(n)); +} + +// O(n^2) DFT in the precision of RefComplex, with twiddles computed directly from the reduced angle 2*pi*(jk mod n)/n. +template +std::vector naive_dft(std::vector const& x) +{ + using Ref = real_t; + using std::cos; + using std::sin; + std::size_t n = x.size(); + std::vector wr(n), wi(n); + Ref two_pi = 2 * boost::math::constants::pi(); + for (std::size_t k = 0; k < n; ++k) + { + Ref theta = two_pi * Ref(k) / Ref(n); + wr[k] = cos(theta); + wi[k] = -sin(theta); + } + std::vector X(n); + for (std::size_t k = 0; k < n; ++k) + { + Ref re = 0; + Ref im = 0; + for (std::size_t j = 0; j < n; ++j) + { + std::size_t i = (j * k) % n; + re += x[j].real() * wr[i] - x[j].imag() * wi[i]; + im += x[j].real() * wi[i] + x[j].imag() * wr[i]; + } + X[k] = RefComplex(re, im); + } + return X; +} + +// Random input whose components are exactly representable in float, so every type sees the same data. +std::vector> random_input(std::size_t n, std::mt19937_64& gen) +{ + std::uniform_real_distribution dis(-1, 1); + std::vector> x(n); + for (auto& z : x) + { + z = std::complex(dis(gen), dis(gen)); + } + return x; +} + +template +Complex convert(std::complex const& z) +{ + using Real = real_t; + return Complex(Real(z.real()), Real(z.imag())); +} + +template +std::vector reference(std::vector> const& x) +{ + std::vector xr(x.size()); + for (std::size_t j = 0; j < x.size(); ++j) + { + xr[j] = convert(x[j]); + } + return naive_dft(xr); +} + +// Normwise relative error O(eps*sqrt(log n)); largest single error relative to the rms of X, O(eps*log n). +template +bool check_spectrum(ComplexContainer const& y, std::vector const& X, std::size_t count, std::size_t n) +{ + using Real = real_t; + using Ref = real_t; + using std::sqrt; + Ref err2 = 0; + Ref norm2 = 0; + Ref max_err2 = 0; + for (std::size_t k = 0; k < count; ++k) + { + RefComplex d(Ref(y[k].real()) - X[k].real(), Ref(y[k].imag()) - X[k].imag()); + Ref e2 = squared_modulus(d); + err2 += e2; + norm2 += squared_modulus(X[k]); + if (e2 > max_err2) + { + max_err2 = e2; + } + } + Real eps = std::numeric_limits::epsilon(); + Real L = Real(log2_length(n)); + Real rms = Real(sqrt(err2 / norm2)); + Real worst = Real(sqrt(max_err2 / (norm2 / Ref(count)))); + bool ok = CHECK_LE(rms, 2 * eps * sqrt(L)); + ok = CHECK_LE(worst, 3 * eps * L) && ok; + if (!ok) + { + std::cerr << " n = " << n << "\n"; + } + return ok; +} + +template +void check_round_trip(ComplexContainer const& y, std::vector> const& x) +{ + using Real = real_t; + using std::sqrt; + std::size_t n = x.size(); + Real err2 = 0; + Real norm2 = 0; + for (std::size_t j = 0; j < n; ++j) + { + Complex xj = convert(x[j]); + err2 += squared_modulus(Complex(y[j].real() - xj.real(), y[j].imag() - xj.imag())); + norm2 += squared_modulus(xj); + } + Real eps = std::numeric_limits::epsilon(); + if (!CHECK_LE(Real(sqrt(err2 / norm2)), 4 * eps * Real(sqrt(Real(log2_length(n)))))) + { + std::cerr << " n = " << n << "\n"; + } +} + +template +void check_against_reference(std::vector> const& x, std::vector const& X) +{ + std::size_t n = x.size(); + std::vector y(n); + for (std::size_t j = 0; j < n; ++j) + { + y[j] = convert(x[j]); + } + fft f(n); + CHECK_EQUAL(f.size(), n); + f.transform(y); + check_spectrum(y, X, n, n); + f.inverse_transform(y); + check_round_trip(y, x); +} + +void test_against_naive_dft() +{ + std::mt19937_64 gen(17); + // Powers of 2; mixed-radix lengths, whose prime factors are at most 97 (including 11-, 13- and 17-smooth ones + // and the primes 89 and 97 just below the cutoff); and Bluestein lengths, with a prime factor above 97 + // (101 and 103 just above it, 127, 509, and composites such as 2*101). + std::vector lengths{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 22, 25, 27, 30, + 31, 32, 45, 49, 60, 64, 89, 97, 98, 100, 101, 103, 120, 125, 127, 128, 143, 169, + 187, 194, 202, 210, 243, 256, 289, 343, 360, 509, 512, 735, 1000, 1001, 1024}; + for (std::size_t n : lengths) + { + auto x = random_input(n, gen); + auto X = reference(x); + check_against_reference>(x, X); + check_against_reference>(x, X); + check_against_reference>(x, X); + } + for (std::size_t n : {1, 2, 3, 5, 6, 7, 8, 11, 12, 13, 16, 17, 30, 49, 64, 89, 97, 100, 101, 128, 143}) + { + auto x = random_input(n, gen); + auto X = reference(x); + check_against_reference(x, X); + check_against_reference(x, X); + } +} + +// Lengths too long for the O(n^2) reference: compare against the FFT in cpp_complex_50, +// whose own accuracy is established above. This checks the log n growth of the error bound. +void test_long_lengths() +{ + std::mt19937_64 gen(29); + for (std::size_t n : {2018, 2401, 3072, 3125, 4096, 4099, 6208, 6464, 10000, 11011, 12297, 16384, 65536, 100000}) + { + auto x = random_input(n, gen); + std::vector X(n); + for (std::size_t j = 0; j < n; ++j) + { + X[j] = convert(x[j]); + } + fft(n).transform(X); + check_against_reference>(x, X); + check_against_reference>(x, X); + } +} + +// The container matrix: std::vector and std::array, of std::complex and of cpp_complex_50, +// for C2C, and the same with real inputs for R2C, at a power of 2, a smooth even and a smooth odd composite, +// and an odd and an even length with a large prime factor. +template +void test_containers() +{ + using Real = real_t; + std::mt19937_64 gen(N); + auto x = random_input(N, gen); + auto X = reference(x); + + // C2C, std::vector and std::array. + fft f(N); + std::vector v(N); + std::array a; + for (std::size_t j = 0; j < N; ++j) + { + v[j] = convert(x[j]); + a[j] = v[j]; + } + f.transform(v); + f.transform(a); + check_spectrum(v, X, N, N); + check_spectrum(a, X, N, N); + f.inverse_transform(v); + f.inverse_transform(a); + check_round_trip(v, x); + check_round_trip(a, x); + + // R2C: the real parts of x as input, in a vector or an array, into a vector or an array of n/2 + 1. + std::vector> xr(N); + for (std::size_t j = 0; j < N; ++j) + { + xr[j] = std::complex(x[j].real(), 0); + } + auto XR = reference(xr); + std::vector rv(N); + std::array ra; + for (std::size_t j = 0; j < N; ++j) + { + rv[j] = Real(x[j].real()); + ra[j] = rv[j]; + } + real_fft rf(N); + CHECK_EQUAL(rf.size(), N); + constexpr std::size_t M = N / 2 + 1; + std::vector out_v(M); + std::array out_a; + rf.transform(rv, out_v); + check_spectrum(out_v, XR, M, N); + rf.transform(ra, out_a); + check_spectrum(out_a, XR, M, N); + rf.transform(rv, out_a); + check_spectrum(out_a, XR, M, N); + rf.transform(ra, out_v); + check_spectrum(out_v, XR, M, N); + + // Round trip through the complex inverse, after filling in X[n-k] = conj(X[k]). + std::vector full(N); + for (std::size_t k = 0; k < N; ++k) + { + Complex z = out_v[k < M ? k : N - k]; + full[k] = k < M ? z : Complex(z.real(), -z.imag()); + } + f.inverse_transform(full); + check_round_trip(full, xr); + + // Wrong sizes throw. + std::vector too_long(M + 1); + std::array too_long_array; + std::vector too_short(N - 1); + std::vector wrong_input(N + 1); + CHECK_THROW(rf.transform(rv, too_long), std::domain_error); + CHECK_THROW(rf.transform(ra, too_long_array), std::domain_error); + CHECK_THROW(rf.transform(wrong_input, out_v), std::domain_error); + CHECK_THROW(f.transform(too_short), std::domain_error); + CHECK_THROW(f.inverse_transform(too_short), std::domain_error); +} + +template +void test_container_matrix() +{ + test_containers(); + test_containers(); + test_containers(); + test_containers(); + test_containers(); + test_containers(); + test_containers(); +} + +// exp(2*pi*i*p/n), with the argument reduced exactly. +template +Complex unit_root(std::size_t p, std::size_t n) +{ + using Real = real_t; + Real x = Real(2 * (p % n)) / Real(n); + return Complex(boost::math::cos_pi(x), boost::math::sin_pi(x)); +} + +template +void test_known_signals() +{ + using Real = real_t; + Real eps = std::numeric_limits::epsilon(); + for (std::size_t n : {1, 2, 3, 4, 7, 8, 12, 16, 31, 64, 100}) + { + fft f(n); + Real L = Real(log2_length(n)); + // Delta at 0 -> all ones. + std::vector v(n, Complex(0, 0)); + v[0] = Complex(1, 0); + f.transform(v); + for (std::size_t k = 0; k < n; ++k) + { + CHECK_ABSOLUTE_ERROR(Real(1), Real(v[k].real()), 4 * eps * L); + CHECK_ABSOLUTE_ERROR(Real(0), Real(v[k].imag()), 4 * eps * L); + } + // Constant -> n at k = 0. + std::fill(v.begin(), v.end(), Complex(1, 0)); + f.transform(v); + CHECK_ABSOLUTE_ERROR(Real(n), Real(v[0].real()), 4 * n * eps * L); + for (std::size_t k = 1; k < n; ++k) + { + CHECK_ABSOLUTE_ERROR(Real(0), Real(v[k].real()), 4 * n * eps * L); + CHECK_ABSOLUTE_ERROR(Real(0), Real(v[k].imag()), 4 * n * eps * L); + } + // Single tone exp(2*pi*i*m*j/n) -> n at k = m: this checks the sign convention. + std::size_t m = n / 3; + for (std::size_t j = 0; j < n; ++j) + { + v[j] = unit_root(m * j, n); + } + f.transform(v); + for (std::size_t k = 0; k < n; ++k) + { + CHECK_ABSOLUTE_ERROR(Real(k == m ? n : 0), Real(v[k].real()), 4 * n * eps * L); + CHECK_ABSOLUTE_ERROR(Real(0), Real(v[k].imag()), 4 * n * eps * L); + } + // A delta at m transforms to exp(-2*pi*i*m*k/n). + std::fill(v.begin(), v.end(), Complex(0, 0)); + v[m] = Complex(1, 0); + f.transform(v); + for (std::size_t k = 0; k < n; ++k) + { + Complex expected = unit_root(m * k, n); + CHECK_ABSOLUTE_ERROR(Real(expected.real()), Real(v[k].real()), 4 * eps * L); + CHECK_ABSOLUTE_ERROR(Real(-expected.imag()), Real(v[k].imag()), 4 * eps * L); + } + } + // Power-of-two deltas are exact. + fft f(1024); + std::vector v(1024, Complex(0, 0)); + v[0] = Complex(1, 0); + f.transform(v); + for (auto const& z : v) + { + CHECK_EQUAL(Real(z.real()), Real(1)); + CHECK_EQUAL(Real(z.imag()), Real(0)); + } +} + +template +void test_parseval_and_linearity() +{ + using Real = real_t; + using std::sqrt; + std::mt19937_64 gen(5); + std::uniform_real_distribution dis(-1, 1); + Real eps = std::numeric_limits::epsilon(); + for (std::size_t n : {3, 16, 100, 127, 256, 1000, 4096, 6000}) + { + fft f(n); + Real L = Real(log2_length(n)); + std::vector x(n), y(n), s(n); + Real a = dis(gen); + Real b = dis(gen); + for (std::size_t j = 0; j < n; ++j) + { + x[j] = Complex(dis(gen), dis(gen)); + y[j] = Complex(dis(gen), dis(gen)); + s[j] = a * x[j] + b * y[j]; + } + Real energy = 0; + for (auto const& z : x) + { + energy += squared_modulus(z); + } + f.transform(x); + f.transform(y); + f.transform(s); + // Parseval: sum |X|^2 = n sum |x|^2. + Real spectral_energy = 0; + for (auto const& z : x) + { + spectral_energy += squared_modulus(z); + } + CHECK_ULP_CLOSE(energy, spectral_energy / Real(n), static_cast(8 * sqrt(Real(n)) * L)); + // Linearity, relative to the size of the coefficients, which is about sqrt(n). + Real worst = 0; + for (std::size_t k = 0; k < n; ++k) + { + worst = (std::max)(worst, Real(sqrt(squared_modulus(Complex(s[k] - (a * x[k] + b * y[k])))))); + } + CHECK_LE(worst, 16 * eps * L * sqrt(Real(n))); + } +} + +template +void test_real_fft() +{ + using Real = real_t; + using std::sqrt; + std::mt19937_64 gen(11); + std::uniform_real_distribution dis(-1, 1); + Real eps = std::numeric_limits::epsilon(); + for (std::size_t n : {1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 15, 16, 64, 100, 127, 1024, 1025}) + { + std::vector x(n); + std::vector z(n); + for (std::size_t j = 0; j < n; ++j) + { + x[j] = dis(gen); + z[j] = Complex(x[j], 0); + } + fft(n).transform(z); + real_fft rf(n); + std::vector X(n / 2 + 1); + rf.transform(x, X); + Real scale = sqrt(Real(n)); + Real L = Real(log2_length(n)); + for (std::size_t k = 0; k < X.size(); ++k) + { + CHECK_ABSOLUTE_ERROR(Real(z[k].real()), Real(X[k].real()), 8 * eps * L * scale); + CHECK_ABSOLUTE_ERROR(Real(z[k].imag()), Real(X[k].imag()), 8 * eps * L * scale); + } + } +} + +template +void test_interfaces() +{ + using Real = real_t; + CHECK_THROW(fft(0), std::domain_error); + CHECK_THROW(real_fft(0), std::domain_error); + // n = 1 is the identity. + fft one(1); + std::vector w{Complex(3, 4)}; + one.transform(w); + CHECK_EQUAL(Real(w[0].real()), Real(3)); + CHECK_EQUAL(Real(w[0].imag()), Real(4)); + one.inverse_transform(w); + CHECK_EQUAL(Real(w[0].real()), Real(3)); + CHECK_EQUAL(Real(w[0].imag()), Real(4)); +} + +template +bool identical(std::vector const& a, std::vector const& b) +{ + if (a.size() != b.size()) + { + return false; + } + for (std::size_t k = 0; k < a.size(); ++k) + { + if (!(a[k].real() == b[k].real() && a[k].imag() == b[k].imag())) + { + return false; + } + } + return true; +} + +// The out-of-place overloads agree with the in-place ones to 0 ulps, leave their input alone, and repeated +// transforms (which reuse the object's workspace) and a second object give the same bits. +// After construction, no transform allocates. +template +void test_overloads(std::vector const& lengths) +{ + using Real = real_t; + std::mt19937_64 gen(17); + std::uniform_real_distribution dis(-1, 1); + for (std::size_t n : lengths) + { + std::vector x(n); + for (auto& z : x) + { + z = Complex(Real(dis(gen)), Real(dis(gen))); + } + std::vector const x0 = x; + fft f(n); + fft g(n); + std::vector in_place = x; + std::vector again = x; + std::vector other = x; + std::vector out(n); + std::vector inv_in_place = x; + std::vector inv_out(n); + std::size_t before = allocations; + f.transform(in_place); + f.transform(x, out); + f.transform(again); + g.transform(other); + f.inverse_transform(inv_in_place); + f.inverse_transform(x, inv_out); + std::size_t after = allocations; + if (!CHECK_EQUAL(after - before, std::size_t(0))) + { + std::cerr << " fft of length " << n << " allocated.\n"; + } + bool ok = CHECK_EQUAL(identical(x, x0), true); + ok = CHECK_EQUAL(identical(out, in_place), true) && ok; + ok = CHECK_EQUAL(identical(again, in_place), true) && ok; + ok = CHECK_EQUAL(identical(other, in_place), true) && ok; + ok = CHECK_EQUAL(identical(inv_out, inv_in_place), true) && ok; + if (!ok) + { + std::cerr << " Overloads of the fft of length " << n << " disagree.\n"; + } + + // real_fft: repeated calls reuse its workspace (and its odd-n buffer). + std::vector r(n); + for (auto& t : r) + { + t = Real(dis(gen)); + } + real_fft rf(n); + real_fft rg(n); + std::vector R1(n / 2 + 1); + std::vector R2(n / 2 + 1); + std::vector R3(n / 2 + 1); + before = allocations; + rf.transform(r, R1); + rf.transform(r, R2); + rg.transform(r, R3); + after = allocations; + if (!CHECK_EQUAL(after - before, std::size_t(0))) + { + std::cerr << " real_fft of length " << n << " allocated.\n"; + } + ok = CHECK_EQUAL(identical(R2, R1), true); + ok = CHECK_EQUAL(identical(R3, R1), true) && ok; + if (!ok) + { + std::cerr << " Repeated real_fft transforms of length " << n << " disagree.\n"; + } + } +} + +int main() +{ + test_against_naive_dft(); + test_long_lengths(); + + test_container_matrix, cpp_complex_50>(); + test_container_matrix(); + + test_known_signals>(); + test_known_signals>(); + test_known_signals>(); + test_known_signals(); + + test_parseval_and_linearity>(); + test_parseval_and_linearity>(); + test_parseval_and_linearity>(); + + test_real_fft>(); + test_real_fft>(); + test_real_fft>(); + test_real_fft(); + + test_interfaces>(); + test_interfaces>(); + test_interfaces(); + + // Mixed-radix lengths (including 11-, 13- and 17-smooth ones, and 89, 97 and 97*64 just below the cutoff), + // and Bluestein ones (101, 103 and 101*64 just above it, 2018, 4099). + std::vector const lengths{1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 16, 17, 25, 27, 30, 49, 64, 89, + 97, 100, 101, 103, 128, 143, 169, 210, 243, 289, 360, 1000, 1001, 1024, 1156, + 2018, 4099, 6208, 6464}; + test_overloads>(lengths); + test_overloads>(lengths); + test_overloads({1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 16, 17, 30, 64, 89, 97, 100, 101, 143, 289, 360}); + + return boost::math::test::report_errors(); +} diff --git a/test/test_fft_module.cpp b/test/test_fft_module.cpp new file mode 100644 index 0000000000..f02481e929 --- /dev/null +++ b/test/test_fft_module.cpp @@ -0,0 +1,135 @@ +/* + * Copyright Nick Thompson, 2026 + * 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) + * + * Module build check for . It exercises fft and real_fft through + * the boost.math module with std::vector and std::array of std::complex (and of double + * for real_fft), on the three code paths (powers of 2, mixed radix, Bluestein). + * Multiprecision does not work in module mode, so the multiprecision cases of test_fft.cpp are + * dropped and the reference is a naive DFT in long double. + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#endif +#include "math_unit_test.hpp" + +using boost::math::tools::fft; +using boost::math::tools::real_fft; +using complex = std::complex; + +std::vector> naive_dft(std::vector const& x) +{ + std::size_t n = x.size(); + std::vector> X(n); + for (std::size_t k = 0; k < n; ++k) + { + std::complex s(0, 0); + for (std::size_t j = 0; j < n; ++j) + { + long double theta = -2 * 3.14159265358979323846264338327950288L * static_cast((j * k) % n) / static_cast(n); + s += std::complex(x[j].real(), x[j].imag()) * std::complex(std::cos(theta), std::sin(theta)); + } + X[k] = s; + } + return X; +} + +template +void check_spectrum(Container const& y, std::vector> const& X, std::size_t count, std::size_t n) +{ + long double err2 = 0; + long double norm2 = 0; + for (std::size_t k = 0; k < count; ++k) + { + err2 += std::norm(std::complex(y[k].real(), y[k].imag()) - X[k]); + norm2 += std::norm(X[k]); + } + double L = n < 2 ? 1.0 : std::log2(double(n)); + // Allow for the reference's own error where long double is no wider than double. + double reference_error = double(4 * std::numeric_limits::epsilon()) * std::sqrt(double(n)); + CHECK_LE(double(std::sqrt(err2 / norm2)), 4 * std::numeric_limits::epsilon() * std::sqrt(L) + reference_error); +} + +template +void check_round_trip(Container const& y, std::vector const& x) +{ + double L = x.size() < 2 ? 1.0 : std::log2(double(x.size())); + for (std::size_t j = 0; j < x.size(); ++j) + { + CHECK_ABSOLUTE_ERROR(x[j].real(), y[j].real(), 8 * std::numeric_limits::epsilon() * L); + CHECK_ABSOLUTE_ERROR(x[j].imag(), y[j].imag(), 8 * std::numeric_limits::epsilon() * L); + } +} + +template +void test_containers() +{ + std::vector x(N); + for (std::size_t j = 0; j < N; ++j) + { + x[j] = complex(std::cos(1.7 * double(j)), std::sin(0.3 * double(j * j))); + } + auto X = naive_dft(x); + + fft f(N); + std::vector v(x); + std::array a; + std::copy(x.begin(), x.end(), a.begin()); + f.transform(v); + f.transform(a); + check_spectrum(v, X, N, N); + check_spectrum(a, X, N, N); + f.inverse_transform(v); + f.inverse_transform(a); + check_round_trip(v, x); + check_round_trip(a, x); + + std::vector xr(N); + std::vector rv(N); + std::array ra; + for (std::size_t j = 0; j < N; ++j) + { + xr[j] = complex(x[j].real(), 0); + rv[j] = x[j].real(); + ra[j] = rv[j]; + } + auto XR = naive_dft(xr); + constexpr std::size_t M = N / 2 + 1; + real_fft rf(N); + std::vector out_v(M); + std::array out_a; + rf.transform(rv, out_v); + check_spectrum(out_v, XR, M, N); + rf.transform(ra, out_a); + check_spectrum(out_a, XR, M, N); + std::array wrong; + CHECK_THROW(rf.transform(rv, wrong), std::domain_error); +} + +int main() +{ + test_containers<1>(); + test_containers<2>(); + test_containers<16>(); + test_containers<12>(); + test_containers<45>(); + test_containers<17>(); + test_containers<38>(); + test_containers<97>(); + CHECK_THROW(fft(0), std::domain_error); + return boost::math::test::report_errors(); +} diff --git a/test/test_fibonacci.cpp b/test/test_fibonacci.cpp index 1a5120b240..cf2bbe0805 100644 --- a/test/test_fibonacci.cpp +++ b/test/test_fibonacci.cpp @@ -6,11 +6,9 @@ #include #include #include -#include +#include "math_unit_test.hpp" #include #include -#define BOOST_TEST_MODULE Fibonacci_Test_Module -#include using boost::math::fibonacci; using boost::math::unchecked_fibonacci; @@ -19,59 +17,59 @@ typedef cpp_int BST; typedef number> BST_2048; // Some sanity checks using OEIS A000045 -BOOST_AUTO_TEST_CASE(sanity_checks) { - BOOST_TEST(fibonacci(0) == 0); // Base case - BOOST_TEST(fibonacci(1) == 1); // Base case - BOOST_TEST(fibonacci(2) == 1); // Base Case - BOOST_TEST(fibonacci(3) == 2); // First computation - BOOST_TEST(fibonacci(10) == 55); - BOOST_TEST(fibonacci(15) == 610); - BOOST_TEST(fibonacci(18) == 2584); - BOOST_TEST(fibonacci(40) == 102334155); +void sanity_checks() { + CHECK_TRUE(fibonacci(0) == 0); // Base case + CHECK_TRUE(fibonacci(1) == 1); // Base case + CHECK_TRUE(fibonacci(2) == 1); // Base Case + CHECK_TRUE(fibonacci(3) == 2); // First computation + CHECK_TRUE(fibonacci(10) == 55); + CHECK_TRUE(fibonacci(15) == 610); + CHECK_TRUE(fibonacci(18) == 2584); + CHECK_TRUE(fibonacci(40) == 102334155); } // Tests unchecked_fibonacci by computing naively -BOOST_AUTO_TEST_CASE(big_integer_check) { +void big_integer_check() { // GMP is used as type for fibonacci and cpp_int is for naive computation BST val = 0, a = 0, b = 1; for (int i = 0; i <= 1e4; ++i) { - BOOST_TEST(fibonacci(i) == a); + CHECK_TRUE(fibonacci(i) == a); val = b, b += a, a = val; } } // Check for overflow throw using magic constants -BOOST_AUTO_TEST_CASE(overflow_check) { +void overflow_check() { // 1. check for unsigned integer overflow - BOOST_CHECK_NO_THROW(fibonacci(93)); - BOOST_CHECK_THROW(fibonacci(94), std::exception); - BOOST_CHECK_NO_THROW(unchecked_fibonacci(94)); + CHECK_NO_THROW(fibonacci(93)); + CHECK_THROW(fibonacci(94), std::exception); + CHECK_NO_THROW(unchecked_fibonacci(94)); // 2. check for signed integer overflow - BOOST_CHECK_NO_THROW(fibonacci(91)); + CHECK_NO_THROW(fibonacci(91)); // BOOST_CHECK_THROW(fibonacci(92), std::exception); // this should be the correct value but imprecisions - BOOST_CHECK_THROW(fibonacci(93), std::exception); + CHECK_THROW(fibonacci(93), std::exception); // In UBSAN this will error out, but it is expected - BOOST_CHECK_NO_THROW(unchecked_fibonacci(93)); + CHECK_NO_THROW(unchecked_fibonacci(93)); // 3. check for floating point (double) - BOOST_CHECK_NO_THROW(fibonacci(78)); - BOOST_CHECK_THROW(fibonacci(79), std::exception); - BOOST_CHECK_NO_THROW(unchecked_fibonacci(79)); + CHECK_NO_THROW(fibonacci(78)); + CHECK_THROW(fibonacci(79), std::exception); + CHECK_NO_THROW(unchecked_fibonacci(79)); // 4. check using boost's multiprecision unchecked integer - BOOST_CHECK_NO_THROW(fibonacci(2950)); + CHECK_NO_THROW(fibonacci(2950)); // BOOST_CHECK_THROW(fibonacci(2951), std::exception); // this should be the correct value but imprecisions - BOOST_CHECK_THROW(fibonacci(2952), std::exception); - BOOST_CHECK_NO_THROW(unchecked_fibonacci(2952)); + CHECK_THROW(fibonacci(2952), std::exception); + CHECK_NO_THROW(unchecked_fibonacci(2952)); } -BOOST_AUTO_TEST_CASE(generator_check) { +void generator_check() { // first 5 values boost::math::fibonacci_generator gen; for (int i : {0, 1, 1, 2, 3, 5, 8, 13, 21}) { - BOOST_TEST(gen() == i); + CHECK_TRUE(gen() == i); } // test whether the generator is set correctly to the given index --- next @@ -79,7 +77,7 @@ BOOST_AUTO_TEST_CASE(generator_check) { gen.set(next); BST_2048 a = fibonacci(next), b = fibonacci(next + 1); for (int i = next; i < next + 50; ++i) { - BOOST_TEST(gen() == a); + CHECK_TRUE(gen() == a); swap(a, b); b += a; } @@ -88,7 +86,7 @@ BOOST_AUTO_TEST_CASE(generator_check) { a = fibonacci(next), b = fibonacci(next + 1); gen.set(next); for (int i = next; i < next + 50; ++i) { - BOOST_TEST(gen() == a); + CHECK_TRUE(gen() == a); swap(a, b); b += a; } @@ -96,7 +94,7 @@ BOOST_AUTO_TEST_CASE(generator_check) { #ifndef BOOST_NO_CXX14_CONSTEXPR -BOOST_AUTO_TEST_CASE(constexpr_check) { +void constexpr_check() { constexpr int x = boost::math::unchecked_fibonacci(32); static_assert(x == 2178309, "constexpr check 1"); @@ -112,3 +110,15 @@ BOOST_AUTO_TEST_CASE(constexpr_check) { } #endif + +int main() +{ + sanity_checks(); + big_integer_check(); + overflow_check(); + generator_check(); +#ifndef BOOST_NO_CXX14_CONSTEXPR + constexpr_check(); +#endif + return boost::math::test::report_errors(); +} diff --git a/test/test_finite_difference_module.cpp b/test/test_finite_difference_module.cpp new file mode 100644 index 0000000000..d6d23b3a25 --- /dev/null +++ b/test/test_finite_difference_module.cpp @@ -0,0 +1,73 @@ +// (C) Copyright Nick Thompson 2018. +// (C) Copyright Matt Borland 2026. +// 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) +// +// Module build check for the finite-difference numerical differentiation +// component. Consuming boost.math as a named module, this exercises both public +// entry points, finite_difference_derivative across every supported order and +// complex_step_derivative, using functions whose derivatives are exact and +// mathematically certain (polynomials) so no library helpers are needed to +// produce the expected values. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif +#include "math_unit_test.hpp" + +using boost::math::differentiation::finite_difference_derivative; +using boost::math::differentiation::complex_step_derivative; + +// tol_fd bounds the finite-difference approximation error (order 1 is the +// loosest at ~2*sqrt(eps)); tol_cs bounds the essentially exact complex step. +template +void test_spots(const char* type_name, T tol_fd, T tol_cs) +{ + std::cout << "Testing finite_difference for type " << type_name << std::endl; + + // f(x) = x*x has f'(x) = 2x, so f'(3) = 6. Exercise every supported order. + auto square = [](T t) { return t * t; }; + + CHECK_ABSOLUTE_ERROR(static_cast(6), (finite_difference_derivative(square, static_cast(3))), tol_fd); + CHECK_ABSOLUTE_ERROR(static_cast(6), (finite_difference_derivative(square, static_cast(3))), tol_fd); + CHECK_ABSOLUTE_ERROR(static_cast(6), (finite_difference_derivative(square, static_cast(3))), tol_fd); + CHECK_ABSOLUTE_ERROR(static_cast(6), (finite_difference_derivative(square, static_cast(3))), tol_fd); + CHECK_ABSOLUTE_ERROR(static_cast(6), (finite_difference_derivative(square, static_cast(3))), tol_fd); + + // The error-estimate output argument is populated on the default (order 6) path. + T error_estimate {}; + const T d {finite_difference_derivative(square, static_cast(3), &error_estimate)}; + CHECK_ABSOLUTE_ERROR(static_cast(6), d, tol_fd); + CHECK_GE(error_estimate, static_cast(0)); + + // f(x) = x*x*x has f'(x) = 3x*x, so f'(2) = 12 (via the default order). + auto cube = [](T t) { return t * t * t; }; + CHECK_ABSOLUTE_ERROR(static_cast(12), (finite_difference_derivative(cube, static_cast(2))), tol_fd); + + // A straight line f(x) = 2x + 1 has f'(x) = 2 everywhere. + auto line = [](T t) { return static_cast(2) * t + static_cast(1); }; + CHECK_ABSOLUTE_ERROR(static_cast(2), (finite_difference_derivative(line, static_cast(5))), tol_fd); + + // Complex-step differentiation is well conditioned and exact for polynomials. + auto complex_square = [](std::complex z) { return z * z; }; + CHECK_ABSOLUTE_ERROR(static_cast(6), complex_step_derivative(complex_square, static_cast(3)), tol_cs); + + auto complex_cube = [](std::complex z) { return z * z * z; }; + CHECK_ABSOLUTE_ERROR(static_cast(12), complex_step_derivative(complex_cube, static_cast(2)), tol_cs); +} + +int main() +{ + test_spots("double", 1e-5, 1e-11); + test_spots("float", 1e-2f, 1e-5f); + + return boost::math::test::report_errors(); +} diff --git a/test/test_fisher_f.cpp b/test/test_fisher_f.cpp index 0739dfbda2..6650699e5a 100644 --- a/test/test_fisher_f.cpp +++ b/test/test_fisher_f.cpp @@ -413,7 +413,49 @@ void test_spots(RealType) BOOST_CHECK_CLOSE( kurtosis(dist2) , static_cast(6272) * 12 / 3456 + 3, tol2); - // special cases: + + if (!std::is_same::value) + { + RealType df1 = 10; + RealType df2 = 2; + RealType x = 6; + RealType P = cdf(fisher_f_distribution(df1, df2), x); + BOOST_CHECK_CLOSE(fisher_f_distribution::find_v2(x, df1, P), df2, tol2*10); + BOOST_CHECK_CLOSE(fisher_f_distribution::find_v1(x, df2, P), df1, tol2*200); + BOOST_CHECK_CLOSE(fisher_f_distribution::find_v1(boost::math::complement(x, df2, 1-P)), df1, tol2*200); + BOOST_CHECK_CLOSE(fisher_f_distribution::find_v2(boost::math::complement(x, df1, 1-P)), df2, tol2*10); + } + // Test case where two df solve inversion problem + RealType df1 = 5; + RealType df2 = 3.5; + x = 3.51; + RealType P = cdf(fisher_f_distribution(df1, df2), x); + BOOST_MATH_CHECK_THROW(fisher_f_distribution::find_v1(x, df2, P), boost::math::evaluation_error); + BOOST_MATH_CHECK_THROW(fisher_f_distribution::find_v1(boost::math::complement(x, df2, 1-P)), boost::math::evaluation_error); + + df1 = 6; + df2 = 4; + x = 0.5; + P = cdf(fisher_f_distribution(df1, df2), x); + BOOST_MATH_CHECK_THROW(fisher_f_distribution::find_v2(x, df1, P), boost::math::evaluation_error); + BOOST_MATH_CHECK_THROW(fisher_f_distribution::find_v2(boost::math::complement(x, df1, P)), boost::math::evaluation_error); + + // https://github.com/boostorg/math/issues/1495: here the cdf tends to 0 both as v2 -> 0 and + // v2 -> infinity, so every P has two roots. Probing v2 = 1/sqrt(max_value) instead of using + // the limit missed the small root once P fell below the cdf there (v2 = 150 for double). + { + df1 = 10000; + x = static_cast(0.1); + for (RealType df2v : {RealType(1), RealType(10), RealType(50), RealType(150)}) + { + RealType Pv = cdf(fisher_f_distribution(df1, df2v), x); + if (Pv < boost::math::tools::min_value()) + continue; + BOOST_MATH_CHECK_THROW(fisher_f_distribution::find_v2(x, df1, Pv), boost::math::evaluation_error); + } + } + + // special cases: BOOST_MATH_CHECK_THROW( pdf( fisher_f_distribution(static_cast(1), static_cast(1)), @@ -512,6 +554,25 @@ void test_spots(RealType) check_out_of_range >(2, 3); } // template void test_spots(RealType) +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 50 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType b, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(entropy(fisher_f_distribution(a, b)), h, tol); + }; + check(static_cast(1.0L), static_cast(1.0L), static_cast(2.53102424696929079297789159426941184779829508L)); + check(static_cast(3.0L), static_cast(7.0L), static_cast(1.29757386701720675737265722214109674705565741L)); + check(static_cast(0.5L), static_cast(20.0L), static_cast(-0.182688737809773478849227322294024324235751138L)); + check(static_cast(40.0L), static_cast(3.0L), static_cast(1.70499110991526789424530604877101535949383958L)); + check(static_cast(300.0L), static_cast(700.0L), static_cast(-0.908695462402952220696390581813149677008313271L)); + check(static_cast(100000000.0L), static_cast(100000000.0L), static_cast(-7.09825465321156468487440412754032928913414501L)); + check(static_cast(100000000.0L), static_cast(2.0L), static_cast(2.15443132980306565454635751349814086208431867L)); +} + BOOST_AUTO_TEST_CASE( test_main ) { @@ -524,11 +585,15 @@ BOOST_AUTO_TEST_CASE( test_main ) // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. + test_entropy(0.0F); test_spots(0.0); // Test double. + test_entropy(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. + test_entropy(0.0L); #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x582)) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #endif diff --git a/test/test_fourier_transform_daubechies.cpp b/test/test_fourier_transform_daubechies.cpp new file mode 100644 index 0000000000..ea9d00ac38 --- /dev/null +++ b/test/test_fourier_transform_daubechies.cpp @@ -0,0 +1,224 @@ +// boost-no-inspect +/* + * Copyright Nick Thompson, 2023 + * 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) + */ + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_FLOAT128 +#include +using boost::multiprecision::float128; +#endif + +using boost::math::fourier_transform_daubechies_scaling; +using boost::math::fourier_transform_daubechies_wavelet; +using boost::math::tools::summation_condition_number; +using boost::math::constants::two_pi; +using boost::math::constants::pi; +using boost::math::constants::one_div_root_two_pi; +using boost::math::quadrature::trapezoidal; +// 𝓕[φ](-ω) = 𝓕[φ](ω)* +template +void test_evaluation_symmetry() { + std::cout << "Testing evaluation symmetry on the " << p << " vanishing moment scaling function.\n"; + auto phi = fourier_transform_daubechies_scaling(0.0); + CHECK_ULP_CLOSE(one_div_root_two_pi(), phi.real(), 3); + CHECK_ULP_CLOSE(static_cast(0), phi.imag(), 3); + + Real domega = Real(1)/128; + for (Real omega = domega; omega < 10; omega += domega) { + auto phi1 = fourier_transform_daubechies_scaling(-omega); + auto phi2 = fourier_transform_daubechies_scaling(omega); + CHECK_ULP_CLOSE(phi1.real(), phi2.real(), 3); + CHECK_ULP_CLOSE(phi1.imag(), -phi2.imag(), 3); + + auto psi1 = fourier_transform_daubechies_wavelet(-omega); + auto psi2 = fourier_transform_daubechies_wavelet(omega); + CHECK_ULP_CLOSE(psi1.real(), psi2.real(), 3); + CHECK_ULP_CLOSE(psi1.imag(), -psi2.imag(), 3); + } + + for (Real omega = 10; omega < std::cbrt(std::numeric_limits::max()); omega *= 10) { + auto phi1 = fourier_transform_daubechies_scaling(-omega); + auto phi2 = fourier_transform_daubechies_scaling(omega); + CHECK_ULP_CLOSE(phi1.real(), phi2.real(), 3); + CHECK_ULP_CLOSE(phi1.imag(), -phi2.imag(), 3); + } + return; +} + +template +void test_roots() { + std::cout << "Testing roots on the " << p << " vanishing moment scaling function.\n"; + for (long n = 1; n < 100; ++n) { + // All arguments of the form 2πn are roots of the complex function: + // See Daubechies, 10 Lectures on Wavelets, Section 6.2: + Real omega = n*two_pi(); + Real residual = std::norm(fourier_transform_daubechies_scaling(omega)); + CHECK_LE(residual, std::numeric_limits::epsilon()*std::numeric_limits::epsilon()); + } + std::cout << "Testing roots on the " << p << " vanishing moment wavelet.\n"; + // If ωₙ is a root of the 𝓕[𝜙], then 2ωₙ is a root of 𝓕[ψ]. + // In addition, m₀(π) = 0, and m₀ is 2π periodic. + // Recalling 𝓕[ψ](ω) = exp(iω/2)m₀(ω/2 + π)^{*}𝓕[𝜙](ω/2)*phase, + // ω=4nπ are also roots: + for (long n = 0; n < 100; ++n) { + Real omega = 4*n*pi(); + Real residual = std::norm(fourier_transform_daubechies_wavelet(omega)); + CHECK_LE(residual, std::numeric_limits::epsilon()*std::numeric_limits::epsilon()); + } +} + +template +void test_scaling_quadrature() { + std::cout << "Testing numerical quadrature of the scaling function with " << p << " vanishing moments matches numerical evaluation.\n"; + // The quadrature is only a sanity check at 1e-4, and its error is the same on a grid of 2^12 points per + // integer interval as on the default grid (2^18 or more), so don't pay for the default grid. + auto phi = boost::math::daubechies_scaling(12); + auto [tmin, tmax] = phi.support(); + double domega = 1/8.0; + for (double omega = domega; omega < 10; omega += domega) { + // I suspect the quadrature is less accurate than special function evaluation, so this is just a sanity check: + auto f = [&](double t) { + return phi(t)*std::exp(std::complex(0, -omega*t))*one_div_root_two_pi(); + }; + auto expected = trapezoidal(f, tmin, tmax, 2*std::numeric_limits::epsilon()); + auto computed = fourier_transform_daubechies_scaling(static_cast(omega)); + CHECK_MOLLIFIED_CLOSE(static_cast(expected.real()), computed.real(), 1e-4); + CHECK_MOLLIFIED_CLOSE(static_cast(expected.imag()), computed.imag(), 1e-4); + } +} + +template +void test_wavelet_quadrature() { + std::cout << "Testing numerical quadrature of the wavelet with " << p << " vanishing moments matches numerical evaluation.\n"; + // The quadrature error here (about 1e-10 in modulus, and just under 1e-2 in phase near the root at + // omega = 0) is the same on a grid of 2^12 points per integer interval as on the default grid + // (it is the quadrature, not the grid, that limits it), so don't pay for the default grid. + auto psi = boost::math::daubechies_wavelet(12); + auto [tmin, tmax] = psi.support(); + double domega = 1/8.0; + // There is a root at at ω=0, so skip this one because we can't recover the phase of a root. + for (double omega = 2*domega; omega < 10; omega += domega) { + // I suspect the quadrature is less accurate than special function evaluation, so this is just a sanity check: + auto f = [&](double t) { + return psi(t)*std::exp(std::complex(0, -omega*t))*one_div_root_two_pi(); + }; + auto expected = trapezoidal(f, tmin, tmax, std::numeric_limits::epsilon()); + auto computed = fourier_transform_daubechies_wavelet(omega); + if(!CHECK_ABSOLUTE_ERROR(std::abs(expected), std::abs(computed), 1e-9)) { + std::cerr << " |𝓕[ψ](" << omega << ")| is incorrect.\n"; + } + // Again, lots of evidence that the quadrature is less accurate than what we've implemented. + // Graph of the quadrature phase is super janky; graph of the implementation phase is pretty good. + if(!CHECK_ABSOLUTE_ERROR(std::arg(expected), std::arg(computed), 1e-2)) { + std::cerr << " arg(𝓕[ψ](" << omega << ")) is incorrect.\n"; + } + } +} + + +// Tests Daubechies "Ten Lectures on Wavelets", equation 5.1.19: +template +void test_ten_lectures_eq_5_1_19() { + std::cout << "Testing Ten Lectures equation 5.1.19 on " << p << " vanishing moments.\n"; + Real domega = Real(1)/Real(16); + for (Real omega = 0; omega < 1; omega += domega) { + Real term = std::norm(fourier_transform_daubechies_scaling(omega)); + auto sum = summation_condition_number(term); + int64_t l = 1; + while (l < 10000 && term > 2*std::numeric_limits::epsilon()) { + Real tpl = std::norm(fourier_transform_daubechies_scaling(omega + two_pi()*l)); + Real tml = std::norm(fourier_transform_daubechies_scaling(omega - two_pi()*l)); + + sum += tpl; + sum += tml; + ++l; + } + // With arg promotion, I can get this to 13 ULPS: + if (!CHECK_ULP_CLOSE(1/two_pi(), sum.sum(), 125)) { + std::cerr << " Failure with occurs on " << p << " vanishing moments.\n"; + } + } +} + +// Tests Daubechies "Ten Lectures on Wavelets", equation 5.1.38: +template +void test_ten_lectures_eq_5_1_38() { + std::cout << "Testing Ten Lectures equation 5.1.38 on " << p << " vanishing moments.\n"; + Real domega = Real(1)/Real(16); + for (Real omega = 0; omega < 1; omega += domega) { + Real phi_omega_sq = std::norm(fourier_transform_daubechies_scaling(omega)); + Real psi_omega_sq = std::norm(fourier_transform_daubechies_wavelet(omega)); + Real phi_half_omega_sq = std::norm(fourier_transform_daubechies_scaling(omega/2)); + + if (!CHECK_ULP_CLOSE(phi_half_omega_sq, phi_omega_sq + psi_omega_sq, 125)) { + std::cerr << " Failure with occurs on " << p << " vanishing moments at omega = " << omega << "\n"; + } + } +} + + +int main() +{ + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + test_roots(); + + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + test_evaluation_symmetry(); + + // Slow tests: + test_scaling_quadrature<9>(); + test_scaling_quadrature<10>(); + + // This one converges really slowly: + //test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + test_ten_lectures_eq_5_1_19(); + + test_ten_lectures_eq_5_1_38(); + test_ten_lectures_eq_5_1_38(); + test_ten_lectures_eq_5_1_38(); + test_ten_lectures_eq_5_1_38(); + + test_wavelet_quadrature<9>(); + + return boost::math::test::report_errors(); +} diff --git a/test/test_functions_for_optimization.hpp b/test/test_functions_for_optimization.hpp index da989fc09e..19cb976bc3 100644 --- a/test/test_functions_for_optimization.hpp +++ b/test/test_functions_for_optimization.hpp @@ -7,10 +7,11 @@ #ifndef TEST_FUNCTIONS_FOR_OPTIMIZATION_HPP #define TEST_FUNCTIONS_FOR_OPTIMIZATION_HPP +#ifndef BOOST_MATH_BUILD_MODULE #include - #include #include +#endif /* simple n-d quadratic function */ template diff --git a/test/test_gamma.cpp b/test/test_gamma.cpp index 5608944f24..ff215e7cec 100644 --- a/test/test_gamma.cpp +++ b/test/test_gamma.cpp @@ -45,7 +45,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_gamma_dist.cpp b/test/test_gamma_dist.cpp index f1abbfd995..df15e9b6ce 100644 --- a/test/test_gamma_dist.cpp +++ b/test/test_gamma_dist.cpp @@ -248,16 +248,36 @@ void test_spots(RealType) } // template void test_spots(RealType) +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType b, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(entropy(gamma_distribution(a, b)), h, tol); + }; + check(static_cast(0.25L), static_cast(2.0L), static_cast(-0.93942044477417628927930504789461881902455563L)); + check(static_cast(3.0L), static_cast(1.0L), static_cast(1.84757851036301103063025630162298143015981881L)); + check(static_cast(1000000.0L), static_cast(0.5L), static_cast(7.63354629829344781773929420955609401204555101L)); + check(static_cast(10000000000.0L), static_cast(1.0L), static_cast(12.931863998141567828536120343160760900089128L)); +} + BOOST_AUTO_TEST_CASE( test_main ) { // Basic sanity-check spot values. // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. OK at decdigits = 0 tolerance = 0.0001 % + test_entropy(0.0F); test_spots(0.0); // Test double. OK at decdigits 7, tolerance = 1e07 % + test_entropy(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. + test_entropy(0.0L); #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #else std::cout << "The long double tests have been disabled on this platform " diff --git a/test/test_gamma_mp.cpp b/test/test_gamma_mp.cpp index afb06388bd..c5a3b54055 100644 --- a/test/test_gamma_mp.cpp +++ b/test/test_gamma_mp.cpp @@ -118,6 +118,33 @@ void test_gamma(T, const char* name) do_test_gamma(near_m55, name, "near -55"); } +template +void test_tgamma1pm1(T, const char* name) +{ + std::cout << "Testing tgamma1pm1 with type " << name << std::endl; + // + // https://github.com/boostorg/math/issues/1519 + // The lgamma approximations used internally for these types are not accurate enough + // to avoid losing digits to cancellation, errors were as high as 1500 epsilon. + // The arguments are dyadic, reference values calculated with Arb: + // + static const std::array, 8> data = {{ + {{ T(-0.375), SC_(0.4345188480905567756360197394564231366322077722066673307706798580950941973020969146309569665256322935994654337852) }}, + {{ T(0.375), SC_(-0.111086430843774659257572435933755308792224698740403129584327399497564425740749328075507124360869447559309799521) }}, + {{ T(0.75), SC_(-0.080937473151116766153176272477832104861570563918947041577410796282632833679901232072120717838813700063369964821) }}, + {{ T(1.25), SC_(0.1330030963193463474783391112086475009359899009000204585729306248655997636058528505057375427260575938629599223101) }}, + {{ T(1.625), SC_(0.4569332050919717252553325478854297481420860186473965078139717308778300441349421789220656691275952981869570811881) }}, + {{ T(1.75), SC_(0.6083594219855456592319415231637938164922515131418426772395311065053925410601728438737887437820760248891025615618) }}, + {{ T(1.875), SC_(0.7877108988969403106484306138406837807894743299311615258427956959629808411549585601993268102781147763595978133741) }}, + {{ T(1.984375), SC_(0.9714651224878432889438635713198502884452632095994134781726907836796579737404575370382611229556842737635526601037) }}, + }}; + T tolerance = 40 * boost::math::tools::epsilon(); + for(unsigned i = 0; i < data.size(); ++i) + { + BOOST_CHECK_CLOSE_FRACTION(boost::math::tgamma1pm1(data[i][0]), data[i][1], tolerance); + } +} + void expected_results() { // @@ -173,17 +200,25 @@ BOOST_AUTO_TEST_CASE(test_main) using namespace boost::multiprecision; #if !defined(TEST) || (TEST == 1) test_gamma(number >(0), "number >"); + test_tgamma1pm1(number >(0), "number >"); test_gamma(number >(0), "number >"); + test_tgamma1pm1(number >(0), "number >"); #endif #if !defined(TEST) || (TEST == 2) test_gamma(cpp_bin_float_50(0), "cpp_bin_float_50"); + test_tgamma1pm1(cpp_bin_float_50(0), "cpp_bin_float_50"); test_gamma(number >(0), "number >"); + test_tgamma1pm1(number >(0), "number >"); test_gamma(number >(0), "number >"); + test_tgamma1pm1(number >(0), "number >"); #endif #if !defined(TEST) || (TEST == 3) test_gamma(number >(0), "number >"); + test_tgamma1pm1(number >(0), "number >"); test_gamma(number >(0), "number >"); + test_tgamma1pm1(number >(0), "number >"); test_gamma(cpp_bin_float_100(0), "cpp_bin_float_100"); + test_tgamma1pm1(cpp_bin_float_100(0), "cpp_bin_float_100"); #endif } #else // No mp tests diff --git a/test/test_gauss_hermite_quadrature.cpp b/test/test_gauss_hermite_quadrature.cpp new file mode 100644 index 0000000000..be46ce9318 --- /dev/null +++ b/test/test_gauss_hermite_quadrature.cpp @@ -0,0 +1,177 @@ +// Copyright Jacob Hass, 2026 +// Copyright Nick Thompson, 2026 +// 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) + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_FLOAT128 +#include +#endif + +using boost::math::quadrature::gauss_hermite; +using boost::math::quadrature::detail::gauss_hermite_detail; + +// An N-point rule integrates x^(2k) exp(-x^2) exactly for 2k <= 2N - 1, giving Gamma(k + 1/2). +// Odd moments vanish by symmetry. The tolerance grows with k because x^(2k) magnifies the +// rounding of the largest abscissa by a factor of 2k. +template +void test_moments() +{ + // Gamma(k + 1/2) by its recurrence from sqrt(pi), which is more accurate than tgamma for some types. + Real expected = boost::math::constants::root_pi(); + for (unsigned k = 0; k < N; ++k) + { + if (k > 0) + expected *= Real(k) - Real(0.5); + auto even = [k](const Real& x) { Real r = 1; for (unsigned j = 0; j < 2 * k; ++j) r *= x; return r; }; + Real L1; + Real Q = gauss_hermite::integrate(even, &L1); + CHECK_ULP_CLOSE(expected, Q, 16 * (k + 1)); + // The integrand is nonnegative, so the L1 norm is the integral itself. + CHECK_ULP_CLOSE(Q, L1, 16 * (k + 1)); + + auto odd = [k](const Real& x) { Real r = x; for (unsigned j = 0; j < 2 * k; ++j) r *= x; return r; }; + CHECK_EQUAL(Real(gauss_hermite::integrate(odd)), Real(0)); + } +} + +// The tabulated abscissas and weights must agree with those computed on demand. +template +void test_tables_match_on_demand() +{ + using table = gauss_hermite_detail; + using on_demand = gauss_hermite_detail; + CHECK_EQUAL(table::abscissa().size(), on_demand::abscissa().size()); + for (unsigned i = 0; i < table::abscissa().size(); ++i) + { + CHECK_ULP_CLOSE(static_cast(table::abscissa()[i]), on_demand::abscissa()[i], 4); + CHECK_ULP_CLOSE(static_cast(table::weights()[i]), on_demand::weights()[i], 32); + } +} + +// Integral of exp(ix) exp(-x^2) over the real line is sqrt(pi) exp(-1/4). +template +void test_complex(std::size_t ulps, typename Complex::value_type imaginary_tol) +{ + using Real = typename Complex::value_type; + using std::cos; + using std::exp; + using std::sin; + auto f = [](const Real& x) { return Complex(cos(x), sin(x)); }; + Complex Q = gauss_hermite::integrate(f); + Real expected = boost::math::constants::root_pi() * exp(-Real(1) / 4); + CHECK_ULP_CLOSE(expected, Q.real(), ulps); + CHECK_ABSOLUTE_ERROR(Real(0), Q.imag(), imaginary_tol); +} + +template +void test_vector_valued() +{ + using vector = std::valarray; + const vector zero(0.0, 3); + auto norm = [](const vector& v) { return std::sqrt((v * v).sum()); }; + auto f = [](double x) { return vector{1.0, x * x, std::cos(x)}; }; + double L1; + vector Q = gauss_hermite::integrate(f, zero, norm, &L1); + const double root_pi = boost::math::constants::root_pi(); + CHECK_ULP_CLOSE(root_pi, Q[0], 4); + CHECK_ULP_CLOSE(root_pi / 2, Q[1], 4); + CHECK_ULP_CLOSE(root_pi * std::exp(-0.25), Q[2], 16); + CHECK_LE(norm(Q), L1); +} + +// Evaluating H_N directly overflows long before these N; the orthonormal recurrence does not. +template +void test_large_N() +{ + using rule = gauss_hermite; + const double root_pi = boost::math::constants::root_pi(); + CHECK_EQUAL(rule::abscissa().size(), static_cast((N + 1) / 2)); + for (unsigned i = 1; i < rule::abscissa().size(); ++i) + CHECK_LE(rule::abscissa()[i - 1], rule::abscissa()[i]); + CHECK_ULP_CLOSE(root_pi, rule::integrate([](double) { return 1.0; }), 16); + CHECK_ULP_CLOSE(root_pi * std::exp(-0.25), rule::integrate([](double x) { return std::cos(x); }), 16); +} + +// Past N = 706 in double the recurrence overflows, which must be reported through the policy. +void test_overflow() +{ + using ignore_policy = boost::math::policies::policy >; + double L1 = 0; + CHECK_NAN((gauss_hermite::integrate([](double x) { return std::cos(x); }, &L1))); + CHECK_NAN(L1); + using vector = std::valarray; + vector Q = gauss_hermite::integrate([](double x) { return vector{1.0, x}; }, vector(0.0, 2), + [](const vector& v) { return std::sqrt((v * v).sum()); }); + CHECK_EQUAL(Q.size(), std::size_t(2)); + CHECK_NAN(Q[0]); + CHECK_NAN(Q[1]); +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW((gauss_hermite::integrate([](double x) { return std::cos(x); })), boost::math::evaluation_error); +#endif +} + +template +void test_moments_all_N() +{ + test_moments(); + test_moments(); + test_moments(); + test_moments(); + test_moments(); + test_moments(); + test_moments(); +} + +int main() +{ + test_moments_all_N(); + test_moments_all_N(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_moments_all_N(); +#endif +#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS + test_moments(); + test_moments(); +#endif + test_moments_all_N(); + test_moments(); + test_moments(); +#ifdef BOOST_HAS_FLOAT128 + test_moments(); + test_moments(); +#endif + + test_tables_match_on_demand(); + test_tables_match_on_demand(); + test_tables_match_on_demand(); + using cpp_bin_float_100 = boost::multiprecision::cpp_bin_float_100; + test_tables_match_on_demand(); + test_tables_match_on_demand(); + test_tables_match_on_demand(); + + test_complex, 15>(4, 4 * std::numeric_limits::epsilon()); + test_complex(64, 1e-32); + + test_vector_valued<15>(); + test_vector_valued<20>(); + + test_large_N<200>(); + test_large_N<500>(); + test_large_N<706>(); + test_overflow(); + + return boost::math::test::report_errors(); +} diff --git a/test/test_gauss_hermite_quadrature_eigen.cpp b/test/test_gauss_hermite_quadrature_eigen.cpp new file mode 100644 index 0000000000..632390c86a --- /dev/null +++ b/test/test_gauss_hermite_quadrature_eigen.cpp @@ -0,0 +1,53 @@ +// Copyright Nick Thompson, 2026 +// 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) + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include + +using boost::math::quadrature::gauss_hermite; + +// Return concrete Eigen matrices so the test does not rely on the lifetime +// of expression-template temporaries. Supply a shaped zero and a scalar norm. +template +void test_matrix(const Matrix& zero) +{ + const auto norm = [](const Matrix& m) { return m.norm(); }; + const auto f = [&zero](double x) -> Matrix { + Matrix result = zero; + result(0, 0) = {1, x * x}; + result(0, 1) = {x, 2 * x}; + result(1, 0) = {-x * x, x}; + result(1, 1) = {x * x * x, -1}; + return result; + }; + // Against exp(-x^2): 1 -> sqrt(pi), x^2 -> sqrt(pi)/2, odd powers -> 0. + const double root_pi = boost::math::constants::root_pi(); + double L1; + Matrix Q = gauss_hermite::integrate(f, zero, norm, &L1); + CHECK_EQUAL(Q.rows(), Eigen::Index(2)); + CHECK_EQUAL(Q.cols(), Eigen::Index(2)); + CHECK_ULP_CLOSE(root_pi, Q(0, 0).real(), 4); + CHECK_ULP_CLOSE(root_pi / 2, Q(0, 0).imag(), 4); + CHECK_EQUAL(Q(0, 1), std::complex(0, 0)); + CHECK_ULP_CLOSE(-root_pi / 2, Q(1, 0).real(), 4); + CHECK_EQUAL(Q(1, 0).imag(), 0.0); + CHECK_EQUAL(Q(1, 1).real(), 0.0); + CHECK_ULP_CLOSE(-root_pi, Q(1, 1).imag(), 4); + CHECK_LE(norm(Q), L1); +} + +int main() +{ + using fixed = Eigen::Matrix, 2, 2>; + test_matrix(fixed::Zero()); + test_matrix(fixed::Zero()); + test_matrix(Eigen::MatrixXcd::Zero(2, 2)); + return boost::math::test::report_errors(); +} diff --git a/test/test_gauss_kronrod_eigen.cpp b/test/test_gauss_kronrod_eigen.cpp new file mode 100644 index 0000000000..f3eccd80d6 --- /dev/null +++ b/test/test_gauss_kronrod_eigen.cpp @@ -0,0 +1,127 @@ +// Copyright Nick Thompson, 2026 +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +#include +#include +#include +#include +#include +#include "math_unit_test.hpp" + +using boost::math::quadrature::gauss_kronrod; +using matrix = Eigen::MatrixXcd; + +// Both parities of the embedded Gauss rule, with rectangular dynamic matrices. +template +void test_adaptive() +{ + const matrix zero = matrix::Zero(2, 3); + matrix value(2, 3); + value << std::complex(1, 2), 2., -3., 4., 5., std::complex(-2, 1); + const auto norm = [](const matrix& m) { return m.norm(); }; + unsigned calls = 0; + const auto f = [&](double x) -> matrix { + ++calls; + return value / (1 + 10000*(x-0.37)*(x-0.37)); + }; + const double integral = (std::atan(100*(1-0.37)) + std::atan(100*0.37))/100; + const matrix expected = value * integral; + double error = 0, l1 = 0; + matrix coarse = gauss_kronrod::integrate(f, 0., 1., zero, norm, 0, 1e-10, &error, &l1); + CHECK_EQUAL(calls, static_cast(N)); + const double coarse_error = (coarse - expected).norm(); + calls = 0; + matrix result = gauss_kronrod::integrate(f, 0., 1., zero, norm, 15, 1e-10, &error, &l1); + CHECK_TRUE(calls > N); + const unsigned refined_calls = calls; + CHECK_TRUE((result - expected).norm() < coarse_error); + CHECK_ABSOLUTE_ERROR(0, (result - expected).norm(), 1e-11); + CHECK_ULP_CLOSE(value.norm()*integral, l1, 4); + CHECK_GE(error, 0.0); + CHECK_TRUE(error < 1e-10*expected.norm()); + + // Rescaling a norm rescales error/L1, but preserves refinement decisions. + const auto scaled_norm = [](const matrix& m) { return 8*m.norm(); }; + double scaled_error = 0, scaled_l1 = 0; + calls = 0; + matrix scaled = gauss_kronrod::integrate(f, 0., 1., zero, scaled_norm, 15, 1e-10, &scaled_error, &scaled_l1); + CHECK_EQUAL(calls, static_cast(refined_calls)); + CHECK_ABSOLUTE_ERROR(0, (scaled-result).norm(), 1e-14); + CHECK_ULP_CLOSE(8*error, scaled_error, 4); + CHECK_ULP_CLOSE(8*l1, scaled_l1, 4); + result = gauss_kronrod::integrate(f, 1., 0., zero, norm, 15, 1e-10, &error, &l1); + CHECK_ABSOLUTE_ERROR(0, (result + expected).norm(), 1e-11); + CHECK_ULP_CLOSE(value.norm()*integral, l1, 4); +} + +void adaptive_matrix_integral() +{ + test_adaptive<15>(); + test_adaptive<21>(); +} + +void bounds_and_error_policies() +{ + using integrator = gauss_kronrod; + const matrix zero = matrix::Zero(2, 3); + const matrix value = matrix::Ones(2, 3); + const auto norm = [](const matrix& m) { return m.norm(); }; + const double inf = std::numeric_limits::infinity(); + const auto right = [&](double x) -> matrix { return value / ((1+x)*(1+x)); }; + const auto left = [&](double x) -> matrix { return value / ((1-x)*(1-x)); }; + const auto whole = [&](double x) -> matrix { return value / (boost::math::constants::pi()*(1+x*x)); }; + double error = 0, l1 = 0; + matrix result = integrator::integrate(right, 0., inf, zero, norm, 15, 1e-10, &error, &l1); + CHECK_ABSOLUTE_ERROR(0, (result-value).norm(), 1e-12); + CHECK_ULP_CLOSE(value.norm(), l1, 4); + result = integrator::integrate(left, -inf, 0., zero, norm); + CHECK_ABSOLUTE_ERROR(0, (result-value).norm(), 1e-12); + result = integrator::integrate(whole, -inf, inf, zero, norm, 15, 1e-10); + CHECK_ABSOLUTE_ERROR(0, (result-value).norm(), 1e-10); + unsigned calls = 0; + const auto counted = [&](double) -> matrix { ++calls; return value; }; + result = integrator::integrate(counted, 1., 1., zero, norm, 15, 1e-10, &error, &l1); + CHECK_EQUAL(result.rows(), static_cast(2)); + CHECK_EQUAL(result.cols(), static_cast(3)); + CHECK_EQUAL(result.norm(), 0.0); + CHECK_EQUAL(error, 0.0); + CHECK_EQUAL(l1, 0.0); + CHECK_EQUAL(calls, static_cast(0)); + const double nan = std::numeric_limits::quiet_NaN(); + CHECK_THROW(integrator::integrate(counted, nan, 1., zero, norm), std::domain_error); + using ignore = boost::math::policies::policy>; + result = gauss_kronrod::integrate(counted, nan, 1., zero, norm, 15, 1e-10, &error, &l1); + CHECK_EQUAL(result.rows(), static_cast(2)); + CHECK_EQUAL(result.cols(), static_cast(3)); + CHECK_NAN(error); + CHECK_NAN(l1); + for (Eigen::Index i = 0; i < result.size(); ++i) + CHECK_NAN(result.data()[i].real()); + CHECK_EQUAL(calls, static_cast(0)); +} + +void scalar_compatibility_and_interval_scaling() +{ + using integrator = gauss_kronrod; + const auto f = [](double x) { return std::exp(x); }; + const auto norm = [](double x) { return std::abs(x); }; + using function = decltype(f); + double (*original)(function, double, double, unsigned, double, double*, double*) = &integrator::integrate; + CHECK_EQUAL(original(f, 0., 1., 0, 1e-10, nullptr, nullptr), integrator::integrate(f, 0., 1., 0., norm, 0, 1e-10)); + // An affine change of variables must scale the error estimate and L1. + const auto stretched = [&](double x) { return f(x/4); }; + double error1 = 0, error2 = 0, l1 = 0, l2 = 0; + double q1 = integrator::integrate(f, 0., 1., 0., norm, 0, 1e-10, &error1, &l1); + double q2 = integrator::integrate(stretched, 0., 4., 0., norm, 0, 1e-10, &error2, &l2); + CHECK_EQUAL(q2, 4*q1); + CHECK_EQUAL(error2, 4*error1); + CHECK_EQUAL(l2, 4*l1); +} + +int main() +{ + adaptive_matrix_integral(); + bounds_and_error_policies(); + scalar_compatibility_and_interval_scaling(); + return boost::math::test::report_errors(); +} diff --git a/test/test_gauss_kronrod_module.cpp b/test/test_gauss_kronrod_module.cpp new file mode 100644 index 0000000000..e44672f79e --- /dev/null +++ b/test/test_gauss_kronrod_module.cpp @@ -0,0 +1,91 @@ +// Copyright Nick Thompson, 2017 +// Copyright Matt Borland, 2026 +// 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) +// +// Module build check for boost/math/quadrature/gauss_kronrod.hpp. Building this +// against the boost.math module confirms the gauss_kronrod class template and +// its integrate() entry point are usable by a module consumer. Expected values +// are the mathematically-certain ones taken from test_gauss_kronrod_quadrature.cpp +// (a Kronrod rule integrates low-degree polynomials exactly, and 1/(1+t^2) over +// the whole real line is pi). + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" + +// The integrands below use only Real arithmetic, so no standard-library header +// is needed here: std::cout and report_errors() come from math_unit_test.hpp. + +template +void test_polynomials(const char* type_name) +{ + std::cout << "Testing gauss_kronrod polynomial integration for type " << type_name << std::endl; + + using boost::math::quadrature::gauss_kronrod; + + Real error {}; + Real L1 {}; + + // Linear: the integral of 5x + 7 over [0, 1] is 9.5 (exact for a Kronrod rule). + auto f_linear = [](const Real& x) -> Real { return 5 * x + 7; }; + Real Q { gauss_kronrod::integrate(f_linear, Real(0), Real(1), 0, 0, &error, &L1) }; + CHECK_ULP_CLOSE(Real(9.5), Q, 16); + CHECK_ULP_CLOSE(Real(9.5), L1, 16); + + // Reversing the limits negates the result but leaves the L1 norm unchanged. + Q = gauss_kronrod::integrate(f_linear, Real(1), Real(0), 0, 0, &error, &L1); + CHECK_ULP_CLOSE(Real(-9.5), Q, 16); + CHECK_ULP_CLOSE(Real(9.5), L1, 16); + + // A degenerate interval integrates to exactly zero. + Q = gauss_kronrod::integrate(f_linear, Real(0), Real(0), 0, 0, &error, &L1); + CHECK_EQUAL(Q, Real(0)); + + // Quadratic: the integral of 5x^2 + 7x + 12 over [0, 1] is 103/6. + auto f_quadratic = [](const Real& x) -> Real { return 5 * x * x + 7 * x + 12; }; + Q = gauss_kronrod::integrate(f_quadratic, Real(0), Real(1), 0, 0, &error, &L1); + CHECK_ULP_CLOSE(Real(103) / 6, Q, 16); + CHECK_ULP_CLOSE(Real(103) / 6, L1, 16); + + // Exercise the default arguments of the public integrate() entry point; the + // adaptive path also integrates this polynomial to full precision. + Q = gauss_kronrod::integrate(f_quadratic, Real(0), Real(1)); + CHECK_ULP_CLOSE(Real(103) / 6, Q, 16); +} + +template +void test_infinite_limits(const char* type_name) +{ + std::cout << "Testing gauss_kronrod integration over the real line for type " << type_name << std::endl; + + using boost::math::quadrature::gauss_kronrod; + + // The integral of 1/(1+t^2) over the whole real line is pi. + const Real pi { static_cast(3.141592653589793238462643383279502884L) }; + + Real error {}; + Real L1 {}; + auto f = [](const Real& t) -> Real { return 1 / (1 + t * t); }; + Real Q { gauss_kronrod::integrate(f, -boost::math::tools::max_value(), + boost::math::tools::max_value(), 0, 0, &error, &L1) }; + + // A single 15-point panel resolves this to about 6e-3 relative error. + CHECK_ABSOLUTE_ERROR(pi, Q, Real(0.02)); + CHECK_ABSOLUTE_ERROR(pi, L1, Real(0.02)); +} + +int main() +{ + test_polynomials("float"); + test_polynomials("double"); + test_infinite_limits("double"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_gauss_kronrod_quadrature.cpp b/test/test_gauss_kronrod_quadrature.cpp new file mode 100644 index 0000000000..5f9e0a3fd3 --- /dev/null +++ b/test/test_gauss_kronrod_quadrature.cpp @@ -0,0 +1,571 @@ +// Copyright Nick Thompson, 2017 +// 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) + +#include +#include +#include +#include "math_unit_test.hpp" + +#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && !defined(BOOST_NO_SFINAE_EXPR) + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_FLOAT128 +#include +#endif + +#if !defined(TEST1) && !defined(TEST1A) && !defined(TEST2) && !defined(TEST3) +# define TEST1 +# define TEST1A +# define TEST2 +# define TEST3 +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4127) // Conditional expression is constant +#endif + +#if __has_include() +# include +#endif + +using std::expm1; +using std::atan; +using std::tan; +using std::log; +using std::log1p; +using std::asinh; +using std::atanh; +using std::sqrt; +using std::isnormal; +using std::abs; +using std::sinh; +using std::tanh; +using std::cosh; +using std::pow; +using std::exp; +using std::sin; +using std::cos; +using std::string; +using boost::math::quadrature::gauss_kronrod; +using boost::math::constants::pi; +using boost::math::constants::half_pi; +using boost::math::constants::two_div_pi; +using boost::math::constants::two_pi; +using boost::math::constants::half; +using boost::math::constants::third; +using boost::math::constants::half; +using boost::math::constants::third; +using boost::math::constants::catalan; +using boost::math::constants::ln_two; +using boost::math::constants::root_two; +using boost::math::constants::root_two_pi; +using boost::math::constants::root_pi; +using boost::multiprecision::cpp_bin_float_quad; +using boost::multiprecision::cpp_dec_float_50; +using boost::multiprecision::debug_adaptor; +using boost::multiprecision::number; + +// +// Error rates depend only on the number of points in the approximation, not the type being tested, +// define all our expected errors here: +// + +enum +{ + test_ca_error_id, + test_ca_error_id_2, + test_three_quad_error_id, + test_three_quad_error_id_2, + test_integration_over_real_line_error_id, + test_right_limit_infinite_error_id, + test_left_limit_infinite_error_id +}; + +template +double expected_error(unsigned) +{ + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<15>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 1e-7; + case test_ca_error_id_2: + return 2e-5; + case test_three_quad_error_id: + return 1e-8; + case test_three_quad_error_id_2: + return 3.5e-3; + case test_integration_over_real_line_error_id: + return 6e-3; + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 1e-5; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<17>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 1e-7; + case test_ca_error_id_2: + return 2e-5; + case test_three_quad_error_id: + return 1e-8; + case test_three_quad_error_id_2: + return 3.5e-3; + case test_integration_over_real_line_error_id: + return 6e-3; + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 1e-5; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<21>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 1e-12; + case test_ca_error_id_2: + return 3e-6; + case test_three_quad_error_id: + return 2e-13; + case test_three_quad_error_id_2: + return 2e-3; + case test_integration_over_real_line_error_id: + return 6e-3; // doesn't get any better with more points! + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 5e-8; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<31>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 6e-20; + case test_ca_error_id_2: + return 3e-7; + case test_three_quad_error_id: + return 1e-19; + case test_three_quad_error_id_2: + return 6e-4; + case test_integration_over_real_line_error_id: + return 6e-3; // doesn't get any better with more points! + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 5e-11; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<41>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 1e-26; + case test_ca_error_id_2: + return 1e-7; + case test_three_quad_error_id: + return 3e-27; + case test_three_quad_error_id_2: + return 3e-4; + case test_integration_over_real_line_error_id: + return 5e-5; // doesn't get any better with more points! + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 1e-15; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<51>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 5e-33; + case test_ca_error_id_2: + return 1e-8; + case test_three_quad_error_id: + return 1e-32; + case test_three_quad_error_id_2: + return 3e-4; + case test_integration_over_real_line_error_id: + return 1e-14; + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 3e-19; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<61>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 5e-34; + case test_ca_error_id_2: + return 5e-9; + case test_three_quad_error_id: + return 4e-34; + case test_three_quad_error_id_2: + return 1e-4; + case test_integration_over_real_line_error_id: + return 1e-16; + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 3e-23; + } + return 0; // placeholder, all tests will fail +} + + +template +void test_linear() +{ + std::cout << "Testing linear functions are integrated properly by gauss_kronrod on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real error; + auto f = [](const Real& x)->Real + { + return 5*x + 7; + }; + Real L1; + Real Q = gauss_kronrod::integrate(f, (Real) 0, (Real) 1, 0, 0, &error, &L1); + CHECK_ULP_CLOSE(Real(9.5), Q, 4); + CHECK_ULP_CLOSE(Real(9.5), L1, 4); + + Q = gauss_kronrod::integrate(f, (Real) 1, (Real) 0, 0, 0, &error, &L1); + CHECK_ULP_CLOSE(Real(-9.5), Q, 4); + CHECK_ULP_CLOSE(Real(9.5), L1, 4); + + Q = gauss_kronrod::integrate(f, (Real) 0, (Real) 0, 0, 0, &error, &L1); + CHECK_EQUAL(Q, Real(0)); +} + +template +void test_quadratic() +{ + std::cout << "Testing quadratic functions are integrated properly by Gauss Kronrod on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real error; + + auto f = [](const Real& x)->Real { return 5*x*x + 7*x + 12; }; + Real L1; + Real Q = gauss_kronrod::integrate(f, 0, 1, 0, 0, &error, &L1); + CHECK_ULP_CLOSE((Real) 17 + half()*third(), Q, 4); + CHECK_ULP_CLOSE((Real) 17 + half()*third(), L1, 4); +} + +// Examples taken from +//http://crd-legacy.lbl.gov/~dhbailey/dhbpapers/quadrature.pdf +template +void test_ca() +{ + std::cout << "Testing integration of C(a) on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_ca_error_id); + Real L1; + Real error; + + auto f1 = [](const Real& x)->Real { return atan(x)/(x*(x*x + 1)) ; }; + Real Q = gauss_kronrod::integrate(f1, 0, 1, 0, 0, &error, &L1); + Real Q_expected = pi()*ln_two()/8 + catalan()*half(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); + CHECK_ABSOLUTE_ERROR(Q_expected, L1, Real(tol*abs(Q_expected))); + + auto f2 = [](Real x)->Real { Real t0 = x*x + 1; Real t1 = sqrt(t0); return atan(t1)/(t0*t1); }; + Q = gauss_kronrod::integrate(f2, 0 , 1, 0, 0, &error, &L1); + Q_expected = pi()/4 - pi()/root_two() + 3*atan(root_two())/root_two(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); + CHECK_ABSOLUTE_ERROR(Q_expected, L1, Real(tol*abs(Q_expected))); + + tol = expected_error(test_ca_error_id_2); + auto f5 = [](Real t)->Real { return t*t*log(t)/((t*t - 1)*(t*t*t*t + 1)); }; + Q = gauss_kronrod::integrate(f5, 0, 1, 0); + Q_expected = pi()*pi()*(2 - root_two())/32; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); +} + +template +void test_three_quadrature_schemes_examples() +{ + std::cout << "Testing integral in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_three_quad_error_id); + Real Q; + Real Q_expected; + + // Example 1: + auto f1 = [](const Real& t)->Real { return t*boost::math::log1p(t); }; + Q = gauss_kronrod::integrate(f1, 0 , 1, 0); + Q_expected = half()*half(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); + + + // Example 2: + auto f2 = [](const Real& t)->Real { return t*t*atan(t); }; + Q = gauss_kronrod::integrate(f2, 0 , 1, 0); + Q_expected = (pi() -2 + 2*ln_two())/12; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real((2 * tol)*abs(Q_expected))); + + // Example 3: + auto f3 = [](const Real& t)->Real { return exp(t)*cos(t); }; + Q = gauss_kronrod::integrate(f3, 0, half_pi(), 0); + Q_expected = boost::math::expm1(half_pi())*half(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); + + // Example 4: + auto f4 = [](Real x)->Real { Real t0 = sqrt(x*x + 2); return atan(t0)/(t0*(x*x+1)); }; + Q = gauss_kronrod::integrate(f4, 0 , 1, 0); + Q_expected = 5*pi()*pi()/96; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); + + tol = expected_error(test_three_quad_error_id_2); + // Example 5: + auto f5 = [](const Real& t)->Real { return sqrt(t)*log(t); }; + Q = gauss_kronrod::integrate(f5, 0 , 1, 0); + Q_expected = -4/ (Real) 9; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); + + // Example 6: + auto f6 = [](const Real& t)->Real { return sqrt(1 - t*t); }; + Q = gauss_kronrod::integrate(f6, 0 , 1, 0); + Q_expected = pi()/4; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); +} + + +template +void test_integration_over_real_line() +{ + std::cout << "Testing integrals over entire real line in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_integration_over_real_line_error_id); + Real Q; + Real Q_expected; + Real L1; + Real error; + + auto f1 = [](const Real& t)->Real { return 1/(1+t*t);}; + Q = gauss_kronrod::integrate(f1, -boost::math::tools::max_value(), boost::math::tools::max_value(), 0, 0, &error, &L1); + Q_expected = pi(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); + CHECK_ABSOLUTE_ERROR(Q_expected, L1, Real(tol*abs(Q_expected))); +} + +template +void test_right_limit_infinite() +{ + std::cout << "Testing right limit infinite for Gauss Kronrod in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_right_limit_infinite_error_id); + Real Q; + Real Q_expected; + Real L1; + Real error; + + // Example 11: + auto f1 = [](const Real& t)->Real { return 1/(1+t*t);}; + Q = gauss_kronrod::integrate(f1, 0, boost::math::tools::max_value(), 0, 0, &error, &L1); + Q_expected = half_pi(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); + + auto f4 = [](const Real& t)->Real { return 1/(1+t*t); }; + Q = gauss_kronrod::integrate(f4, 1, boost::math::tools::max_value(), 0, 0, &error, &L1); + Q_expected = pi()/4; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); +} + +template +void test_left_limit_infinite() +{ + std::cout << "Testing left limit infinite for Gauss Kronrod in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_left_limit_infinite_error_id); + Real Q; + Real Q_expected; + + // Example 11: + auto f1 = [](const Real& t)->Real { return 1/(1+t*t);}; + Q = gauss_kronrod::integrate(f1, -boost::math::tools::max_value(), Real(0), 0); + Q_expected = half_pi(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, Real(tol*abs(Q_expected))); +} + +template +void test_complex_lambert_w() +{ + std::cout << "Testing that complex-valued integrands are integrated correctly by Gaussian quadrature on type " << boost::typeindex::type_id().pretty_name() << "\n"; + typedef typename Complex::value_type Real; + Real tol = 10e-9; + using boost::math::constants::pi; + Complex z{2, 3}; + auto lw = [&z](Real v)->Complex { + using std::cos; + using std::sin; + using std::exp; + Real sinv = sin(v); + Real cosv = cos(v); + + Real cotv = cosv/sinv; + Real cscv = 1/sinv; + Real t = (1-v*cotv)*(1-v*cotv) + v*v; + Real x = v*cscv*exp(-v*cotv); + Complex den = z + x; + Complex num = t*(z/pi()); + Complex res = num/den; + return res; + }; + + //N[ProductLog[2+3*I], 150] + boost::math::quadrature::gauss_kronrod integrator; + Complex Q = integrator.integrate(lw, (Real) 0, pi()); + CHECK_ABSOLUTE_ERROR(BOOST_MATH_TEST_VALUE(Real, 1.0900765344857908463017778267816696498710210863535777805644), Q.real(), Real(tol*abs(BOOST_MATH_TEST_VALUE(Real, 1.0900765344857908463017778267816696498710210863535777805644)))); + CHECK_ABSOLUTE_ERROR(BOOST_MATH_TEST_VALUE(Real, 0.5301397207748388014268602135741217419287056313827031782979), Q.imag(), Real(tol*abs(BOOST_MATH_TEST_VALUE(Real, 0.5301397207748388014268602135741217419287056313827031782979)))); +} + +void gauss_quadrature_test() +{ +#ifdef TEST1 + std::cout << "Testing 15 point approximation:\n"; + +#ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#else + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#endif + + // test one case where we do not have pre-computed constants: + std::cout << "Testing 17 point approximation:\n"; + +#ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#else + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#endif + + test_complex_lambert_w>(); + test_complex_lambert_w>(); +#endif +#ifdef TEST1A +#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) // If we have too many digits in a long double, we get build errors due to a constexpr issue. + std::cout << "Testing 21 point approximation:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + std::cout << "Testing 31 point approximation:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#endif +#endif +#ifdef TEST2 +#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) // If we have too many digits in a long double, we get build errors due to a constexpr issue. + std::cout << "Testing 41 point approximation:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + std::cout << "Testing 51 point approximation:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#endif +#endif +#if defined(TEST3) && defined(BOOST_MATH_RUN_MP_TESTS) + // Need at least one set of tests with expression templates turned on: + std::cout << "Testing 61 point approximation:\n"; + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#ifdef BOOST_HAS_FLOAT128 +#if LDBL_MANT_DIG < 100 // If we have too many digits in a long double, we get build errors due to a constexpr issue. + test_complex_lambert_w(); +#endif +#endif +#endif +} + +int main() +{ + gauss_quadrature_test(); + return boost::math::test::report_errors(); +} + +#else + +int main() { return 0; } + +#endif diff --git a/test/test_gauss_module.cpp b/test/test_gauss_module.cpp new file mode 100644 index 0000000000..67f76a1d56 --- /dev/null +++ b/test/test_gauss_module.cpp @@ -0,0 +1,76 @@ +// Copyright Nick Thompson, 2017 +// 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) +// +// Module build check for the Gauss-Legendre quadrature component. It consumes +// through import boost.math and exercises the +// public gauss::integrate entry point. Expected values are the +// mathematically-exact integrals and known-good results taken from +// test_gauss_quadrature.cpp (double/float paths only). + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif +#include "math_unit_test.hpp" + +using boost::math::quadrature::gauss; + +template +void test_spots(const char* type_name) +{ + std::cout << "Testing gauss quadrature for type " << type_name << std::endl; + + using std::exp; + using std::sqrt; + using std::cos; + + const Real pi {boost::math::constants::pi()}; + + // A Gauss rule integrates polynomials of degree <= 2N-1 exactly, so a + // 7-point rule reproduces linear and quadratic integrands to rounding. + + // Integral of 5x + 7 over [0, 1] is 9.5; the L1 norm matches on a positive + // integrand. + auto linear = [](const Real& x) { return 5 * x + 7; }; + Real L1 {}; + Real Q {gauss::integrate(linear, static_cast(0), static_cast(1), &L1)}; + CHECK_ULP_CLOSE(static_cast(9.5), Q, 32); + CHECK_ULP_CLOSE(static_cast(9.5), L1, 32); + + // Swapping the limits negates the result. + Q = gauss::integrate(linear, static_cast(1), static_cast(0)); + CHECK_ULP_CLOSE(static_cast(-9.5), Q, 32); + + // Integral of 5x^2 + 7x + 12 over [0, 1] is 103/6. + auto quadratic = [](const Real& x) { return 5 * x * x + 7 * x + 12; }; + Q = gauss::integrate(quadratic, static_cast(0), static_cast(1), &L1); + CHECK_ULP_CLOSE(static_cast(103) / 6, Q, 32); + CHECK_ULP_CLOSE(static_cast(103) / 6, L1, 32); + + // Smooth analytic integrand: exp(t) cos(t) over [0, pi/2] is (e^(pi/2) - 1)/2. + auto smooth = [](const Real& t) { return exp(t) * cos(t); }; + Q = gauss::integrate(smooth, static_cast(0), pi / 2); + const Real smooth_expected {(exp(pi / 2) - 1) / 2}; + CHECK_ABSOLUTE_ERROR(smooth_expected, Q, static_cast(1e-5)); + + // Area of the quarter unit circle: integral of sqrt(1 - t^2) over [0, 1] is pi/4. + auto circle = [](const Real& t) { return sqrt(1 - t * t); }; + Q = gauss::integrate(circle, static_cast(0), static_cast(1)); + CHECK_ABSOLUTE_ERROR(pi / 4, Q, static_cast(3.5e-3)); +} + +int main() +{ + test_spots("double"); + test_spots("float"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_gauss_quadrature.cpp b/test/test_gauss_quadrature.cpp new file mode 100644 index 0000000000..4fe0426be8 --- /dev/null +++ b/test/test_gauss_quadrature.cpp @@ -0,0 +1,561 @@ +// Copyright Nick Thompson, 2017 +// 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) + +#include +//#include +#include +#include + +#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && !defined(BOOST_NO_SFINAE_EXPR) + +#include +#include +#include +#include +#include +#include +#include +#include "math_unit_test.hpp" + +#ifdef BOOST_HAS_FLOAT128 +#include +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4127) // Conditional expression is constant +#endif + +#if __has_include() +# include +#endif + +#if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) +# define TEST1 +# define TEST2 +# define TEST3 +#endif + +using std::expm1; +using std::atan; +using std::tan; +using std::log; +using std::log1p; +using std::asinh; +using std::atanh; +using std::sqrt; +using std::isnormal; +using std::abs; +using std::sinh; +using std::tanh; +using std::cosh; +using std::pow; +using std::exp; +using std::sin; +using std::cos; +using std::string; +using boost::math::quadrature::gauss; +using boost::math::constants::pi; +using boost::math::constants::half_pi; +using boost::math::constants::two_div_pi; +using boost::math::constants::two_pi; +using boost::math::constants::half; +using boost::math::constants::third; +using boost::math::constants::half; +using boost::math::constants::third; +using boost::math::constants::catalan; +using boost::math::constants::ln_two; +using boost::math::constants::root_two; +using boost::math::constants::root_two_pi; +using boost::math::constants::root_pi; +using boost::multiprecision::cpp_bin_float_quad; + +// +// Error rates depend only on the number of points in the approximation, not the type being tested, +// define all our expected errors here: +// + +enum +{ + test_ca_error_id, + test_ca_error_id_2, + test_three_quad_error_id, + test_three_quad_error_id_2, + test_integration_over_real_line_error_id, + test_right_limit_infinite_error_id, + test_left_limit_infinite_error_id +}; + +template +double expected_error(unsigned) +{ + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<7>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 1e-7; + case test_ca_error_id_2: + return 2e-5; + case test_three_quad_error_id: + return 1e-8; + case test_three_quad_error_id_2: + return 3.5e-3; + case test_integration_over_real_line_error_id: + return 6e-3; + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 1e-5; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<9>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 1e-7; + case test_ca_error_id_2: + return 2e-5; + case test_three_quad_error_id: + return 1e-8; + case test_three_quad_error_id_2: + return 3.5e-3; + case test_integration_over_real_line_error_id: + return 6e-3; + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 1e-5; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<10>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 1e-12; + case test_ca_error_id_2: + return 3e-6; + case test_three_quad_error_id: + return 2e-13; + case test_three_quad_error_id_2: + return 2e-3; + case test_integration_over_real_line_error_id: + return 6e-3; // doesn't get any better with more points! + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 5e-8; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<15>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 6e-20; + case test_ca_error_id_2: + return 3e-7; + case test_three_quad_error_id: + return 1e-19; + case test_three_quad_error_id_2: + return 6e-4; + case test_integration_over_real_line_error_id: + return 6e-3; // doesn't get any better with more points! + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 5e-11; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<20>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 1e-26; + case test_ca_error_id_2: + return 1e-7; + case test_three_quad_error_id: + return 3e-27; + case test_three_quad_error_id_2: + return 3e-4; + case test_integration_over_real_line_error_id: + return 5e-5; // doesn't get any better with more points! + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 1e-15; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<25>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 5e-33; + case test_ca_error_id_2: + return 1e-8; + case test_three_quad_error_id: + return 1e-32; + case test_three_quad_error_id_2: + return 3e-4; + case test_integration_over_real_line_error_id: + return 1e-14; + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 3e-19; + } + return 0; // placeholder, all tests will fail +} + +template <> +double expected_error<30>(unsigned id) +{ + switch (id) + { + case test_ca_error_id: + return 2e-34; + case test_ca_error_id_2: + return 5e-9; + case test_three_quad_error_id: + return 4e-34; + case test_three_quad_error_id_2: + return 1e-4; + case test_integration_over_real_line_error_id: + return 1e-16; + case test_right_limit_infinite_error_id: + case test_left_limit_infinite_error_id: + return 3e-23; + } + return 0; // placeholder, all tests will fail +} + + +template +void test_linear() +{ + std::cout << "Testing linear functions are integrated properly by gauss on type " << boost::typeindex::type_id().pretty_name() << "\n"; + auto f = [](const Real& x) + { + return 5*x + 7; + }; + Real L1; + Real Q = gauss::integrate(f, (Real) 0, (Real) 1, &L1); + CHECK_ULP_CLOSE(Real(9.5), Q, 4); + CHECK_ULP_CLOSE(Real(9.5), L1, 4); + Q = gauss::integrate(f, (Real) 0, (Real) 0, &L1); + CHECK_EQUAL(Q, Real(0)); + Q = gauss::integrate(f, (Real) 1, (Real) 0, &L1); + CHECK_ULP_CLOSE(Real(-9.5), Q, 4); +} + +template +void test_quadratic() +{ + std::cout << "Testing quadratic functions are integrated properly by Gaussian quadrature on type " << boost::typeindex::type_id().pretty_name() << "\n"; + + auto f = [](const Real& x) { return 5*x*x + 7*x + 12; }; + Real L1; + Real Q = gauss::integrate(f, 0, 1, &L1); + CHECK_ULP_CLOSE((Real) 17 + half()*third(), Q, 4); + CHECK_ULP_CLOSE((Real) 17 + half()*third(), L1, 4); +} + +// Examples taken from +//http://crd-legacy.lbl.gov/~dhbailey/dhbpapers/quadrature.pdf +template +void test_ca() +{ + std::cout << "Testing integration of C(a) on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_ca_error_id); + Real L1; + + auto f1 = [](const Real& x) { + if (x == 0) { + return static_cast(1); + } + return atan(x)/(x*(x*x + 1)) ; + }; + Real Q = gauss::integrate(f1, 0, 1, &L1); + Real Q_expected = pi()*ln_two()/8 + catalan()*half(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); + CHECK_ABSOLUTE_ERROR(Q_expected, L1, tol*abs(Q_expected)); + + auto f2 = [](Real x)->Real { Real t0 = x*x + 1; Real t1 = sqrt(t0); return atan(t1)/(t0*t1); }; + Q = gauss::integrate(f2, 0 , 1, &L1); + Q_expected = pi()/4 - pi()/root_two() + 3*atan(root_two())/root_two(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); + CHECK_ABSOLUTE_ERROR(Q_expected, L1, tol*abs(Q_expected)); + + tol = expected_error(test_ca_error_id_2); + auto f5 = [](Real t)->Real { return t*t*log(t)/((t*t - 1)*(t*t*t*t + 1)); }; + Q = gauss::integrate(f5, 0 , 1); + Q_expected = pi()*pi()*(2 - root_two())/32; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); +} + +template +void test_three_quadrature_schemes_examples() +{ + std::cout << "Testing integral in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_three_quad_error_id); + Real Q; + Real Q_expected; + + // Example 1: + auto f1 = [](const Real& t) { return t*boost::math::log1p(t); }; + Q = gauss::integrate(f1, 0 , 1); + Q_expected = half()*half(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); + + + // Example 2: + auto f2 = [](const Real& t) { return t*t*atan(t); }; + Q = gauss::integrate(f2, 0 , 1); + Q_expected = (pi() -2 + 2*ln_two())/12; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, (2 * tol)*abs(Q_expected)); + + // Example 3: + auto f3 = [](const Real& t) { return exp(t)*cos(t); }; + Q = gauss::integrate(f3, 0, half_pi()); + Q_expected = boost::math::expm1(half_pi())*half(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); + + // Example 4: + auto f4 = [](Real x)->Real { Real t0 = sqrt(x*x + 2); return atan(t0)/(t0*(x*x+1)); }; + Q = gauss::integrate(f4, 0 , 1); + Q_expected = 5*pi()*pi()/96; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); + + tol = expected_error(test_three_quad_error_id_2); + // Example 5: + auto f5 = [](const Real& t) { return sqrt(t)*log(t); }; + Q = gauss::integrate(f5, 0 , 1); + Q_expected = -4/ (Real) 9; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); + + // Example 6: + auto f6 = [](const Real& t) { return sqrt(1 - t*t); }; + Q = gauss::integrate(f6, 0 , 1); + Q_expected = pi()/4; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); +} + + +template +void test_integration_over_real_line() +{ + std::cout << "Testing integrals over entire real line in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_integration_over_real_line_error_id); + Real Q; + Real Q_expected; + Real L1; + + auto f1 = [](const Real& t) { return 1/(1+t*t);}; + Q = gauss::integrate(f1, -boost::math::tools::max_value(), boost::math::tools::max_value(), &L1); + Q_expected = pi(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); + CHECK_ABSOLUTE_ERROR(Q_expected, L1, tol*abs(Q_expected)); +} + +template +void test_right_limit_infinite() +{ + std::cout << "Testing right limit infinite for Gaussian quadrature in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_right_limit_infinite_error_id); + Real Q; + Real Q_expected; + Real L1; + + // Example 11: + auto f1 = [](const Real& t) { return 1/(1+t*t);}; + Q = gauss::integrate(f1, 0, boost::math::tools::max_value(), &L1); + Q_expected = half_pi(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); + + auto f4 = [](const Real& t) { return 1/(1+t*t); }; + Q = gauss::integrate(f4, 1, boost::math::tools::max_value(), &L1); + Q_expected = pi()/4; + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); +} + +template +void test_left_limit_infinite() +{ + std::cout << "Testing left limit infinite for Gaussian quadrature in 'A Comparison of Three High Precision Quadrature Schemes' on type " << boost::typeindex::type_id().pretty_name() << "\n"; + Real tol = expected_error(test_left_limit_infinite_error_id); + Real Q; + Real Q_expected; + + // Example 11: + auto f1 = [](const Real& t) { return 1/(1+t*t);}; + Q = gauss::integrate(f1, -boost::math::tools::max_value(), Real(0)); + Q_expected = half_pi(); + CHECK_ABSOLUTE_ERROR(Q_expected, Q, tol*abs(Q_expected)); +} + +template +void test_complex_lambert_w() +{ + #ifndef BOOST_MATH_STANDALONE + std::cout << "Testing that complex-valued integrands are integrated correctly by Gaussian quadrature on type " << boost::typeindex::type_id().pretty_name() << "\n"; + typedef typename Complex::value_type Real; + Real tol = 10e-9; + using boost::math::constants::pi; + Complex z{2, 3}; + auto lw = [&z](Real v)->Complex { + using std::cos; + using std::sin; + using std::exp; + Real sinv = sin(v); + Real cosv = cos(v); + + Real cotv = cosv/sinv; + Real cscv = 1/sinv; + Real t = (1-v*cotv)*(1-v*cotv) + v*v; + Real x = v*cscv*exp(-v*cotv); + Complex den = z + x; + Complex num = t*(z/pi()); + Complex res = num/den; + return res; + }; + + //N[ProductLog[2+3*I], 150] + Complex Q = gauss::integrate(lw, (Real) 0, pi()); + Real expected_real = BOOST_MATH_TEST_VALUE(Real, 1.0900765344857908463017778267816696498710210863535777805644); + Real expected_imag = BOOST_MATH_TEST_VALUE(Real, 0.5301397207748388014268602135741217419287056313827031782979); + CHECK_ABSOLUTE_ERROR(expected_real, Q.real(), tol*abs(expected_real)); + CHECK_ABSOLUTE_ERROR(expected_imag, Q.imag(), tol*abs(expected_imag)); + #endif +} + +void gauss_quadrature_test() +{ + +#ifdef TEST1 + +#ifdef __STDCPP_FLOAT64_T__ + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#else + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#endif + +#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); +#endif +#endif +#ifdef TEST2 +#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + + test_linear(); + test_quadratic(); + test_ca(); + test_three_quadrature_schemes_examples(); + test_integration_over_real_line(); + test_right_limit_infinite(); + test_left_limit_infinite(); + +#endif +#endif +#ifdef TEST3 +#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) + test_left_limit_infinite(); +#endif + test_complex_lambert_w>(); + test_complex_lambert_w>(); +#ifdef BOOST_HAS_FLOAT128 + test_left_limit_infinite(); + test_complex_lambert_w(); +#endif +#if LDBL_MANT_DIG < 100 && defined(BOOST_MATH_RUN_MP_TESTS) + test_complex_lambert_w(); +#endif +#endif +} + +int main() +{ + gauss_quadrature_test(); + return boost::math::test::report_errors(); +} + +#else + +int main() { return 0; } + +#endif diff --git a/test/test_gauss_quadrature_eigen.cpp b/test/test_gauss_quadrature_eigen.cpp new file mode 100644 index 0000000000..21a5b60526 --- /dev/null +++ b/test/test_gauss_quadrature_eigen.cpp @@ -0,0 +1,171 @@ +// Copyright Nick Thompson, 2026 +// 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) + +#include +#include +#include +#include +#include +#include "math_unit_test.hpp" + +using boost::math::quadrature::gauss; +using matrix = Eigen::Matrix, 2, 2>; + +// Regression for https://github.com/boostorg/math/issues/337. +// Return concrete Eigen matrices so the test does not rely on the lifetime +// of expression-template temporaries. Supply a shaped zero and a scalar norm. +template +void test_matrix() +{ + const matrix zero = matrix::Zero(); + const auto norm = [](const matrix& m) { return m.norm(); }; + const auto f = [](double x) -> matrix { + matrix result; + result(0, 0) = {1, x * x}; + result(0, 1) = {x, 2 * x}; + result(1, 0) = {-x * x, x}; + result(1, 1) = {x * x * x, -1}; + return result; + }; + const auto primitive = [](double x) -> matrix { + matrix result; + result(0, 0) = {x, x * x * x / 3}; + result(0, 1) = {x * x / 2, x * x}; + result(1, 0) = {-x * x * x / 3, x * x / 2}; + result(1, 1) = {x * x * x * x / 4, -x}; + return result; + }; + const auto check = [](const matrix& actual, const matrix& expected) { + for (unsigned i = 0; i < 2; ++i) + for (unsigned j = 0; j < 2; ++j) + CHECK_ABSOLUTE_ERROR(0, std::abs(actual(i, j) - expected(i, j)), 100 * std::numeric_limits::epsilon()); + }; + + check(gauss::integrate(f, zero, norm), primitive(1) + -primitive(-1)); + check(gauss::integrate(f, 0., 1., zero, norm), primitive(1)); + check(gauss::integrate(f, 1., 0., zero, norm), -primitive(1)); + check(gauss::integrate(f, 1., 1., zero, norm), matrix::Zero()); + + // A constant matrix has an exactly known integral and L1 norm. + const matrix value = f(1); + double l1 = 0; + check(gauss::integrate([&](double) { return value; }, 0., 3., zero, norm, &l1), + value * 3); + CHECK_ULP_CLOSE(3 * value.norm(), l1, 4); +} + +void matrix_valued_quadrature() +{ + test_matrix<7>(); + test_matrix<10>(); +} + +void dynamic_matrices_and_infinite_bounds() +{ + using dynamic_matrix = Eigen::MatrixXcd; + const dynamic_matrix zero = dynamic_matrix::Zero(2, 3); + dynamic_matrix value(2, 3); + value << 1., 2., 3., 4., 5., 6.; + const auto norm = [](const dynamic_matrix& m) { return m.norm(); }; + const auto check = [&](const dynamic_matrix& actual) { + CHECK_EQUAL(actual.rows(), static_cast(2)); + CHECK_EQUAL(actual.cols(), static_cast(3)); + CHECK_ABSOLUTE_ERROR(0, (actual - value).norm(), 1e-10); + }; + const double inf = std::numeric_limits::infinity(); + using integrator = gauss; + // These functions become constants under the half-line substitution. + const auto right = [&](double x) -> dynamic_matrix { return value / ((1+x)*(1+x)); }; + const auto left = [&](double x) -> dynamic_matrix { return value / ((1-x)*(1-x)); }; + double l1 = 0; + check(integrator::integrate(right, 0., inf, zero, norm, &l1)); + CHECK_ULP_CLOSE(value.norm(), l1, 4); + check(integrator::integrate(left, -inf, 0., zero, norm)); + const auto whole = [&](double x) -> dynamic_matrix { + return value / (boost::math::constants::pi() * (1+x*x)); + }; + check(integrator::integrate(whole, -inf, inf, zero, norm)); + + unsigned calls = 0; + const auto counted = [&](double) -> dynamic_matrix { ++calls; return value; }; + l1 = -1; + dynamic_matrix empty = integrator::integrate(counted, 2., 2., zero, norm, &l1); + CHECK_EQUAL(empty.rows(), static_cast(2)); + CHECK_EQUAL(empty.cols(), static_cast(3)); + CHECK_EQUAL(empty.norm(), 0.0); + CHECK_EQUAL(l1, 0.0); + CHECK_EQUAL(calls, static_cast(0)); + + const double nan = std::numeric_limits::quiet_NaN(); + CHECK_THROW(integrator::integrate(counted, nan, 1., zero, norm), std::domain_error); + using ignore = boost::math::policies::policy< + boost::math::policies::domain_error>; + dynamic_matrix invalid = gauss::integrate(counted, nan, 1., zero, norm, &l1); + CHECK_EQUAL(invalid.rows(), static_cast(2)); + CHECK_EQUAL(invalid.cols(), static_cast(3)); + CHECK_NAN(l1); + for (Eigen::Index i = 0; i < invalid.size(); ++i) + CHECK_NAN(invalid.data()[i].real()); + CHECK_EQUAL(calls, static_cast(0)); +} + +void scalar_overload_compatibility() +{ + const auto f = [](double x) { return x*x; }; + const auto norm = [](double x) { return std::abs(x); }; + using integrator = gauss; + double old_l1 = 0, new_l1 = 0; + CHECK_EQUAL(integrator::integrate(f, &old_l1), integrator::integrate(f, 0., norm, &new_l1)); + CHECK_EQUAL(old_l1, new_l1); + CHECK_EQUAL(integrator::integrate(f, 0., 1., &old_l1), integrator::integrate(f, 0., 1., 0., norm, &new_l1)); + CHECK_EQUAL(old_l1, new_l1); + using function = decltype(f); + double (*original)(function, double*) = &integrator::integrate; + CHECK_EQUAL(original(f, nullptr), integrator::integrate(f)); +} + +void controllability_gramian() +{ + // The dimensions and matrix-exponential expression from issue #337. + // A*A = 0, so exp(A*t) = I + A*t and the integral is polynomial. + using gramian_matrix = Eigen::Matrix, 12, 12>; + Eigen::Matrix a = Eigen::Matrix::Zero(); + Eigen::Matrix b = Eigen::Matrix::Zero(); + a(0, 1) = 1; + b(1, 0) = 1; + const auto f = [&](double t) -> gramian_matrix { + return (a*t).exp() * b * b.transpose() * (a.transpose()*t).exp(); + }; + const gramian_matrix zero = gramian_matrix::Zero(); + const auto norm = [](const gramian_matrix& m) { return m.norm(); }; + gramian_matrix expected = zero; + expected(0, 0) = 1./3; + expected(0, 1) = expected(1, 0) = 0.5; + expected(1, 1) = 1; + gramian_matrix result = gauss::integrate(f, 0., 1., zero, norm); + CHECK_ABSOLUTE_ERROR(0, (result - expected).norm(), 1e-14); + + // Verify that L1 follows the supplied norm, including on the canonical + // interval and when the integration bounds are reversed. + const auto scaled_norm = [](const gramian_matrix& m) { return 2*m.norm(); }; + const auto constant = [&](double) -> gramian_matrix { return expected; }; + double l1 = 0; + result = gauss::integrate(constant, zero, scaled_norm, &l1); + CHECK_ABSOLUTE_ERROR(0, (result - 2*expected).norm(), 1e-14); + CHECK_ULP_CLOSE(4*expected.norm(), l1, 4); + result = gauss::integrate(constant, 3., 0., zero, scaled_norm, &l1); + CHECK_ABSOLUTE_ERROR(0, (result + 3*expected).norm(), 1e-14); + CHECK_ULP_CLOSE(6*expected.norm(), l1, 4); +} + +int main() +{ + matrix_valued_quadrature(); + dynamic_matrices_and_infinite_bounds(); + scalar_overload_compatibility(); + controllability_gramian(); + return boost::math::test::report_errors(); +} diff --git a/test/gegenbauer_test.cpp b/test/test_gegenbauer.cpp similarity index 100% rename from test/gegenbauer_test.cpp rename to test/test_gegenbauer.cpp diff --git a/test/test_generalized_extreme_value.cpp b/test/test_generalized_extreme_value.cpp new file mode 100644 index 0000000000..3101ed0fb3 --- /dev/null +++ b/test/test_generalized_extreme_value.cpp @@ -0,0 +1,443 @@ +// Copyright Nick Thompson 2026. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) +// +// References: mpmath at 150 digits, printed to 40, at the double values of the parameters and arguments +// (the generator is in the PR that added this file). Where the tests need more than a few ulps, it is the +// condition number of the function, not the method: +// * the cdf deep in its tails, exp(-t) for large t, magnifies the rounding of (x - mu)/sigma, so the +// tolerances scale with each function's condition number; +// * mu + sigma q cancels where the quantile is near 0 (-0.016 at xi = 1.5, p = 0.25), so the quantile's tolerance +// scales with (|mu| + |x - mu|)/|x|; +// * skewness and kurtosis excess pass through 0 (at xi = -0.28 and -0.15), so they are checked to an +// absolute error, and for |xi| >= 1/4 the kurtosis is a fourth difference of lgamma(1 - k xi). + +#include "math_unit_test.hpp" +#include +#include +#include "test_out_of_range.hpp" +#include +#include +#if __has_include() +#include +#define BOOST_MATH_TEST_GEV_MULTIPRECISION +#endif + +using boost::math::generalized_extreme_value_distribution; + +// mu, sigma, xi, x, pdf, logpdf, cdf, ccdf, logcdf, logccdf +const long double cdf_data[][10] = { + { 0.5, 2, 0, -3, 0.009115765822384945444346020789780975286465L, -4.697749856565675746283731826300868938998L, 0.003168165149053243848719669162880521440672L, 0.9968318348509467561512803308371194785593L, -5.754602676005730436866499704842692370923L, -0.003173194409419889751857546828551054431638L }, + { 0.5, 2, 0, -0.5, 0.1585209605389710880473291448008405244162L, -1.841868451260073456265882909272340139729L, 0.1922956455479649280742866860378975816894L, 0.8077043544520350719257133139621024183106L, -1.648721270700128146848650787814163571654L, -0.2135591853734341440449422035125653857933L }, + { 0.5, 2, 0, 0.25, 0.1824469864020708676088842652042828343706L, -1.701295633626771626246239349269970440641L, 0.3220178007714426731329932585931980462668L, 0.6779821992285573268670067414068019537332L, -1.133148453066826316829007227811793872566L, -0.3886342462115421229163077265709873030708L }, + { 0.5, 2, 0, 1, 0.1787176730860912736876052717082097864081L, -1.721947963631350177662402388436497215372L, 0.4589560693076638184581480769101370726848L, 0.5410439306923361815418519230898629273152L, -0.7788007830714048682451702669783206472968L, -0.614254800673943822670724491688423891635L }, + { 0.5, 2, 0, 4, 0.07302735923472654790400422830811197399479L, -2.61692112401039043609794938012454758409L, 0.8404868737475783667364934360395455344152L, 0.1595131262524216332635065639604544655848L, -0.1737739434504451266807172586663710160147L, -1.835629063889961509423681941292199838984L }, + { 0.5, 2, 0, 30, 1.963931001335069415616541086995321911745e-7L, -15.44314757334629985752113467810391568766L, 0.9999996072137225924461571189333918174662L, 3.927862774075538428810666081825337687368e-7L, -3.927863545481039025566457391195863032792e-7L, -14.75000019639317084567193797879849698995L }, + { 0.5, 2, 1e-20, -3, 0.009115765822384945443841874696649368440024L, -4.697749856565675746339036679777206683281L, 0.003168165149053243848440498834569982501757L, 0.9968318348509467561515595011654300174982L, -5.754602676005730436954617058319030113406L, -0.003173194409419889751577489231521880065215L }, + { 0.5, 2, 1e-20, -0.5, 0.1585209605389710880479932047048435720762L, -1.841868451260073456261693810860715300143L, 0.192295645547964928073890383636550153991L, 0.807704354452035071926109616363449846009L, -1.648721270700128146850711689402538731724L, -0.2135591853734341440444515507147154989699L }, + { 0.5, 2, 1e-20, 0.25, 0.1824469864020708676091104260830661932527L, -1.701295633626771626244999751492866286515L, 0.3220178007714426731329647512515727226953L, 0.6779821992285573268670352487484272773047L, -1.133148453066826316829095755034689718367L, -0.3886342462115421229162656792404559695394L }, + { 0.5, 2, 1e-20, 1, 0.1787176730860912736871708313409126657638L, -1.72194796363135017766483326368120702926L, 0.4589560693076638184580363783644582656449L, 0.5410439306923361815419636216355417343551L, -0.7788007830714048682454136422230304613048L, -0.6142548006739438226705180416400223243136L }, + { 0.5, 2, 1e-20, 4, 0.07302735923472654790365016147306552690034L, -2.616921124010390436102797793633632524827L, 0.8404868737475783667342569731629820340084L, 0.1595131262524216332657430268370179659916L, -0.1737739434504451266833781721754559568711L, -1.83562906388996150940966138430666117859L }, + { 0.5, 2, 1e-20, 30, 1.963931001335069417463249117543877889429e-7L, -15.44314757334629985658082260538182204619L, 0.9999996072137225924461566916556533395052L, 3.927862774075538433083443466604947852275e-7L, -3.927863545481039029839236454264455565347e-7L, -14.75000019639317084458412569243743621741L }, + { 0.5, 2, -1e-9, -3, 0.009115765872799554771946080968262620026985L, -4.697749851035190412359091169626025457627L, 0.003168165176970276748828468916096131826271L, 0.9968318348230297232511715310839038681737L, -5.754602667193995106259567173008525775103L, -0.003173194437425649524441523294602566123376L }, + { 0.5, 2, -1e-9, -0.5, 0.1585209604725650976744218719492888455378L, -1.841868451678983297343277604902220403243L, 0.1922956455875951681974261917104534818515L, 0.8077043544124048318025738082895465181485L, -1.648721270494037988092712111127424194838L, -0.2135591854224994238167688548412075966868L }, + { 0.5, 2, -1e-9, 0.25, 0.182446986379454779733353359398335601163L, -1.701295633750731403948963542528035519475L, 0.3220178007742934072952895375955548586645L, 0.6779821992257065927047104624044451413355L, -1.133148453057973594540194954464039676811L, -0.3886342462157468559691017126026166415997L }, + { 0.5, 2, -1e-9, 1, 0.178717673129535310427908761610173438766L, -1.721947963388262653161703324233783748909L, 0.4589560693188336730278518189664221151632L, 0.5410439306811663269721481810335778848368L, -0.7788007830470673437705128830706037529678L, -0.6142548006945888275144638144559958666686L }, + { 0.5, 2, -1e-9, 4, 0.07302735927013323140638808443280455603325L, -2.616921123525549085337949864699606090224L, 0.8404868739712246545122901543310216909817L, 0.1595131260287753454877098456689783090183L, -0.17377394318435377566550942297392605831L, -1.835629065292017209709248439735100776865L }, + { 0.5, 2, -1e-9, 30, 1.963930816664273156023001573027157430863e-7L, -15.4431476673775080906334661135206673916L, 0.9999996072137653202181010821144661558863L, 3.927862346797818989178855338441136576943e-7L, -3.927863118203151757053016200034791262688e-7L, -14.7500003051744005514612834025113567628L }, + { 0.5, 2, 1e-9, -3, 0.009115765771970336145624700217464420508732L, -4.697749862096161107626641378518741212887L, 0.003168165121136211086720674613104760872243L, 0.9968318348788637889132793253868952391278L, -5.75460268481746580152711779888655526371L, -0.003173194381414130118606643465339249650594L }, + { 0.5, 2, 1e-9, -0.5, 0.1585209606053770784750314195231078862963L, -1.84186845084116361501830958938882670287L, 0.1922956455083346879279406427428083575554L, 0.8077043544916653120720593572571916424446L, -1.648721270906218305767744173580603150022L, -0.213559185324368864246791478672148497165L }, + { 0.5, 2, 1e-9, 0.25, 0.1824469864246869554900251411162551697432L, -1.701295633502811848528132688286390169526L, 0.3220178007685919389702248226276367206498L, 0.6779821992314080610297751773723632793502L, -1.133148453075679039119364116767366211481L, -0.388634246207337389862835005334260806701L }, + { 0.5, 2, 1e-9, 1, 0.1787176730426472369684846225640671376264L, -1.721947963874437702103666158788601709202L, 0.4589560692964939638920904083634490935538L, 0.5410439307035060361079095916365509064462L, -0.7788007830957423927124756903687619088155L, -0.6142548006532988178341503453350002029345L }, + { 0.5, 2, 1e-9, 4, 0.07302735919931986439709865733298120907751L, -2.616921124495231787154938124508301140614L, 0.8404868735239320791995900204472480338069L, 0.1595131264760679208004099795527519661931L, -0.1737739437165364774824976566509613042549L, -1.835629062487905812601516027788899559118L }, + { 0.5, 2, 1e-9, 30, 1.963931186005879265734471889093366625678e-7L, -15.44314747931509354621469424527979978518L, 0.999999607213679864670405489814773606136L, 3.927863201353295945101852263938640014138e-7L, -3.927863972758964370772486657174537095069e-7L, -14.75000008761194327924907972277214799304L }, + { 0.5, 2, 0.05, -3, 0.006654207329959662526934006477968915074622L, -5.012505943175803363223445387272214509505L, 0.001945434707953234552092815540172502183168L, 0.9980545652920467654479071844598274978168L, -6.242269826651158210658094099245287635833L, -0.00194732952394737760557329759096809338509L }, + { 0.5, 2, 0.05, -0.5, 0.1619111752996693505827179422710667011729L, -1.820707394740831011982784453049470024416L, 0.1902846477536663758749416549401691954994L, 0.8097153522463336241250583450598308045006L, -1.659234181850973087825942269518598513973L, -0.2110725100569042567305917116110946846935L }, + { 0.5, 2, 0.05, 0.25, 0.1835848470423718787177487583081779818812L, -1.695078336650691841412114949055366012756L, 0.3218746711043940370184449592529980726989L, 0.6781253288956059629815550407470019273011L, -1.1335930293762498514571924436629684101L, -0.3884231572460850972272443880540950963379L }, + { 0.5, 2, 0.05, 1, 0.1765716300692055618376724509591067746702L, -1.734028648851825495277856801880003561455L, 0.4584020927196983646983517538704278540592L, 0.5415979072803016353016482461295721459408L, -0.7800085483221799657234567565864361429962L, -0.6132314213496210496449898360512151050468L }, + { 0.5, 2, 0.05, 4, 0.07125611704849486727158939803010069722299L, -2.641474610206353167989633676116143473334L, 0.8295961473591191058350015746177976544793L, 0.1704038526408808941649984253822023455207L, -0.1868162660516636254194341504841769437842L, -1.769584055447669281973206403773798709673L }, + { 0.5, 2, 0.05, 30, 4.576590121622874632575130895371787826148e-6L, -12.29455635205656301223688087145681232746L, 0.9999840962228616264473566472665571532576L, 1.590377713837355264335273344284674240573e-5L, -1.590390360477805028881394339502371816681e-5L, -11.04895392107746622240188923278841501568L }, + { 0.5, 2, -0.05, -3, 0.0116522972401220260452493356780315964923L, -4.452251930416117493176344205665701826687L, 0.004734624088379052327935505548823451317078L, 0.9952653759116209476720644944511765486829L, -5.352852945489512195361591654164601106664L, -0.004745867925273727842992985544106665896138L }, + { 0.5, 2, -0.05, -0.5, 0.1552677890261829157254418743604834157109L, -1.86260398163328395446559383287104030657L, 0.1942486110094597440911993454966736347911L, 0.8057513889905402559088006545033263652089L, -1.638616440290397162630580347606087362705L, -0.2159800344400579524535708917838999447462L }, + { 0.5, 2, -0.05, 0.25, 0.181323151227319643223971569411501005637L, -1.707474473690776936044334692444143202217L, 0.3221597500187632053101022398452834952805L, 0.6778402499812367946898977601547165047195L, -1.132707738392917036539335266553895759585L, -0.3888436383010770192104506812337850194648L }, + { 0.5, 2, -0.05, 1, 0.1809166811361984369704735047807703523638L, -1.709718678912861502344432957419012997998L, 0.4595191619005060828100913912866177786501L, 0.5404808380994939171899086087133822213499L, -0.7775746364225739497035679822722962193043L, -0.6152960947061666546825125553326396886438L }, + { 0.5, 2, -0.05, 4, 0.07478619311646186860222396651672830589823L, -2.593121995043949955032873487064120053411L, 0.8519749640523185531180141938235932211261L, 0.1480250359476814468819858061764067788739L, -0.1601981374996854657648926641497742859958L, -1.910373857715608960778425274430996387585L }, + { 0.5, 2, -0.05, 30, 4.596495628665318784510202472933638098048e-12L, -26.10572692262107364754515967239754052211L, 0.9999999999975868397949477963434007444284L, 2.413160205052203656599255571631276795675e-12L, -2.413160205055115327686884052649638212485e-12L, -26.7500839390103805297543906676252635749L }, + { 0.5, 2, 0.125, -3, 0.003423246589701594419900482066542693821116L, -5.677165882969006728455454653911608516139L, 0.0007422982779016125799840396566571464186797L, 0.9992577017220983874200159603433428535813L, -7.2057594037927936L, -0.0007425739176813640686958440054640087028603L }, + { 0.5, 2, 0.125, -0.5, 0.1672727062307847691187462917250953461827L, -1.788129826971705694097237563124980650824L, 0.1871529023412981934236701852128733036644L, 0.8128470976587018065763298147871266963356L, -1.675829336649900929736320682822740435909L, -0.2072122588825521358688092544051501334343L }, + { 0.5, 2, 0.125, 0.25, 0.1853185158707079340417764264213095687752L, -1.685679226933769823085801112302159614852L, 0.3216577267813451408584717373817422758756L, 0.6783422732186548591415282626182577241244L, -1.134267259087077031136514593991437472465L, -0.3881032906682759843935688114900746473114L }, + { 0.5, 2, 0.125, 1, 0.1734477527072901158512380207091809130925L, -1.751878862079889173325343037941231293253L, 0.4575876840435851385758078160443173339454L, 0.5424123159564148614241921839556826660546L, -0.7817867535191606685688570481121052483518L, -0.6117288362044184134725997865669490731972L }, + { 0.5, 2, 0.125, 4, 0.06863052259648018182869424109167513063265L, -2.679017907396134254294770921115472364825L, 0.8142897347074998526170434672704840171996L, 0.1857102652925001473829565327295159828004L, -0.2054390368669100216143901588846425750722L, -1.683567533247151993873221105493973708099L }, + { 0.5, 2, 0.125, 30, 4.110037028923576548359531029915430181689e-5L, -10.09949342703221363549386646401175817482L, 0.9997662143139766060126797142254146386006L, 0.0002337856860233939873202857745853613993746L, -0.0002338130181568794225181430950421601604372L, -8.361105733968211082512536218011388359181L }, + { 0.5, 2, 0.13, -3, 0.003238608780817604308032961692976858258538L, -5.732611430028139465850306873793424785492L, 0.0006870172638822821523678523743578983473903L, 0.9993129827361177178476321476256421016526L, -7.283151136680250121578402982594014422121L, -0.0006872533683874924330563580122977629701224L }, + { 0.5, 2, 0.13, -0.5, 0.167642582979750668189820404169765257474L, -1.785921048147577612224991852149429323638L, 0.186938984860475730721935780976793185975L, 0.813061015139524269278064219023206814025L, -1.676972999538390460021589330236193440741L, -0.2069491228782811202391501773295148965376L }, + { 0.5, 2, 0.13, 0.25, 0.1854352593863591939810156732461367276423L, -1.685049463854870883476988933156621950072L, 0.3216431666550400036284121905812256791238L, 0.6783568333449599963715878094187743208762L, -1.134312526011019406511383155627553356037L, -0.3880818266218485114822986459015728619994L }, + { 0.5, 2, 0.13, 1, 0.173243430462994115239555769316327097926L, -1.753057561036600643732551237372863172629L, 0.4575340801157133252464811627294380131082L, 0.5424659198842866747535188372705619868918L, -0.7819039049847524964377866345172480098276L, -0.611630016030606195189945313598941525237L }, + { 0.5, 2, 0.13, 4, 0.06845798596980971827317031124342798230274L, -2.681535065392460035884664670868056662852L, 0.813310520058397836922121976181850860999L, 0.186689479941602163077878023818149139001L, -0.2066422988649100421747385705977984967315L, -1.678308577415702260218934747197293895355L }, + { 0.5, 2, 0.13, 30, 4.537717623727485757201078903810861975631e-5L, -10.00050130537729555640686691536980221853L, 0.9997351891111566976157126505655734167769L, 0.0002648108888433023842873494344265832231021L, -0.0002648459574378944841479534482292109445275L, -8.236494613737416399497571797131769469261L }, + { 0.5, 2, -0.3, -3, 0.02257883218224408674428728479627418398383L, -3.79074244071926629082213152250139356226L, 0.01686948545248619375262787356543226767867L, 0.9831305145475138062473721264345677323213L, -4.082248883631195877498228653947753613791L, -0.01701339598251505476486047576402773046538L }, + { 0.5, 2, -0.3, -0.5, 0.1407963398662055892525447031129239136436L, -1.960440830864504084642685787505986146457L, 0.2032324564965004859201866072448043529658L, 0.7967675435034995140798133927551956470342L, -1.59340484917992907506999272775344169187L, -0.227192307096227335984562664303698179324L }, + { 0.5, 2, -0.3, 0.25, 0.1759055476293873263072756029607300024377L, -1.737808089194809348779680153454023765511L, 0.3228523505680641335944189777181274753936L, 0.6771476494319358664055810222818725246064L, -1.130560179254535433596138358277503983987L, -0.3898659361532131300854343785533963854326L }, + { 0.5, 2, -0.3, 1, 0.1927795672983714006835847556170475107805L, -1.646207881164722508291043440915108869867L, 0.4624807071474759097728591303018553747857L, 0.5375192928525240902271408696981446252143L, -0.7711504371754495264611890107350469005594L, -0.6207906259453672883184693821818092690651L }, + { 0.5, 2, -0.3, 4, 0.08096038522226132802083470239305868591372L, -2.513795315274196404958072065994092601609L, 0.9197803753929363396011351962134600433416L, 0.08021962460706366039886480378653995665844L, -0.08362035983676079918029272072320952064178L, -2.522987098194140438626166073892907539789L }, + { 0.5, 2, 0.3, -3, 8.059704992362896995119811007517873715506e-5L, -9.426048510565349992020177118882759848275L, 6.402576600575467769883962668923564384817e-6L, 0.9999935974233994245322301160373310764356L, -11.95881005477788658284444167501990557427L, -6.402597097156518221636218314392215847589e-6L }, + { 0.5, 2, 0.3, -0.5, 0.1812503225698147173179925232617782002554L, -1.707876205553407075855624216073082303607L, 0.1792492973447090255388108136039045090739L, 0.8207507026552909744611891863960954909261L, -1.71897771948381971532460359928267808018L, -0.1975358664871359474170686040679475679825L }, + { 0.5, 2, 0.3, 0.25, 0.1894940236404238306364162765021104566183L, -1.663397792474526321406233515749467943149L, 0.3211407214070816380060702435413827912124L, 0.6788592785929183619939297564586172087876L, -1.135875867468771317232919576205998713349L, -0.3873414209244915061172579286398172204468L }, + { 0.5, 2, 0.3, 1, 0.1665725681295165996385848051549330081597L, -1.79232421989259561589974139903168544228L, 0.4557606462631520925261687698121302605051L, 0.5442393537368479074738312301878697394949L, -0.7857875058209371193944533846408445480066L, -0.6083661404058928633051700276338946733242L }, + { 0.5, 2, 0.3, 4, 0.06286582155301994052150842939996142150539L, -2.766752640494270141607384901313505234844L, 0.7827334860527895458826706624083477548845L, 0.2172665139472104541173293375916522451155L, -0.2449630163437000697794851493209835780066L, -1.526630504159534364420939159431703465001L }, + { 0.5, 2, 0.3, 30, 0.0003273580834484173214067780354743419595302L, -8.024455929786768161735886630208929083997L, 0.996441826975464168416324204254454132273L, 0.003558173024535831583675795745545867727038L, -0.003564518378555365734021672304781503586974L, -5.638508061203108378546491617990135356678L }, + { 0.5, 2, -0.7, -3, 0.03065313768572185299711007995410933359305L, -3.485020250364091045199580492854250520331L, 0.04351602431599833910256362151992301784644L, 0.9564839756840016608974363784800769821536L, -3.134626033640518737066247611835648581181L, -0.04449124331691377264478415694517319717866L }, + { 0.5, 2, -0.7, -0.5, 0.1224780659178903405081370654853399188579L, -2.099823318760895943245804892832088841208L, 0.2153927028350637145526002290527971174053L, 0.7846072971649362854473997709472028825947L, -1.535292392108238402871228881400685712766L, -0.2425719447593194681492008503702743807618L }, + { 0.5, 2, -0.7, 0.25, 0.167880318057502716578366363708646221341L, -1.784503945965868755929679208375181402125L, 0.3239046900990341450574093655119228912695L, 0.6760953099009658549425906344880771087305L, -1.127305972826224354630816284263039890692L, -0.3914212218997065966819085426931104755151L }, + { 0.5, 2, -0.7, 1, 0.2153903268677851220270401478970179674622L, -1.535303423031532923288919312610236116888L, 0.4678015340166633970763864726217391180225L, 0.5321984659833366029236135273782608819775L, -0.7597111456226778590349280458738389255287L, -0.6307388028490597649920765035511791995061L }, + { 0.5, 2, 0.9, -0.5, 0.2530658734606315277479524224191294277061L, -1.374105454735238240559972359301174861478L, 0.1432650870655338913562264826490839940841L, 0.8567349129344661086437735173509160059159L, -1.943058609103825017156942536489297314252L, -0.1546267280300151672391999106680229972773L }, + { 0.5, 2, 0.9, 0.25, 0.2053591919323515073717253479034976085078L, -1.582994677310361952163458363526016508605L, 0.3192433025902280900330646960560710881853L, 0.6807566974097719099669353039439289118147L, -1.141801762863611938061786002862994555557L, -0.3845503091956913171670906007042623815087L }, + { 0.5, 2, 0.9, 1, 0.1466505062859526950907301644183770990309L, -1.919703031222647272046695408322428608797L, 0.450172165222532504053136402084222020012L, 0.549827834777467495946863597915777979988L, -0.7981251800030224208698105134477822631855L, -0.59815007743634220782812536170051942518L }, + { 0.5, 2, 0.9, 4, 0.04785650470556758324311619753289467322999L, -3.039548230811817410079180781740187256459L, 0.7049646710996157775249081280210048415821L, 0.2950353289003842224750918719789951584179L, -0.3496075893409509957988211565573886561168L, -1.220660170828498612057196401644921029177L }, + { 0.5, 2, 0.9, 30, 0.00173336156054610425360097856463650573284L, -6.357692657265018351117128996627085044189L, 0.9491997737464478260487518121425344402256L, 0.05080022625355217395124818785746555977442L, -0.05213599278291702573343607369694041681873L, -2.979854470597536862470282274060356423935L }, + { 0.5, 2, 2, 0.25, 0.2426040447120236162512332757790964753174L, -1.416324610261525447276701173471350332115L, 0.3151518986722023896141958639310454513001L, 0.6848481013277976103858041360689545486999L, -1.154700538379251529018297561003914911295L, -0.3785582151964799813383119465458937224332L }, + { 0.5, 2, 2, 1, 0.1202910057881380141120158758405166072322L, -2.117841423649917915116679819556664070255L, 0.4419773772406739579865398211578859656963L, 0.5580226227593260420134601788421140343037L, -0.816496580927726032732428024901963797322L, -0.5833557748432169237414957712355888063703L }, + { 0.5, 2, 2, 4, 0.03269059698142522532567882310927362868032L, -3.420667796515388102411015891441721522761L, 0.6241250557782609608783975539903324977094L, 0.3758749442217390391216024460096675022906L, -0.4714045207910316829338962414032326928566L, -0.9784987860692273495936509450915494075046L }, + { 0.5, 2, 2, 30, 0.002476748424901686938892812180090879881433L, -6.000808698065031280290777657414978377417L, 0.8343757053045658053987031428930575316221L, 0.1656242946954341946012968571069424683779L, -0.1810714920850370618723100630056445419812L, -1.798033340693379056209812357545670028983L }, + { 0.5, 2, -2, -3, 0.02825439601041371508207652025113584539374L, -3.56650622250772491930639438396616110654L, 0.1198732501037620330747323068407013287011L, 0.8801267498962379669252676931592986712989L, -2.121320343559642573202533086314547117855L, -0.1276893479087839697383530966932791042295L }, + { 0.5, 2, -2, -0.5, 0.08595474576918094590790089441973243385282L, -2.453934333213013012927536906396962930683L, 0.2431167344342142108048623204999460644609L, 0.7568832655657857891951376795000539355391L, -1.41421356237309504880168872420969807857L, -0.278546244085973154673030816903783655471L }, + { 0.5, 2, -2, 0.25, 0.1462039162679206421758576956058319087134L, -1.922752944966945035504966500978731937483L, 0.3269218953517579112720873007606364511319L, 0.6730781046482420887279126992393635488681L, -1.11803398874989484820458683436563811772L, -0.3958939016161662776988365565973799879904L }, + { 0.5, 2, -2, 1, 0.3486522152763511488462237401551361482114L, -1.053680371466520179109460422833937323323L, 0.4930686913952397878459573806151774752358L, 0.5069313086047602121540426193848225247642L, -0.7071067811865475244008443621048490392848L, -0.6793797705566755265109604011331633483493L }, +}; + +// mu, sigma, xi, p, quantile(p), quantile(complement(p)) +const long double quantile_data[][6] = { + { 0.5, 2, 0, 1e-300, -12.5756298398083137183963288862606664562L, 1382.051055796427410360676689140201005817L }, + { 0.5, 2, 0, 1e-10, -5.773235076484002964477948553537579912083L, 46.55170185978091360749126779238166592248L }, + { 0.5, 2, 0, 0.001, -3.365289467832130976369869903602085211958L, 14.31451014104743295818180028793985985517L }, + { 0.5, 2, 0, 0.25, -0.1532685199565619648095859264510141972425L, 2.991798647414476396761561605799278127912L }, + { 0.5, 2, 0, 0.5, 1.233025841163328654024878316465338938909L, 1.233025841163328654024878316465338938909L }, + { 0.5, 2, 0, 0.75, 2.991798647414476396761561605799278127912L, -0.1532685199565619648095859264510141972425L }, + { 0.5, 2, 0, 0.999, 14.31451014104743122259023912057020651812L, -3.365289467832130725242925488683664408872L }, + { 0.5, 2, 0, 0.99999999, 37.34136146785521232696297750383352136488L, -5.326947973310027150864118532956906440812L }, + { 0.5, 2, 1e-9, 1e-300, -12.57562979706528988462358895414425749839L, 1382.05153296736722607948550779053034854L }, + { 0.5, 2, 1e-9, 1e-10, -5.77323506664563339355703516054520922164L, 46.55170238997072872238572308430781231717L }, + { 0.5, 2, 1e-9, 0.001, -3.365289464097015311242587306799330065802L, 14.31451018875760567730617218391453783919L }, + { 0.5, 2, 1e-9, 0.25, -0.1532685198498720250296428667953639746252L, 2.991798648966741522220370573709271182235L }, + { 0.5, 2, 1e-9, 0.5, 1.23302584129766037499459114420234923096L, 1.23302584129766037499459114420234923096L }, + { 0.5, 2, 1e-9, 0.75, 2.991798648966741522220370573709271182235L, -0.1532685198498720250296428667953639746252L }, + { 0.5, 2, 1e-9, 0.999, 14.31451018875760394171459902837123186796L, -3.365289464097015060115643377220075461646L }, + { 0.5, 2, 1e-9, 0.99999999, 37.34136180717669311176557459591262533638L, -5.326947964821696488192169976806530503024L }, + { 0.5, 2, -1e-9, 1e-300, -12.57562988255133773846638851920848108813L, 1382.050578625707339929835571189279739489L }, + { 0.5, 2, -1e-9, 1e-10, -5.773235086322372555971663663944269955237L, 46.55170132959110663131118162134251665025L }, + { 0.5, 2, -1e-9, 0.001, -3.36528947156724664630958691735551269533L, 14.31451009333726045875498283928558450044L }, + { 0.5, 2, -1e-9, 0.25, -0.1532685200632519046127613791272932954428L, 2.991798645862211272592063350702808937606L }, + { 0.5, 2, -1e-9, 0.5, 1.233025841028996933087988362977232413154L, 1.233025841028996933087988362977232413154L }, + { 0.5, 2, -1e-9, 0.75, 2.991798645862211272592063350702808937606L, -0.1532685200632519046127613791272932954428L }, + { 0.5, 2, -1e-9, 0.999, 14.31451009333725872316343366008950099219L, -3.365289471567246395182642017097924755325L }, + { 0.5, 2, -1e-9, 0.99999999, 37.34136112853373570918213062556195007658L, -5.326947981798357830023087488999341876338L }, + { 0.5, 2, 0.1, 1e-300, -9.098492146372804608864205359432952262754L, 2.00000000000000755311483837239514148787e+31L }, + { 0.5, 2, 0.1, 1e-10, -4.884676695574487760921707924416759610688L, 180.4999999990000148431395292428273467397L }, + { 0.5, 2, 0.1, 0.001, -3.014721011455450203818984787388703685023L, 20.40325025512648903682365669916080180916L }, + { 0.5, 2, 0.1, 0.25, -0.1427147455436507519235484201451701256752L, 3.153677616531757077682086383344611767531L }, + { 0.5, 2, 0.1, 0.5, 1.246624642471412121321222799267411548132L, 1.246624642471412121321222799267411548132L }, + { 0.5, 2, 0.1, 0.75, 3.153677616531757077682086383344611767531L, -0.1427147455436507519235484201451701256752L }, + { 0.5, 2, 0.1, 0.999, 20.40325025512648557403643640179963007554L, -3.014721011455449996824097776356218705496L }, + { 0.5, 2, 0.1, 0.99999999, 106.6914687695347467102837941353157503273L, -4.554879256576813897134283068908618375508L }, + { 0.5, 2, -0.1, 1e-300, -17.95596288816075050927756797340028646439L, 20.49999999999999888977697537482352120613L }, + { 0.5, 2, -0.1, 1e-10, -6.868535862554625238918763399218445721122L, 18.49999999998999924915069534853500923024L }, + { 0.5, 2, -0.1, 0.001, -3.764072223342769747986519854910516424594L, 10.47575391872718881130071752413829357759L }, + { 0.5, 2, -0.1, 0.25, -0.164054630693307353519068190091098963657L, 2.842822795884769008582543984252495089731L }, + { 0.5, 2, -0.1, 0.5, 1.219755290644205266101074759104846547934L, 1.219755290644205266101074759104846547934L }, + { 0.5, 2, -0.1, 0.75, 2.842822795884769008582543984252495089731L, -0.164054630693307353519068190091098963657L }, + { 0.5, 2, -0.1, 0.999, 10.47575391872718794140087223803001241633L, -3.764072223342769443318404029362227341775L }, + { 0.5, 2, -0.1, 0.99999999, 17.330213611900137860993975842357316173L, -6.264588046304391117894908529045757023257L }, + { 0.5, 2, 0.5, 1e-300, -3.347808106759349922301748343690987107433L, 3.999999999999999949881816329582481570545e+150L }, + { 0.5, 2, 0.5, 1e-10, -2.666410670026779358283931425752205794977L, 3.999964999899999927132688700516086050025e+5L }, + { 0.5, 2, 0.5, 0.001, -1.978081067593499220751919467145709898194L, 122.9594744018793442987725313740319406105L }, + { 0.5, 2, 0.5, 0.25, -0.1027127988479238291139886635884415211394L, 3.957677382973556235894851336295208920213L }, + { 0.5, 2, 0.5, 0.5, 1.304489635145799179431213144380886890267L, 1.304489635145799179431213144380886890267L }, + { 0.5, 2, 0.5, 0.75, 3.957677382973556235894851336295208920213L, -0.1027127988479238291139886635884415211394L }, + { 0.5, 2, 0.5, 0.999, 122.9594744018792894282733809833461204596L, -1.978081067593499125203206681530880286184L }, + { 0.5, 2, 0.5, 0.99999999, 39996.49979950481432923013743236994190557L, -2.568018796303575793907240515617076686281L }, + { 0.5, 2, -0.5, 1e-300, -100.6304353951386395706955318473740513189L, 4.5L }, + { 0.5, 2, -0.5, 1e-10, -14.69410364875232481508473000078024131598L, 4.499959999999998999999271301886968726567L }, + { 0.5, 2, -0.5, 0.001, -6.013043539513863941419591712727294057535L, 4.373477253676121397844184180029057779858L }, + { 0.5, 2, -0.5, 0.25, -0.2096400900618987640462773058387985509895L, 2.354559914789393416226967493531125213178L }, + { 0.5, 2, -0.5, 0.5, 1.169781555369208974587341420419195809478L, 1.169781555369208974587341420419195809478L }, + { 0.5, 2, -0.5, 0.75, 2.354559914789393416226967493531125213178L, -0.2096400900618987640462773058387985509895L }, + { 0.5, 2, -0.5, 0.999, 4.373477253676121342946231476168160149408L, -6.013043539513863281392466567948484653939L }, + { 0.5, 2, -0.5, 0.99999999, 4.499599999997995048133242721454662269415L, -12.66772820797328732427871819361313767496L }, + { 0.5, 2, 1.5, 1e-200, -0.8331984152353507655021985957119811372087L, 1.333333333333333369132808535167814942226e+300L }, + { 0.5, 2, 1.5, 1e-10, -0.8212658917939733770375279133898950683426L, 1.333333333233332427135188704159432109032e+15L }, + { 0.5, 2, 1.5, 0.001, -0.7598932228613076226472790168569414439187L, 42131.24470703879474650865711481124332923L }, + { 0.5, 2, 1.5, 0.25, -0.01645843373705890274069126157240972584411L, 7.807776763674368551664252384128167313212L }, + { 0.5, 2, 1.5, 0.5, 1.477137790209089876562044068057611286388L, 1.477137790209089876562044068057611286388L }, + { 0.5, 2, 1.5, 0.75, 7.807776763674368551664252384128167313212L, -0.01645843373705890274069126157240972584411L }, + { 0.5, 2, 1.5, 0.999, 42131.24470703873990344933112866136953218L, -0.759893222861307608815186111606538485309L }, + { 0.5, 2, 1.5, 0.99999999, 1.333333313282981533418812268220497771132e+12L, -0.81646857107861184640351984211780469705L }, + { 0.5, 2, -1.5, 1e-300, -24205.34400274864829699997496298744631796L, 1.833333333333333333333333333333333333333L }, + { 0.5, 2, -1.5, 1e-10, -145.4868564499990778008788306250011297411L, 1.833333333333331999999999899999927127689L }, + { 0.5, 2, -1.5, 0.001, -22.37384400274864818889387098884254541468L, 1.83329113798336568488968167869093474847L }, + { 0.5, 2, -1.5, 0.25, -0.3429824999189946874784489084545169083132L, 1.627598449988495743380535845506960621981L }, + { 0.5, 2, -1.5, 0.5, 1.06388949148514695405338186368306265767L, 1.06388949148514695405338186368306265767L }, + { 0.5, 2, -1.5, 0.75, 1.627598449988495743380535845506960621981L, -0.3429824999189946874784489084545169083132L }, + { 0.5, 2, -1.5, 0.999, 1.833291137983365684834756258697668850538L, -22.3738440027486436295880129985934156298L }, + { 0.5, 2, -1.5, 0.99999999, 1.833333333331999999979950481231931414678L, -103.5804134439192277068503656272328464734L }, +}; + +// xi, mean, variance, skewness, kurtosis_excess, mode, median, entropy, for mu = 0.5, sigma = 2 +const long double moment_data[][8] = { + { -3, -2.833333333333333333333333333333333333333L, 304.0L, -19.58485896516058864744704924603960276765L, 1002.531855955678670360110803324099722992L, 1.166666666666666666666666666666666666667L, 0.9446502320073803468540976115921796372292L, 0.5387158507568795882042079412933717059912L }, + { -1, 0.5L, 4.0L, -2.0L, 6.0L, 2.5L, 1.113705638880109381165535757083646863849L, 1.693147180559945309417232121458176568076L }, + { -0.7, 0.7610321918477416120986094092934992813022L, 3.400367327861812827006952124923533645419L, -1.160392728202874330200516009502937526774L, 1.698453497221796334383449480790908683616L, 2.127109656428759269757252685159577858255L, 1.146544828562143746224956954046140776713L, 1.866311880030405193232710602402922212832L }, + { -0.3, 1.183528691291485424098573010753824634699L, 3.913853269298499701383800112689952627786L, -0.06874209942096706080288294973113119974362L, -0.289399162107949706627675781165848166877L, 1.176510388062401562284821150299102160269L, 1.194163629688140530678864252817002609567L, 2.097198145991018318250171797995864498666L }, + { -0.13, 1.424131542591410291946229744699725656592L, 4.952896477265949926405670179598615678555L, 0.5136871089846431160319333561076186998656L, 0.2858096471132615891399975041498497692222L, 0.7760180707317563468194075597259850477742L, 1.215836798220134140775267400701285930257L, 2.195324809024278895581545154437864191538L }, + { -0.12, 1.440163573101605578076943181400254978206L, 5.044061098077296378047764932023288965371L, 0.5540021135248004886617811879635306797331L, 0.3716301414765079931716820994962564984678L, 0.7537157672471984893263687435540211023558L, 1.217139783552452963126246626368292989835L, 2.201096965673294229314315246122693198937L }, + { -0.01, 1.634829761698792572529680260212485936139L, 6.412196648010445039890101186741231605832L, 1.081073759807266273858956528275016526025L, 2.125445886586571376929642583102013399481L, 0.5200996616483335806178703717697134542996L, 1.231684163594858762816687075275816643953L, 2.264590688812462841297521942887004858016L }, + { -1e-6, 1.654429351692890021456710465409222852749L, 6.57971905513086479986738955938859978589L, 1.139541132804515740836640856317379221379L, 2.399971082464274566936674468358194583232L, 0.5000020000009999996665756627996313747545L, 1.2330257068316241121591228516200509969L, 2.27036226824581326849090972512720938759L }, + { -1e-12, 1.654431329801087609222370050051952694087L, 6.579736267375693436975510933807444342468L, 1.139547099398682045080138208052414725792L, 2.399999999971082311659352991890256472674L, 0.5000000000020000000000009999597732949251L, 1.233025841163194322303925031497233263303L, 2.27036284546090095435884267869158222909L }, + { 1e-12, 1.654431329805043833203681940193961353626L, 6.579736267410118054803904146074174922329L, 1.139547099410615269905472390300595465804L, 2.400000000028917688340952240175754611781L, 0.4999999999980000000000010000402267050748L, 1.233025841163462985745831634256318863418L, 2.270362845462055385688645744389575769146L }, + { 1e-6, 1.654433307916871337273665367728207595283L, 6.579753479748693405330144223354347365232L, 1.139553066029341147467124756032196087804L, 2.400028917840957499080165724640479681121L, 0.4999980000010000003334233370193610725493L, 1.233025975495066018764882685290321447262L, 2.270363422677143071556578697953948610645L }, + { 0.01, 1.674395928821558387244769681014319615333L, 6.756655174188248780404314727298438625328L, 1.200478519762556269331078472919269293561L, 2.705134978371804552738435844656986437332L, 0.48010032835166642105707054463640603916L, 1.234370801021428012906777726473035063745L, 2.276135002110493498749966480194153140219L }, + { 0.12, 1.921796457795325141504033129127197829462L, 9.567328041748161760308999329794170737815L, 2.129206380223521923200713361070088227233L, 10.4127143737989297783691126735759442322L, 0.2748768734662167365566969712751014132572L, 1.249384593879594267985829474900117552262L, 2.339628725249662110733173176958464799298L }, + { 0.13, 1.94721813462737892879360520664898861468L, 9.932951514939585997564689348668914277938L, 2.251782857706110263308481491192789580094L, 11.99260069837783378364765088349075208532L, 0.2574963206206130134352559080015524785188L, 1.250769653649645211837358227649886079707L, 2.345400881898677444465943268643293806698L }, + { 0.2, 2.142297137253033769930034117143080376893L, 13.37614224919152628643986765706565611003L, 3.535071604621394887878195503476186178003L, 45.09151212581577318204971476397941468765L, 0.1419250400262719916570182230117110839103L, 1.260560851390051221516189461818868534605L, 2.385805978441784748553427843037065714187L }, + { 0.24, 2.269461454069749995037297391358303819376L, 16.39491346167414058557668895449269328167L, 5.024462495135007919842276150900259265379L, 309.6084113035859890772945909440607406133L, 0.08069406600135331847379173643045407240867L, 1.266231911965916800406745667483278841138L, 2.408894605037846051442602142376350599479L }, +}; + +template +bool representable(long double v) +{ + return std::abs(v) <= (std::numeric_limits::max)() && (v == 0 || std::abs(v) >= (std::numeric_limits::min)()); +} + +// The condition numbers |x f'(x)/f(x)| of the row's functions, from the reference values: with +// s = 1 + xi (x - mu)/sigma and t = -logcdf, d(log t)/dx = -1/(sigma s). +struct cdf_conditions +{ + long double pdf, logpdf, cdf, ccdf, logcdf, logccdf; +}; + +inline cdf_conditions conditions(long double const (&r)[10]) +{ + long double mu = r[0], sigma = r[1], xi = r[2], x = r[3]; + long double s = 1 + xi * (x - mu) / sigma, t = -r[8], P = r[6], Q = r[7]; + long double g = std::abs(x / (sigma * s)); + cdf_conditions c; + c.pdf = g * std::abs(1 + xi - t); + c.logpdf = c.pdf / std::abs(r[5]); + c.cdf = g * t; + c.ccdf = c.cdf * P / Q; + c.logcdf = g; + c.logccdf = c.ccdf / std::abs(r[9]); + return c; +} + +template +void test_cdf() +{ + // 16 ulps times each function's condition number, which is large deep in the tails (38 for the cdf at + // xi = 0.3, x = -3, where t = 12); the condition numbers come from the long double references. + auto ulps = [](long double kappa) { return static_cast(16 * (std::max)(1.0L, kappa)); }; + for (auto const& r : cdf_data) + { + generalized_extreme_value_distribution d(static_cast(r[0]), static_cast(r[1]), static_cast(r[2])); + T x = static_cast(r[3]); + if (static_cast(x) != r[3] || static_cast(d.shape()) != r[2]) + { + continue; + } + cdf_conditions k = conditions(r); + if (representable(r[4])) { CHECK_ULP_CLOSE(static_cast(r[4]), pdf(d, x), ulps(k.pdf)); } + CHECK_ULP_CLOSE(static_cast(r[5]), logpdf(d, x), ulps(k.logpdf)); + if (representable(r[6])) { CHECK_ULP_CLOSE(static_cast(r[6]), cdf(d, x), ulps(k.cdf)); } + if (representable(r[7])) { CHECK_ULP_CLOSE(static_cast(r[7]), cdf(complement(d, x)), ulps(k.ccdf)); } + if (representable(r[8])) { CHECK_ULP_CLOSE(static_cast(r[8]), logcdf(d, x), ulps(k.logcdf)); } + if (representable(r[9])) { CHECK_ULP_CLOSE(static_cast(r[9]), logcdf(complement(d, x)), ulps(k.logccdf)); } + } +} + +template +void test_quantile() +{ + for (auto const& r : quantile_data) + { + generalized_extreme_value_distribution d(static_cast(r[0]), static_cast(r[1]), static_cast(r[2])); + T p = static_cast(r[3]); + if (static_cast(p) != r[3] || static_cast(d.shape()) != r[2]) + { + continue; + } + // mu + sigma q cancels where the quantile is near 0, multiplying the error by (|mu| + |x - mu|)/|x|: + for (int c = 0; c < 2; ++c) + { + long double x = r[4 + c]; + if (!representable(x)) + { + continue; + } + double cancellation = static_cast((std::abs(r[0]) + std::abs(x - r[0])) / std::abs(x)); + double scale = (std::max)(1.0, cancellation); +#if defined(__MINGW32__) || defined(__CYGWIN__) + // MinGW's long double pow loses about |log x| ulps for huge results: + if (std::numeric_limits::digits > 53) + { + scale = (std::max)(scale, static_cast(std::abs(std::log(std::abs(x))))); + } +#endif + unsigned ulps = static_cast(16 * scale); + CHECK_ULP_CLOSE(static_cast(x), c ? quantile(complement(d, p)) : quantile(d, p), ulps); + } + } +} + +template +void test_moments() +{ + const T eps = std::numeric_limits::epsilon(); + for (auto const& r : moment_data) + { + T xi = static_cast(r[0]); + if (static_cast(xi) != r[0]) + { + continue; + } + generalized_extreme_value_distribution d(T(0.5), T(2), xi); + CHECK_ULP_CLOSE(static_cast(r[1]), mean(d), 8); + // Gamma(1 - xi)^2 doubles tgamma's error: + CHECK_ULP_CLOSE(static_cast(r[2]), variance(d), 32); + CHECK_ULP_CLOSE(static_cast(r[2]), standard_deviation(d) * standard_deviation(d), 32); + CHECK_MOLLIFIED_CLOSE(static_cast(r[3]), skewness(d), 64 * eps); + CHECK_MOLLIFIED_CLOSE(static_cast(r[4]), kurtosis_excess(d), 512 * eps); + CHECK_MOLLIFIED_CLOSE(static_cast(r[4] + 3), kurtosis(d), 512 * eps); + CHECK_ULP_CLOSE(static_cast(r[5]), mode(d), 8); + CHECK_ULP_CLOSE(static_cast(r[6]), median(d), 8); + CHECK_ULP_CLOSE(static_cast(r[7]), entropy(d), 8); + } +} + +// The support, its endpoints, the moments' domains, and xi = 0 against extreme_value_distribution. +template +void test_edges() +{ + using boost::math::extreme_value_distribution; + const T inf = std::numeric_limits::infinity(); + generalized_extreme_value_distribution frechet(T(0.5), T(2), T(0.25)); + generalized_extreme_value_distribution weibull(T(0.5), T(2), T(-0.25)); + // mu - sigma/xi: + CHECK_EQUAL(support(frechet).first, T(-7.5)); + CHECK_EQUAL(support(weibull).second, T(8.5)); + CHECK_EQUAL(cdf(frechet, T(-7.5)), T(0)); + CHECK_EQUAL(cdf(frechet, T(-100)), T(0)); + CHECK_EQUAL(cdf(complement(frechet, T(-100))), T(1)); + CHECK_EQUAL(pdf(frechet, T(-7.5)), T(0)); + CHECK_EQUAL(logcdf(frechet, T(-100)), -inf); + CHECK_EQUAL(cdf(weibull, T(8.5)), T(1)); + CHECK_EQUAL(cdf(weibull, T(100)), T(1)); + CHECK_EQUAL(cdf(complement(weibull, T(100))), T(0)); + CHECK_EQUAL(pdf(weibull, T(8.5)), T(0)); + CHECK_EQUAL(logpdf(weibull, T(100)), -inf); + CHECK_EQUAL(quantile(frechet, T(0)), T(-7.5)); + CHECK_EQUAL(quantile(complement(weibull, T(0))), T(8.5)); + CHECK_EQUAL(cdf(frechet, inf), T(1)); + CHECK_EQUAL(cdf(weibull, -inf), T(0)); + CHECK_EQUAL(pdf(frechet, inf), T(0)); + // Just past an end point, where (x - mu)/sigma rounds onto it: + generalized_extreme_value_distribution unit_end(T(-1), T(1), T(-1)); + CHECK_EQUAL(pdf(unit_end, T(1e-17)), T(0)); + CHECK_EQUAL(logpdf(unit_end, T(1e-17)), -inf); + CHECK_EQUAL(cdf(unit_end, T(1e-17)), T(1)); + // log(1 - cdf) = -L once t = exp(-L) underflows: + generalized_extreme_value_distribution gumbel(T(0), T(1), T(0)); + if (std::numeric_limits::max_exponent10 < 300) + { + CHECK_ULP_CLOSE(T(-100), logcdf(complement(gumbel, T(100))), 1); + } + else + { + CHECK_ULP_CLOSE(T(-750), logcdf(complement(gumbel, T(750))), 1); + } + // At the upper endpoint the density is t^(1 + xi)/sigma with t = 0: + CHECK_EQUAL(pdf(generalized_extreme_value_distribution(T(0), T(2), T(-1)), T(2)), T(0.5)); + CHECK_THROW(pdf(generalized_extreme_value_distribution(T(0), T(2), T(-2)), T(1)), std::overflow_error); + // Unbounded ends: + CHECK_THROW(quantile(frechet, T(1)), std::overflow_error); + CHECK_THROW(quantile(weibull, T(0)), std::overflow_error); + // Moments that do not exist: + generalized_extreme_value_distribution heavy(T(0), T(1), T(1)); + // The mean and variance are infinite there, the skewness and kurtosis undefined: + CHECK_EQUAL(mean(heavy), inf); + CHECK_EQUAL(variance(generalized_extreme_value_distribution(T(0), T(1), T(0.5))), inf); + CHECK_EQUAL(standard_deviation(heavy), inf); + CHECK_THROW(skewness(generalized_extreme_value_distribution(T(0), T(1), T(1) / 3)), std::domain_error); + CHECK_THROW(kurtosis(generalized_extreme_value_distribution(T(0), T(1), T(0.25))), std::domain_error); + CHECK_THROW(generalized_extreme_value_distribution(T(0), T(0), T(0)), std::domain_error); + CHECK_THROW(generalized_extreme_value_distribution(T(0), T(1), inf), std::domain_error); + check_out_of_range>(T(0.5), T(2), T(0.25)); + check_out_of_range>(T(0.5), T(2), T(-0.25)); + + // xi = 0 is the Gumbel distribution, and tiny xi tends to it; two implementations, deep in the tail at x = 30: + generalized_extreme_value_distribution g(T(0.5), T(2), T(0)); + extreme_value_distribution e(T(0.5), T(2)); + for (T x : { T(-3), T(0.5), T(4), T(30) }) + { + CHECK_ULP_CLOSE(pdf(e, x), pdf(g, x), 16); + CHECK_ULP_CLOSE(cdf(e, x), cdf(g, x), 4); + CHECK_ULP_CLOSE(cdf(complement(e, x)), cdf(complement(g, x)), 4); + } + for (T p : { T(0.001), T(0.5), T(0.999) }) + { + CHECK_ULP_CLOSE(quantile(e, p), quantile(g, p), 4); + } + CHECK_ULP_CLOSE(skewness(e), skewness(g), 0); + CHECK_ULP_CLOSE(kurtosis(e), kurtosis(g), 0); + generalized_extreme_value_distribution tiny(T(0.5), T(2), std::numeric_limits::denorm_min()); + CHECK_ULP_CLOSE(mean(e), mean(tiny), 1); + CHECK_ULP_CLOSE(cdf(e, T(4)), cdf(tiny, T(4)), 4); + CHECK_ULP_CLOSE(quantile(e, T(0.25)), quantile(tiny, T(0.25)), 4); +} + +#ifdef BOOST_MATH_TEST_GEV_MULTIPRECISION +// The moment series in many digits, against the closed forms in more, and the quantile's round trip +// (away from p -> 0, where cdf(quantile(p)) multiplies the error by -log p). +void test_multiprecision() +{ + using T = boost::multiprecision::cpp_bin_float_50; + using U = boost::multiprecision::cpp_bin_float_100; + for (const char* s : { "-0.1", "-1e-10", "1e-10", "0.0625", "0.15", "0.2" }) + { + T xi(s); + U k(xi); + generalized_extreme_value_distribution d(T(0), T(1), xi); + U g1 = boost::math::tgamma(1 - k), g2 = boost::math::tgamma(1 - 2 * k), g3 = boost::math::tgamma(1 - 3 * k), g4 = boost::math::tgamma(1 - 4 * k); + U var = (g2 - g1 * g1) / (k * k); + U skew = (k > 0 ? 1 : -1) * (g3 - 3 * g1 * g2 + 2 * g1 * g1 * g1) / pow(g2 - g1 * g1, U(1.5)); + U kex = (g4 - 4 * g1 * g3 + 6 * g2 * g1 * g1 - 3 * g1 * g1 * g1 * g1) / ((g2 - g1 * g1) * (g2 - g1 * g1)) - 3; + // tgamma itself is ~20 ulps at 50 digits, and the variance has Gamma(1 - xi)^2: + CHECK_ULP_CLOSE(T(var), variance(d), 128); + CHECK_MOLLIFIED_CLOSE(T(skew), skewness(d), T(64 * std::numeric_limits::epsilon())); + CHECK_MOLLIFIED_CLOSE(T(kex), kurtosis_excess(d), T(512 * std::numeric_limits::epsilon())); + for (T p : { T(0.001), T(0.3), T(0.9) }) + { + CHECK_ULP_CLOSE(p, cdf(d, quantile(d, p)), 64); + } + } +} +#endif + +int main() +{ + test_cdf(); + test_cdf(); + test_cdf(); + test_quantile(); + test_quantile(); + test_quantile(); + test_moments(); + test_moments(); + test_moments(); + test_edges(); + test_edges(); + test_edges(); +#ifdef BOOST_MATH_TEST_GEV_MULTIPRECISION + test_multiprecision(); +#endif + return boost::math::test::report_errors(); +} diff --git a/test/test_geometric.cpp b/test/test_geometric.cpp index 7e1a00f574..0d27c862c8 100644 --- a/test/test_geometric.cpp +++ b/test/test_geometric.cpp @@ -802,6 +802,23 @@ if(std::numeric_limits::is_specialized) return; } // template void test_spots(RealType) // Any floating-point type RealType. +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(entropy(geometric_distribution(a)), h, tol); + }; + check(static_cast(0.5L), static_cast(1.38629436111989061883446424291635313615100027L)); + check(static_cast(0.125L), static_cast(3.01416129005149429027610171089397952635241012L)); + check(static_cast(0.0009765625L), static_cast(7.93098336532607797421766209482556123084489774L)); + check(static_cast(0.99999904632568359375L), static_cast(1.41744206512281872090189702738787926182672857e-5L)); + BOOST_CHECK_EQUAL(entropy(geometric_distribution(1)), RealType(0)); +} + BOOST_AUTO_TEST_CASE( test_main ) { // Check that can generate geometric distribution using the two convenience methods: @@ -824,17 +841,21 @@ BOOST_AUTO_TEST_CASE( test_main ) // (Parameter value, arbitrarily zero, only communicates the floating point type). #ifdef TEST_FLOAT test_spots(0.0F); // Test float. + test_entropy(0.0F); #endif #ifdef TEST_DOUBLE test_spots(0.0); // Test double. + test_entropy(0.0); #endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS #ifdef TEST_LDOUBLE test_spots(0.0L); // Test long double. + test_entropy(0.0L); #endif #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x582)) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) #if defined(TEST_REAL_CONCEPT) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #endif #else diff --git a/test/test_gradient_descent_module.cpp b/test/test_gradient_descent_module.cpp new file mode 100644 index 0000000000..fca1a1ed83 --- /dev/null +++ b/test/test_gradient_descent_module.cpp @@ -0,0 +1,137 @@ +// Copyright Maksym Zhelyenzyakov 2025-2026. +// Copyright Matt Borland 2026. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) +// +// Module build check for boost::math::optimization::gradient_descent. When +// BOOST_MATH_BUILD_MODULE is defined the component is consumed through +// `import boost.math;` and the standard library through `import std;` (performed +// by math_unit_test.hpp). Nothing standard or Boost is included textually in +// that mode. +// +// The optimizer minimizes f(x) = sum_i x_i^2, whose gradient is 2 x_i. With a +// fixed learning rate lr a single descent step maps each coordinate x_i to +// x_i * (1 - 2*lr), and repeated steps drive the minimizer to the origin. Both +// the one-step and the limiting values are mathematically certain; the setup +// mirrors the analytic_derivative_policies case in +// test_gradient_descent_optimizer.cpp. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif +#include "math_unit_test.hpp" + +namespace bopt = boost::math::optimization; + +// f(x) = sum_i x_i^2. Its gradient, 2 x_i, is supplied analytically by the +// gradient policy below, so one descent step scales each x_i by (1 - 2*lr). +template +Real sum_of_squares(const std::vector& x) +{ + Real s {0}; + for (const auto& xi : x) + { + s += xi * xi; + } + return s; +} + +// Leave the caller-supplied starting point untouched. +template +struct no_init_policy +{ + void operator()(std::vector&) const noexcept {} +}; + +// Evaluate the objective directly. +template +struct analytic_objective_eval_pol +{ + template + Real operator()(Objective&& objective, ArgumentContainer& x) + { + return objective(x); + } +}; + +// Supply the analytic gradient of sum_of_squares: grad_i = 2 x_i. +template +struct analytic_gradient_eval_pol +{ + template + void operator()(Objective&& obj_f, + ArgumentContainer& x, + FunctionEvaluationPolicy&& f_eval_pol, + Real& obj_v, + std::vector& grad_container) + { + obj_v = f_eval_pol(obj_f, x); + grad_container.resize(x.size()); + for (std::size_t i = 0; i < x.size(); ++i) + { + grad_container[i] = 2 * x[i]; + } + } +}; + +template +void test_gradient_descent(Real, const char* type_name) +{ + std::cout << "Testing gradient_descent for type " << type_name << std::endl; + + // One step with lr = 0.01 scales each coordinate by (1 - 2*lr) = 0.98: + // {3, -4, 5} -> {2.94, -3.92, 4.9}. + { + Real lr = Real {1} / Real {100}; + std::vector x = {Real {3}, Real {-4}, Real {5}}; + + auto gdopt = bopt::make_gradient_descent(&sum_of_squares, + x, + lr, + no_init_policy {}, + analytic_objective_eval_pol {}, + analytic_gradient_eval_pol {}); + gdopt.step(); + + CHECK_ULP_CLOSE(2.94, x[0], 4); + CHECK_ULP_CLOSE(-3.92, x[1], 4); + CHECK_ULP_CLOSE(4.9, x[2], 4); + } + + // Repeated steps drive the minimizer of f(x) = sum_i x_i^2 to the origin. + { + Real lr = Real {1} / Real {100}; + std::vector x = {Real {3}, Real {-4}, Real {5}}; + + auto gdopt = bopt::make_gradient_descent(&sum_of_squares, + x, + lr, + no_init_policy {}, + analytic_objective_eval_pol {}, + analytic_gradient_eval_pol {}); + for (std::size_t i = 0; i < 2000; ++i) + { + gdopt.step(); + } + + CHECK_ABSOLUTE_ERROR(Real(0), x[0], Real(1e-3)); + CHECK_ABSOLUTE_ERROR(Real(0), x[1], Real(1e-3)); + CHECK_ABSOLUTE_ERROR(Real(0), x[2], Real(1e-3)); + } +} + +int main() +{ + test_gradient_descent(0.0, "double"); + test_gradient_descent(0.0F, "float"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_gradient_descent_optimizer.cpp b/test/test_gradient_descent_optimizer.cpp index d44a89b987..bb8b829c1e 100644 --- a/test/test_gradient_descent_optimizer.cpp +++ b/test/test_gradient_descent_optimizer.cpp @@ -9,9 +9,9 @@ #include namespace rdiff = boost::math::differentiation::reverse_mode; namespace bopt = boost::math::optimization; -BOOST_AUTO_TEST_SUITE(basic_gradient_descent) -BOOST_AUTO_TEST_CASE_TEMPLATE(default_gd_test, T, all_float_types) +template +void default_gd_test() { size_t NITER = 2000; size_t N = 15; @@ -28,10 +28,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(default_gd_test, T, all_float_types) gdopt.step(); } for (auto& x : x_ad) { - BOOST_REQUIRE_SMALL(x.item(), eps); + if (!CHECK_ABSOLUTE_ERROR(0,x.item(), eps)) { return; } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(test_minimize, T, all_float_types) +template +void test_minimize() { size_t NITER = 2000; size_t N = 15; @@ -46,10 +47,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_minimize, T, all_float_types) bopt::make_gradient_descent(&quadratic>, x_ad, lr); auto z = minimize(gdopt); for (auto& x : x_ad) { - BOOST_REQUIRE_SMALL(x.item(), eps); + if (!CHECK_ABSOLUTE_ERROR(0,x.item(), eps)) { return; } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(random_initializer_test, T, all_float_types) +template +void random_initializer_test() { size_t N = 10; T lr = T{ 1e-2 }; @@ -63,12 +65,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(random_initializer_test, T, all_float_types) T(-2.0), T(2.0), 1234)); for (auto& xi : x) { T v = xi.item(); - BOOST_TEST(v >= -2); - BOOST_TEST(v <= 2); + CHECK_TRUE(v >= -2); + CHECK_TRUE(v <= 2); } gdopt.step(); } -BOOST_AUTO_TEST_CASE_TEMPLATE(const_initializer_test, T, all_float_types) +template +void const_initializer_test() { size_t N = 10; T lr = T{ 1e-2 }; @@ -82,12 +85,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(const_initializer_test, T, all_float_types) for (auto& xi : x) { T v = xi.item(); - BOOST_REQUIRE_CLOSE(v, T{ 5.0 }, T{ 1e-3 }); + if (!CHECK_RELATIVE_ERROR(v, T{ 5.0 }, (T{ 1e-3 }) / 100)) { return; } } gdopt.step(); } -BOOST_AUTO_TEST_CASE_TEMPLATE(box_constraint_test, T, all_float_types) +template +void box_constraint_test() { size_t N = 5; T lr = T{ 1e-2 }; @@ -100,11 +104,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(box_constraint_test, T, all_float_types) gdopt, bopt::box_constraints>, T>(-1.0, 1.0)); for (auto& xi : x) { - BOOST_TEST(xi.item() >= -1.0); - BOOST_TEST(xi.item() <= 1.0); + CHECK_TRUE(xi.item() >= -1.0); + CHECK_TRUE(xi.item() <= 1.0); } } -BOOST_AUTO_TEST_CASE_TEMPLATE(max_iter_test, T, all_float_types) +template +void max_iter_test() { size_t N = 2; T lr = T{ 1e-6 }; // very slow learning @@ -120,10 +125,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(max_iter_test, T, all_float_types) bopt::gradient_norm_convergence_policy(T{ 1e-20 }), bopt::max_iter_termination_policy(max_iter)); - BOOST_TEST(!res.converged); // should not converge with tiny lr - BOOST_REQUIRE_EQUAL(res.num_iter, max_iter); + CHECK_TRUE(!res.converged); // should not converge with tiny lr + if (!CHECK_EQUAL(res.num_iter, max_iter)) { return; } } -BOOST_AUTO_TEST_CASE_TEMPLATE(history_tracking_test, T, all_float_types) +template +void history_tracking_test() { size_t N = 3; T lr = T{ 1e-2 }; @@ -139,10 +145,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(history_tracking_test, T, all_float_types) bopt::max_iter_termination_policy(1000), true); // enable history - BOOST_TEST(!res.objective_history.empty()); - BOOST_TEST(res.objective_history.front() > res.objective_history.back()); + CHECK_TRUE(!res.objective_history.empty()); + CHECK_TRUE(res.objective_history.front() > res.objective_history.back()); } -BOOST_AUTO_TEST_CASE_TEMPLATE(rosenbrock_test, T, all_float_types) +template +void rosenbrock_test() { std::array, 2> x = { T{ -1.2 }, T{ 1.0 } }; // bad start T lr = T{ 1e-3 }; @@ -155,35 +162,36 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(rosenbrock_test, T, all_float_types) bopt::unconstrained_policy, 2>>{}, bopt::gradient_norm_convergence_policy(T{ 1e-4 }), bopt::max_iter_termination_policy(50000)); - BOOST_TEST(res.converged); - BOOST_REQUIRE_CLOSE(x[0].item(), T{ 1.0 }, T{ 1e-1 }); - BOOST_REQUIRE_CLOSE(x[1].item(), T{ 1.0 }, T{ 1e-1 }); + CHECK_TRUE(res.converged); + if (!CHECK_RELATIVE_ERROR(x[0].item(), T{ 1.0 }, (T{ 1e-1 }) / 100)) { return; } + if (!CHECK_RELATIVE_ERROR(x[1].item(), T{ 1.0 }, (T{ 1e-1 }) / 100)) { return; } } -BOOST_AUTO_TEST_CASE_TEMPLATE(objective_tol_convergence_test, - T, - all_float_types) +template +void objective_tol_convergence_test() { using policy_t = bopt::objective_tol_convergence_policy; policy_t pol(1e-3); std::vector dummy_grad; - BOOST_TEST(!pol(dummy_grad, T{100.0})); - BOOST_TEST(!pol(dummy_grad, T{99.0})); - BOOST_TEST(pol(dummy_grad, T{99.0005})); + CHECK_TRUE(!pol(dummy_grad, T{100.0})); + CHECK_TRUE(!pol(dummy_grad, T{99.0})); + CHECK_TRUE(pol(dummy_grad, T{99.0005})); } -BOOST_AUTO_TEST_CASE_TEMPLATE(relative_objective_tol_test, T, all_float_types) +template +void relative_objective_tol_test() { using policy_t = bopt::relative_objective_tol_policy; policy_t pol(1e-3); std::vector dummy_grad; - BOOST_TEST(!pol(dummy_grad, T{1000.0})); - BOOST_TEST(!pol(dummy_grad, T{1010.0})); - BOOST_TEST(pol(dummy_grad, T{1010.5})); + CHECK_TRUE(!pol(dummy_grad, T{1000.0})); + CHECK_TRUE(!pol(dummy_grad, T{1010.0})); + CHECK_TRUE(pol(dummy_grad, T{1010.5})); } -BOOST_AUTO_TEST_CASE_TEMPLATE(combined_policy_test, T, all_float_types) +template +void combined_policy_test() { using pol_abs = bopt::objective_tol_convergence_policy; using pol_rel = bopt::relative_objective_tol_policy; @@ -195,12 +203,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(combined_policy_test, T, all_float_types) std::vector dummy_grad; - BOOST_TEST(!comb(dummy_grad, T{100.0})); - BOOST_TEST(!comb(dummy_grad, T{110.0})); - BOOST_TEST(comb(dummy_grad, T{110.1})); - BOOST_TEST(comb(dummy_grad, T{110.1000001})); + CHECK_TRUE(!comb(dummy_grad, T{100.0})); + CHECK_TRUE(!comb(dummy_grad, T{110.0})); + CHECK_TRUE(comb(dummy_grad, T{110.1})); + CHECK_TRUE(comb(dummy_grad, T{110.1000001})); } -BOOST_AUTO_TEST_CASE_TEMPLATE(nonnegativity_constraint_test, T, all_float_types) +template +void nonnegativity_constraint_test() { std::vector x = {T{1.0}, T{-2.0}, T{3.0}, T{-4.0}}; @@ -208,33 +217,39 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(nonnegativity_constraint_test, T, all_float_types) proj(x); for (auto& xi : x) - BOOST_TEST(xi >= 0.0); - BOOST_TEST(x == std::vector({T{1.0}, T{0.0}, T{3.0}, T{0.0}})); + CHECK_TRUE(xi >= 0.0); + CHECK_TRUE(x == std::vector({T{1.0}, T{0.0}, T{3.0}, T{0.0}})); } -BOOST_AUTO_TEST_CASE_TEMPLATE(l2_ball_constraint_test, T, all_float_types) +template +void l2_ball_constraint_test() { + using std::abs; std::vector x = {T{3.0}, T{4.0}}; // norm = 5 bopt::l2_ball_constraint, T> proj(1.0); proj(x); T norm = sqrt(x[0] * x[0] + x[1] * x[1]); - BOOST_TEST(abs(norm - T{1.0}) < T{1e-12}); // projected to unit circle + CHECK_TRUE(abs(norm - T{1.0}) < T{1e-12}); // projected to unit circle } -BOOST_AUTO_TEST_CASE_TEMPLATE(l1_ball_constraint_test, T, all_float_types) +template +void l1_ball_constraint_test() { + using std::abs; std::vector x = {T{3.0}, T{4.0}}; // L1 norm = 7 bopt::l1_ball_constraint, T> proj(2.0); proj(x); T norm1 = abs(x[0]) + abs(x[1]); - BOOST_TEST(abs(norm1 - T{2.0}) < T{1e-12}); + CHECK_TRUE(abs(norm1 - T{2.0}) < T{1e-12}); } -BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_constraint_test, T, all_float_types) +template +void simplex_constraint_test() { + using std::abs; std::vector x = {T{-1.0}, T{2.0}, T{3.0}}; // has negative and sum != 1 bopt::simplex_constraint, T> proj; @@ -242,23 +257,26 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_constraint_test, T, all_float_types) T sum = 0.0; for (auto& xi : x) { - BOOST_TEST(xi >= 0.0); // all nonnegative + CHECK_TRUE(xi >= 0.0); // all nonnegative sum += xi; } - BOOST_TEST(abs(sum - T{1.0}) < T{1e-12}); // normalized to sum=1 + CHECK_TRUE(abs(sum - T{1.0}) < T{1e-12}); // normalized to sum=1 } -BOOST_AUTO_TEST_CASE_TEMPLATE(unit_sphere_constraint_test, T, all_float_types) +template +void unit_sphere_constraint_test() { + using std::abs; std::vector x = {T{0.3}, T{0.4}}; // norm = 0.5 bopt::unit_sphere_constraint, T> proj; proj(x); T norm = sqrt(x[0] * x[0] + x[1] * x[1]); - BOOST_TEST(abs(norm - T{1.0}) < T{1e-12}); // always projected to sphere + CHECK_TRUE(abs(norm - T{1.0}) < T{1e-12}); // always projected to sphere } -BOOST_AUTO_TEST_CASE_TEMPLATE(function_constraint_test, T, all_float_types) +template +void function_constraint_test() { auto clip_to_half = [](std::vector& v) { for (auto& xi : v) @@ -270,13 +288,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(function_constraint_test, T, all_float_types) std::vector x = {T{0.2}, T{0.7}, T{1.5}}; proj(x); - BOOST_TEST(x == std::vector({T{0.2}, T{0.5}, T{0.5}})); + CHECK_TRUE(x == std::vector({T{0.2}, T{0.5}, T{0.5}})); } template struct no_init_policy { - void operator()(std::vector& x) const noexcept {} + void operator()(std::vector& /*x*/) const noexcept {} }; template @@ -310,7 +328,8 @@ struct analytic_gradient_eval_pol } }; -BOOST_AUTO_TEST_CASE_TEMPLATE(analytic_derivative_policies, T, all_float_types) +template +void analytic_derivative_policies() { std::vector x; size_t NITER = 2000; @@ -333,7 +352,29 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(analytic_derivative_policies, T, all_float_types) gdopt.step(); } for (auto& xi : x) { - BOOST_REQUIRE_SMALL(xi, eps); + if (!CHECK_ABSOLUTE_ERROR(0,xi, eps)) { return; } } } -BOOST_AUTO_TEST_SUITE_END() + +int main() +{ + boost::mp11::mp_for_each>([](auto t) { default_gd_test(); }); + boost::mp11::mp_for_each>([](auto t) { test_minimize(); }); + boost::mp11::mp_for_each>([](auto t) { random_initializer_test(); }); + boost::mp11::mp_for_each>([](auto t) { const_initializer_test(); }); + boost::mp11::mp_for_each>([](auto t) { box_constraint_test(); }); + boost::mp11::mp_for_each>([](auto t) { max_iter_test(); }); + boost::mp11::mp_for_each>([](auto t) { history_tracking_test(); }); + boost::mp11::mp_for_each>([](auto t) { rosenbrock_test(); }); + boost::mp11::mp_for_each>([](auto t) { objective_tol_convergence_test(); }); + boost::mp11::mp_for_each>([](auto t) { relative_objective_tol_test(); }); + boost::mp11::mp_for_each>([](auto t) { combined_policy_test(); }); + boost::mp11::mp_for_each>([](auto t) { nonnegativity_constraint_test(); }); + boost::mp11::mp_for_each>([](auto t) { l2_ball_constraint_test(); }); + boost::mp11::mp_for_each>([](auto t) { l1_ball_constraint_test(); }); + boost::mp11::mp_for_each>([](auto t) { simplex_constraint_test(); }); + boost::mp11::mp_for_each>([](auto t) { unit_sphere_constraint_test(); }); + boost::mp11::mp_for_each>([](auto t) { function_constraint_test(); }); + boost::mp11::mp_for_each>([](auto t) { analytic_derivative_policies(); }); + return boost::math::test::report_errors(); +} diff --git a/test/header_deprecated_test.cpp b/test/test_header_deprecated.cpp similarity index 100% rename from test/header_deprecated_test.cpp rename to test/test_header_deprecated.cpp diff --git a/test/test_hermite.cpp b/test/test_hermite.cpp index 2e589e6453..6aa5e63d67 100644 --- a/test/test_hermite.cpp +++ b/test/test_hermite.cpp @@ -47,7 +47,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_heuman_lambda.cpp b/test/test_heuman_lambda.cpp index 95c88bcd83..eb34c15426 100644 --- a/test/test_heuman_lambda.cpp +++ b/test/test_heuman_lambda.cpp @@ -45,7 +45,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_heuman_lambda.hpp b/test/test_heuman_lambda.hpp index c0b305d175..190692a18b 100644 --- a/test/test_heuman_lambda.hpp +++ b/test/test_heuman_lambda.hpp @@ -78,6 +78,16 @@ void test_spots(T, const char* type_name) do_test_heuman_lambda(heuman_lambda_data, type_name, "Elliptic Integral Heuman Lambda: Random Data"); + // + // Data is phi, k, result. phi close to pi/2, where 1 - k^2 / delta^2 cancels; values calculated with Arb: + // + static const std::array, 2> data2 = {{ + { { SC_(1.570556640625), SC_(0.99609375), SC_(0.99984939042322658740529229320291417190363051236320589578) } }, + { { SC_(1.570556640625), SC_(0.5), SC_(0.99993800327192228903056807352064091322769813604390459942) } }, + }}; + + do_test_heuman_lambda(data2, type_name, "Elliptic Integral Heuman Lambda: phi near pi/2"); + // // Special cases for coverage: // diff --git a/test/test_holtsmark.cpp b/test/test_holtsmark.cpp index 75cf8a232c..dd0a0c532e 100644 --- a/test/test_holtsmark.cpp +++ b/test/test_holtsmark.cpp @@ -4,16 +4,13 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_TEST_MAIN -#define BOOST_TEST_MODULE StatsHoltsmarkTest #ifdef BOOST_MATH_ENABLE_SYCL #include "sycl/sycl.hpp" #endif #include -#include -#include +#include "math_unit_test.hpp" #include @@ -49,185 +46,185 @@ void do_test_holtsmark_pdf(){ holtsmark_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36729417918039395222067998266923903487897550760740e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65389736963758327689008908803579458127136270822821e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02515191704410688567167143509210415364664018836038e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.51083986231955529936787758130352472694082331202869e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.15094236163249353135030241188004077293096105502542e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.99750209903363198419241505065146206315152726747464e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.11488945306717663129360225856869217115733169200098e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.57635410598104651856363821355027691095093972951943e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.45396231261375200568114750897618690566092315194568e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.56644599840900478087175884712634478003230341866094e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.07991505579130717014680432847812811882295188855215e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21504440259916207727077397273468920426729181666284e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36133628073378183373326886775069575640127303211029e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51745548085348400860371488668500734429223868343929e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.68134487107062900924723590620591092812119992658420e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.85018067925573560771430043931430243630326746823000e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02038159607840130388931544845552929991729709746772e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.10468477092312109723487937526691724501188944561469e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18768434960425041116444711570747254236793293668156e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26876533945661456653252880545328465490361724757011e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.34729279420630671501163324236373491976559833675371e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42262031889641529582832839126322520342094549884605e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.49409942058625893002692983261905908575520500298169e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56108951988457608160176526934999395388199046235972e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62296840354090035789597147663858548813023471783846e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.67914286936215258107106284322230987052088197806732e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72905929336501384188469491706325278582273134014420e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.77221383677408177290219591627664575751370295766362e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.80816200831657887972174538033323818453141437738815e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83652730587590691770044766018047580182775092180058e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85700868106012048340895194764008089858950037497619e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.86938660017923959009561433879636172948429661600328e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.87352751452164445024482162286994868261727837966217e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.86938660017923959009561433879636172948429661600328e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85700868106012048340895194764008089858950037497619e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83652730587590691770044766018047580182775092180058e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.80816200831657887972174538033323818453141437738815e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.77221383677408177290219591627664575751370295766362e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72905929336501384188469491706325278582273134014420e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.67914286936215258107106284322230987052088197806732e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62296840354090035789597147663858548813023471783846e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56108951988457608160176526934999395388199046235972e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.49409942058625893002692983261905908575520500298169e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42262031889641529582832839126322520342094549884605e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.34729279420630671501163324236373491976559833675371e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26876533945661456653252880545328465490361724757011e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18768434960425041116444711570747254236793293668156e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.10468477092312109723487937526691724501188944561469e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02038159607840130388931544845552929991729709746772e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.85018067925573560771430043931430243630326746823000e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.68134487107062900924723590620591092812119992658420e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51745548085348400860371488668500734429223868343929e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36133628073378183373326886775069575640127303211029e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21504440259916207727077397273468920426729181666284e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.07991505579130717014680432847812811882295188855215e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.56644599840900478087175884712634478003230341866094e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.45396231261375200568114750897618690566092315194568e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.57635410598104651856363821355027691095093972951943e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.11488945306717663129360225856869217115733169200098e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.99750209903363198419241505065146206315152726747464e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.15094236163249353135030241188004077293096105502542e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.51083986231955529936787758130352472694082331202869e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02515191704410688567167143509210415364664018836038e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65389736963758327689008908803579458127136270822821e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36729417918039395222067998266923903487897550760740e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.66754576694881156512310862711445437434536539665220e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.11173604765480684115169149814306652067264621028219e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.40661030133408839114013026681116038222350468593972e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.22346322254737897976061662951210609505224644527458e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.37441612177611972649583292419049409747033180591176e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.74744460065068339118467750880557414156817094839507e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(7.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.27304026309950351561235691054710976330201642992015e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(8)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90649774685568282389553481307707005424869182652166e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(9)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38767874243521145729361398147898730301527980427894e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(10)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.04777602492944046116536405570429208835346612226751e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(11)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.14427312838534546510639939284636768866987456541955e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(12)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.48125490715334110982111302156190976484065179596964e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(13)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.25926848543648125740563360613612653857829343973075e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(14)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.33819608589296696976594994753563070519825392999328e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(15)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.62882342819480981578669644070664737082208227167328e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(16)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.07231582988207590928480356376941073734041404814646e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(18)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.27006701837892764913571864450685488819589225207004e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(20)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.73366906892470965030093227280098921046549874789447e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(22)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.35957320021440204694920969306620767773792096574145e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(24)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08962051920666002556891360954800856160496745325982e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(26)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.89257005093845424113694708405490444536741708307432e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(28)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.36985573727704971748849427466806366268717813920884e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(30)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.18908057108330090847508167263164576897080536147998e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(32)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.25741312407933720816582583160953651639222885045617e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(36)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.90521803068812235229266578780465914597024834788499e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(40)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.99440098605222381975051163529379005706849379136631e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(44)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.35556983515831713649398537010595127693244595946631e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(48)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.89252591391344813399503397931059007207167187335384e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(52)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.54761819718387004182264813450582914982582239574760e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(56)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28473144505453904388319480756963924103363111590946e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(60)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08038477619830474574170723303117982155643976342020e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(64)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.18821097500148811906668422616947735567544539343910e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(72)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.83770756909753597744679176403606964363170824955403e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(80)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.25030682765210472090258978149127752580598842866547e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(88)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.13470581474698689445958562292807701026370826971490e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(96)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.32481553840568432886657947564022812389544240910245e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(104)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72079249234488105623103527050493983216840056389979e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(112)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25993583492605042781181768463472827114252734385354e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(120)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90139785097711606987697985776461422964227374409867e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61772178749879746562419160426660201168856327635754e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(256)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85568203412051586615998003517909621954036193765824e-7), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(512)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.04563780918059698346140819518179336362098891429611e-8), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1024)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.91792339891869109849236922708731694322153177924824e-9), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 11)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.57638176923363231335450711092364627257129748508825e-9), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 12)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.78661356398095539721893167504764083609118624639856e-10), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 13)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.92604459926540711296353370623384343787650705186643e-11), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 14)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.70807462044367666228538283653300633948804226008283e-12), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 15)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.53938313936621297172285881159282265471330118114236e-12), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 16)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72126969520581558576219170420297785383800313247716e-13), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 17)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.81057004571925961169117504945825287978291651680376e-14), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 18)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.50396638201843310535816082381660912483279969324341e-15), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 19)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.50330305081854272655464104542050109297998338121296e-15), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 20)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.65748943908780839905864199570025333227786061957216e-16), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 21)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.69782199924985143903444545973473854205301886566784e-17), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 22)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.30465447555059221873312238790689561215989143051468e-18), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 23)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.46806937341565301230797169380667244412810953871153e-18), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 24)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.59520452276585659227559942516968833301265805493281e-19), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.58771679139660099100514647692148711295768774585921e-20), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 26)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.11001413331373018059574227843565648889473010676660e-21), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 27)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43366149729083958029796238740037446793377590904146e-21), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 28)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.53437941664766678806680232945039585344994407777604e-22), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 29)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.48019217902582750507529988918628139079404963189635e-23), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 30)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.91993567701892984811136675864172386794777828712695e-24), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 31)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40006005594525679129869441468227938628239752074460e-24), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 32)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.47497989906821913751146663525981445654490373951224e-25), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 34)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.73431218458810807033921781897016124929992555367139e-27), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 36)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.41697255768378077454412606000376285104775580444420e-28), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 38)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.55303924276181374957661287953452523234530316565188e-30), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 40)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.36032476336306675100543445227730858361169873925804e-31), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 42)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.37601488550958357902586661939110889053699438042016e-33), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 44)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.30500465172174486774768816059192932509423715417166e-34), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 46)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.20313953663045271143891020576861031160487434865093e-36), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 48)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25098110519701647231401040429952006498171313622520e-37), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 50)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.03431595374067647597712273413788666502302011992057e-39), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 52)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19822373554396139874268836303925702273981755123190e-40), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 54)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.86944917357487937107083766130282172728072819621788e-42), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 56)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.14670286674214980345963428973545770896346187182759e-43), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 58)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.70844645856921813581135618689921390269372237700480e-45), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 60)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.09638951830288066744104877057303202280205793138993e-46), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 62)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55121724469650208575327739326222025805731763269349e-48), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 64)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.04725538896765690179789918481715848637732139291593e-49), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 68)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.99927284078872744316201092259372825667966088624440e-52), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 72)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.95241488358274164371290129159422806319923560612665e-55), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 76)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90665515974877113643838016757246988460215123083510e-58), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 80)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.86196792944215931292810563239498984002947733280447e-61), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 84)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.81832805609585870403135315663573226135611325562940e-64), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 88)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.77571099228111201565561831702708228641500206234884e-67), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 92)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.73409276589952345278868976272176004532614982149466e-70), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 96)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.69344996669875337186395484640796879426380291665101e-73), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 100)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65375973310425133971089340469528202564824480281467e-76), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 104)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61499973935962044893641934052273635317211406169375e-79), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 108)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.57714818296837934466447201222923471989464263831856e-82), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 112)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.54018377243005795377389844944261203114711195148214e-85), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 116)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.50408571526372847048232270453380081166710151511926e-88), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 120)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.46883370631223483445539326614628985514365382335866e-91), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 124)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43440791632054183052284498647098618666372443687369e-94), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40078898078177913136996580710057244791379339538446e-97), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40078898078177913136996580710057244791379339538446e-97), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 136)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.33589647367647088181492405614907498160724010027357e-103), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 144)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.27401015632292831593983083357722757492755899455411e-109), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 152)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21499076492588836282713969571802861683612727599536e-115), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 160)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.15870548718060337336267442294886457141506888961350e-121), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 168)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10502766340313279472606127066503960744387520753240e-127), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 176)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05383650150597838852506758753303490394961853745690e-133), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 184)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.00501680517766798832422980073264589686357358689966e-139), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 192)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.58458714654605854343633461697240731109212481403024e-146), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 200)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.14057459501844267219193898865929347142422181513809e-152), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 208)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.71713122846454875201410197130135867254659825815019e-158), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 216)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.31330416532950282288942525034080378775272203269023e-164), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 224)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.92818466694784433640425229105072382712623790043853e-170), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 232)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.56090609259399827614236096482345946037887373012402e-176), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 240)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.21064194926643207182155701143594690359008191120531e-182), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 248)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.87660403181689459974437428611368837698944274063617e-188), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 256)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55804064923943958258092335330361211489624284804933e-194), tolerance); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36729417918039395222067998266923903487897550760740e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65389736963758327689008908803579458127136270822821e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02515191704410688567167143509210415364664018836038e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.51083986231955529936787758130352472694082331202869e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.15094236163249353135030241188004077293096105502542e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.99750209903363198419241505065146206315152726747464e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.11488945306717663129360225856869217115733169200098e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.57635410598104651856363821355027691095093972951943e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.45396231261375200568114750897618690566092315194568e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.56644599840900478087175884712634478003230341866094e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.07991505579130717014680432847812811882295188855215e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21504440259916207727077397273468920426729181666284e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36133628073378183373326886775069575640127303211029e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51745548085348400860371488668500734429223868343929e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.68134487107062900924723590620591092812119992658420e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.85018067925573560771430043931430243630326746823000e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02038159607840130388931544845552929991729709746772e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.10468477092312109723487937526691724501188944561469e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18768434960425041116444711570747254236793293668156e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26876533945661456653252880545328465490361724757011e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.34729279420630671501163324236373491976559833675371e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42262031889641529582832839126322520342094549884605e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.49409942058625893002692983261905908575520500298169e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56108951988457608160176526934999395388199046235972e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62296840354090035789597147663858548813023471783846e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.67914286936215258107106284322230987052088197806732e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72905929336501384188469491706325278582273134014420e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.77221383677408177290219591627664575751370295766362e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.80816200831657887972174538033323818453141437738815e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83652730587590691770044766018047580182775092180058e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85700868106012048340895194764008089858950037497619e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.86938660017923959009561433879636172948429661600328e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.87352751452164445024482162286994868261727837966217e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.86938660017923959009561433879636172948429661600328e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85700868106012048340895194764008089858950037497619e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83652730587590691770044766018047580182775092180058e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.80816200831657887972174538033323818453141437738815e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.77221383677408177290219591627664575751370295766362e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72905929336501384188469491706325278582273134014420e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.67914286936215258107106284322230987052088197806732e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62296840354090035789597147663858548813023471783846e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56108951988457608160176526934999395388199046235972e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.49409942058625893002692983261905908575520500298169e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42262031889641529582832839126322520342094549884605e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.34729279420630671501163324236373491976559833675371e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26876533945661456653252880545328465490361724757011e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18768434960425041116444711570747254236793293668156e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.10468477092312109723487937526691724501188944561469e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02038159607840130388931544845552929991729709746772e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.85018067925573560771430043931430243630326746823000e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.68134487107062900924723590620591092812119992658420e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51745548085348400860371488668500734429223868343929e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36133628073378183373326886775069575640127303211029e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21504440259916207727077397273468920426729181666284e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.07991505579130717014680432847812811882295188855215e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.56644599840900478087175884712634478003230341866094e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.45396231261375200568114750897618690566092315194568e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.57635410598104651856363821355027691095093972951943e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.11488945306717663129360225856869217115733169200098e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.99750209903363198419241505065146206315152726747464e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.15094236163249353135030241188004077293096105502542e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.51083986231955529936787758130352472694082331202869e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02515191704410688567167143509210415364664018836038e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65389736963758327689008908803579458127136270822821e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36729417918039395222067998266923903487897550760740e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.66754576694881156512310862711445437434536539665220e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.11173604765480684115169149814306652067264621028219e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.40661030133408839114013026681116038222350468593972e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.22346322254737897976061662951210609505224644527458e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.37441612177611972649583292419049409747033180591176e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.74744460065068339118467750880557414156817094839507e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(7.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.27304026309950351561235691054710976330201642992015e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(8)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90649774685568282389553481307707005424869182652166e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(9)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38767874243521145729361398147898730301527980427894e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(10)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.04777602492944046116536405570429208835346612226751e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(11)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.14427312838534546510639939284636768866987456541955e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(12)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.48125490715334110982111302156190976484065179596964e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(13)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.25926848543648125740563360613612653857829343973075e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(14)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.33819608589296696976594994753563070519825392999328e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(15)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.62882342819480981578669644070664737082208227167328e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(16)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.07231582988207590928480356376941073734041404814646e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(18)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.27006701837892764913571864450685488819589225207004e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(20)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.73366906892470965030093227280098921046549874789447e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(22)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.35957320021440204694920969306620767773792096574145e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(24)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08962051920666002556891360954800856160496745325982e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(26)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.89257005093845424113694708405490444536741708307432e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(28)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.36985573727704971748849427466806366268717813920884e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(30)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.18908057108330090847508167263164576897080536147998e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(32)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.25741312407933720816582583160953651639222885045617e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(36)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.90521803068812235229266578780465914597024834788499e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(40)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.99440098605222381975051163529379005706849379136631e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(44)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.35556983515831713649398537010595127693244595946631e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(48)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.89252591391344813399503397931059007207167187335384e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(52)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.54761819718387004182264813450582914982582239574760e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(56)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28473144505453904388319480756963924103363111590946e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(60)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08038477619830474574170723303117982155643976342020e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(64)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.18821097500148811906668422616947735567544539343910e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(72)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.83770756909753597744679176403606964363170824955403e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(80)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.25030682765210472090258978149127752580598842866547e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(88)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.13470581474698689445958562292807701026370826971490e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(96)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.32481553840568432886657947564022812389544240910245e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(104)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72079249234488105623103527050493983216840056389979e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(112)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25993583492605042781181768463472827114252734385354e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(120)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90139785097711606987697985776461422964227374409867e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61772178749879746562419160426660201168856327635754e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(256)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85568203412051586615998003517909621954036193765824e-7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(512)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.04563780918059698346140819518179336362098891429611e-8), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1024)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.91792339891869109849236922708731694322153177924824e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 11)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.57638176923363231335450711092364627257129748508825e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 12)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.78661356398095539721893167504764083609118624639856e-10), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 13)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.92604459926540711296353370623384343787650705186643e-11), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 14)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.70807462044367666228538283653300633948804226008283e-12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 15)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.53938313936621297172285881159282265471330118114236e-12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 16)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72126969520581558576219170420297785383800313247716e-13), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 17)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.81057004571925961169117504945825287978291651680376e-14), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 18)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.50396638201843310535816082381660912483279969324341e-15), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 19)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.50330305081854272655464104542050109297998338121296e-15), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 20)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.65748943908780839905864199570025333227786061957216e-16), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 21)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.69782199924985143903444545973473854205301886566784e-17), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 22)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.30465447555059221873312238790689561215989143051468e-18), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 23)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.46806937341565301230797169380667244412810953871153e-18), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 24)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.59520452276585659227559942516968833301265805493281e-19), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.58771679139660099100514647692148711295768774585921e-20), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 26)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.11001413331373018059574227843565648889473010676660e-21), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 27)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43366149729083958029796238740037446793377590904146e-21), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 28)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.53437941664766678806680232945039585344994407777604e-22), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 29)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.48019217902582750507529988918628139079404963189635e-23), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 30)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.91993567701892984811136675864172386794777828712695e-24), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 31)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40006005594525679129869441468227938628239752074460e-24), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 32)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.47497989906821913751146663525981445654490373951224e-25), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 34)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.73431218458810807033921781897016124929992555367139e-27), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 36)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.41697255768378077454412606000376285104775580444420e-28), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 38)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.55303924276181374957661287953452523234530316565188e-30), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 40)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.36032476336306675100543445227730858361169873925804e-31), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 42)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.37601488550958357902586661939110889053699438042016e-33), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 44)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.30500465172174486774768816059192932509423715417166e-34), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 46)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.20313953663045271143891020576861031160487434865093e-36), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 48)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25098110519701647231401040429952006498171313622520e-37), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 50)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.03431595374067647597712273413788666502302011992057e-39), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 52)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19822373554396139874268836303925702273981755123190e-40), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 54)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.86944917357487937107083766130282172728072819621788e-42), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 56)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.14670286674214980345963428973545770896346187182759e-43), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 58)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.70844645856921813581135618689921390269372237700480e-45), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 60)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.09638951830288066744104877057303202280205793138993e-46), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 62)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55121724469650208575327739326222025805731763269349e-48), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 64)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.04725538896765690179789918481715848637732139291593e-49), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 68)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.99927284078872744316201092259372825667966088624440e-52), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 72)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.95241488358274164371290129159422806319923560612665e-55), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 76)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90665515974877113643838016757246988460215123083510e-58), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 80)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.86196792944215931292810563239498984002947733280447e-61), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 84)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.81832805609585870403135315663573226135611325562940e-64), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 88)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.77571099228111201565561831702708228641500206234884e-67), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 92)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.73409276589952345278868976272176004532614982149466e-70), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 96)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.69344996669875337186395484640796879426380291665101e-73), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 100)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65375973310425133971089340469528202564824480281467e-76), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 104)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61499973935962044893641934052273635317211406169375e-79), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 108)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.57714818296837934466447201222923471989464263831856e-82), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 112)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.54018377243005795377389844944261203114711195148214e-85), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 116)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.50408571526372847048232270453380081166710151511926e-88), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 120)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.46883370631223483445539326614628985514365382335866e-91), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 124)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43440791632054183052284498647098618666372443687369e-94), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40078898078177913136996580710057244791379339538446e-97), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40078898078177913136996580710057244791379339538446e-97), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 136)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.33589647367647088181492405614907498160724010027357e-103), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 144)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.27401015632292831593983083357722757492755899455411e-109), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 152)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21499076492588836282713969571802861683612727599536e-115), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 160)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.15870548718060337336267442294886457141506888961350e-121), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 168)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10502766340313279472606127066503960744387520753240e-127), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 176)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05383650150597838852506758753303490394961853745690e-133), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 184)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.00501680517766798832422980073264589686357358689966e-139), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 192)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.58458714654605854343633461697240731109212481403024e-146), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 200)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.14057459501844267219193898865929347142422181513809e-152), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 208)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.71713122846454875201410197130135867254659825815019e-158), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 216)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.31330416532950282288942525034080378775272203269023e-164), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 224)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.92818466694784433640425229105072382712623790043853e-170), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 232)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.56090609259399827614236096482345946037887373012402e-176), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 240)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.21064194926643207182155701143594690359008191120531e-182), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 248)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.87660403181689459974437428611368837698944274063617e-188), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 256)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55804064923943958258092335330361211489624284804933e-194), (tolerance) / 100); } template @@ -243,79 +240,79 @@ void do_test_holtsmark_cdf() { holtsmark_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.05754562114095147060025732340404110273918791128410e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.43368449353064312968788810247763526151579823896375e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.89152652981222928500336992235218785823347685619486e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.45576815036790322986175114501424442292398775002753e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.15978035591850473786135203626730317231876547935253e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04840867577215219812315602202859291564396444891271e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.18107352643844092577238041212187564083206726822056e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.63452659158632535349648745626466375370661702427253e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05039829654829170780787685299557006719608839147146e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.16290125976286647650587923507379034571826555851855e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.29006094814340314434551699445775276932192677014796e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43337488600334723245402521343673257218591019586678e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.59428804524998597404889957316726146572475641692056e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.77411943695232738645173996334900914289694617802622e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.97397674713122675501528813572074060920189377220435e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19466281873758062089629668872911218009781881016957e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.43657975600729535499895880792984203156689462603233e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56549331000915958092357114949075709547374035120716e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.69963821328456787766164921360924665804748003656962e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83891389704828738280543932012082190429368746897774e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.98318069008956501931929973721256792184639224594009e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13225883262651243874304479279543149837428487068880e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.28592804901375835801811223649103787689862120396348e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.44392772657854742558827130471487286937515502098876e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.60595773518728397925852903878144782668636743128847e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.77167990746831553875195022302050315427406387091454e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.94072018335986771952143399033763464047462959349960e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.11267140533666880513239944176560287064005137544504e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.28709673289702231328042170648699212093305785288837e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.46353362731996489993314637378816744341919505345430e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.64149834100915287958166424201293669944118353975980e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.82049083059559169016945833205795772857456974521089e-1), tolerance); - BOOST_CHECK_EQUAL(cdf(dist, static_cast(0)), static_cast(0.5)); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.17950916940440830983054166794204227142543025478911e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.35850165899084712041833575798706330055881646024020e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.53646637268003510006685362621183255658080494654570e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.71290326710297768671957829351300787906694214711163e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.88732859466333119486760055823439712935994862455496e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.05927981664013228047856600966236535952537040650040e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.22832009253168446124804977697949684572593612908546e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.39404226481271602074147096121855217331363256871153e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55607227342145257441172869528512713062484497901124e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.71407195098624164198188776350896212310137879603652e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.86774116737348756125695520720456850162571512931120e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.01681930991043498068070026278743207815360775405991e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.16108610295171261719456067987917809570631253102226e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.30036178671543212233835078639075334195251996343038e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.43450668999084041907642885050924290452625964879284e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.56342024399270464500104119207015796843310537396767e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.80533718126241937910370331127088781990218118983044e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.02602325286877324498471186427925939079810622779565e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.22588056304767261354826003665099085710305382197378e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.40571195475001402595110042683273853427524358307944e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.56662511399665276754597478656326742781408980413322e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.70993905185659685565448300554224723067807322985204e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.83709874023713352349412076492620965428173444148145e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94960170345170829219212314700442993280391160852854e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.13654734084136746465035125437353362462933829757275e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.28189264735615590742276195878781243591679327317794e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.39515913242278478018768439779714070843560355510873e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.48402196440814952621386479637326968276812345206475e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.55442318496320967701382488549857555770760122499725e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.61084734701877707149966300776478121417665231438051e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.65663155064693568703121118975223647384842017610363e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.69424543788590485293997426765959588972608120887159e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.75181239051510561995724918481437181225561682663730e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.79330912859883809209439632732487322514831404016950e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.82433333964997258238374422700352745232108521574338e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.84823776850456273960749947374965581355459282720918e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.86712078422837181984231917376692653955733800370589e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.88234978933381804514525314568892574021644736001062e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(7.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.89484817977790488434819448808352507951600536883956e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(8)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.90525915297517643347206332876433307912297417265919e-1), tolerance); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.05754562114095147060025732340404110273918791128410e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.43368449353064312968788810247763526151579823896375e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.89152652981222928500336992235218785823347685619486e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.45576815036790322986175114501424442292398775002753e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.15978035591850473786135203626730317231876547935253e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04840867577215219812315602202859291564396444891271e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.18107352643844092577238041212187564083206726822056e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.63452659158632535349648745626466375370661702427253e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05039829654829170780787685299557006719608839147146e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.16290125976286647650587923507379034571826555851855e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.29006094814340314434551699445775276932192677014796e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43337488600334723245402521343673257218591019586678e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.59428804524998597404889957316726146572475641692056e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.77411943695232738645173996334900914289694617802622e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.97397674713122675501528813572074060920189377220435e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19466281873758062089629668872911218009781881016957e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.43657975600729535499895880792984203156689462603233e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56549331000915958092357114949075709547374035120716e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.69963821328456787766164921360924665804748003656962e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83891389704828738280543932012082190429368746897774e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.98318069008956501931929973721256792184639224594009e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13225883262651243874304479279543149837428487068880e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.28592804901375835801811223649103787689862120396348e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.44392772657854742558827130471487286937515502098876e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.60595773518728397925852903878144782668636743128847e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.77167990746831553875195022302050315427406387091454e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.94072018335986771952143399033763464047462959349960e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.11267140533666880513239944176560287064005137544504e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.28709673289702231328042170648699212093305785288837e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.46353362731996489993314637378816744341919505345430e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.64149834100915287958166424201293669944118353975980e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.82049083059559169016945833205795772857456974521089e-1), (tolerance) / 100); + CHECK_EQUAL(cdf(dist, static_cast(0)), static_cast(0.5)); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.17950916940440830983054166794204227142543025478911e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.35850165899084712041833575798706330055881646024020e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.53646637268003510006685362621183255658080494654570e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.71290326710297768671957829351300787906694214711163e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.88732859466333119486760055823439712935994862455496e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.05927981664013228047856600966236535952537040650040e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.22832009253168446124804977697949684572593612908546e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.39404226481271602074147096121855217331363256871153e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55607227342145257441172869528512713062484497901124e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.71407195098624164198188776350896212310137879603652e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.86774116737348756125695520720456850162571512931120e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.01681930991043498068070026278743207815360775405991e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.16108610295171261719456067987917809570631253102226e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.30036178671543212233835078639075334195251996343038e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.43450668999084041907642885050924290452625964879284e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.56342024399270464500104119207015796843310537396767e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.80533718126241937910370331127088781990218118983044e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.02602325286877324498471186427925939079810622779565e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.22588056304767261354826003665099085710305382197378e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.40571195475001402595110042683273853427524358307944e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.56662511399665276754597478656326742781408980413322e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.70993905185659685565448300554224723067807322985204e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.83709874023713352349412076492620965428173444148145e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94960170345170829219212314700442993280391160852854e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.13654734084136746465035125437353362462933829757275e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.28189264735615590742276195878781243591679327317794e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.39515913242278478018768439779714070843560355510873e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.48402196440814952621386479637326968276812345206475e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.55442318496320967701382488549857555770760122499725e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.61084734701877707149966300776478121417665231438051e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.65663155064693568703121118975223647384842017610363e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.69424543788590485293997426765959588972608120887159e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.75181239051510561995724918481437181225561682663730e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.79330912859883809209439632732487322514831404016950e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.82433333964997258238374422700352745232108521574338e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.84823776850456273960749947374965581355459282720918e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.86712078422837181984231917376692653955733800370589e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.88234978933381804514525314568892574021644736001062e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(7.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.89484817977790488434819448808352507951600536883956e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(8)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.90525915297517643347206332876433307912297417265919e-1), (tolerance) / 100); } template @@ -331,186 +328,186 @@ void do_test_holtsmark_ccdf() { holtsmark_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-2))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94960170345170829219212314700442993280391160852854e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.83709874023713352349412076492620965428173444148145e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.70993905185659685565448300554224723067807322985204e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.56662511399665276754597478656326742781408980413322e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.40571195475001402595110042683273853427524358307944e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.22588056304767261354826003665099085710305382197378e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.02602325286877324498471186427925939079810622779565e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.80533718126241937910370331127088781990218118983044e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.56342024399270464500104119207015796843310537396767e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.9375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.43450668999084041907642885050924290452625964879284e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.30036178671543212233835078639075334195251996343038e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.8125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.16108610295171261719456067987917809570631253102226e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.01681930991043498068070026278743207815360775405991e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.6875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.86774116737348756125695520720456850162571512931120e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.71407195098624164198188776350896212310137879603652e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.5625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55607227342145257441172869528512713062484497901124e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.39404226481271602074147096121855217331363256871153e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.22832009253168446124804977697949684572593612908546e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.05927981664013228047856600966236535952537040650040e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.88732859466333119486760055823439712935994862455496e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.71290326710297768671957829351300787906694214711163e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.53646637268003510006685362621183255658080494654570e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.35850165899084712041833575798706330055881646024020e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.0625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.17950916940440830983054166794204227142543025478911e-1), tolerance); - BOOST_CHECK_EQUAL(cdf(complement(dist, static_cast(0))), static_cast(0.5)); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.0625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.82049083059559169016945833205795772857456974521089e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.64149834100915287958166424201293669944118353975980e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.46353362731996489993314637378816744341919505345430e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.28709673289702231328042170648699212093305785288837e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.11267140533666880513239944176560287064005137544504e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.94072018335986771952143399033763464047462959349960e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.77167990746831553875195022302050315427406387091454e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.60595773518728397925852903878144782668636743128847e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.5625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.44392772657854742558827130471487286937515502098876e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.28592804901375835801811223649103787689862120396348e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.6875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13225883262651243874304479279543149837428487068880e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.98318069008956501931929973721256792184639224594009e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.8125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83891389704828738280543932012082190429368746897774e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.69963821328456787766164921360924665804748003656962e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.9375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56549331000915958092357114949075709547374035120716e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.43657975600729535499895880792984203156689462603233e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19466281873758062089629668872911218009781881016957e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.97397674713122675501528813572074060920189377220435e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.77411943695232738645173996334900914289694617802622e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.59428804524998597404889957316726146572475641692056e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43337488600334723245402521343673257218591019586678e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.29006094814340314434551699445775276932192677014796e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.16290125976286647650587923507379034571826555851855e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(2))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05039829654829170780787685299557006719608839147146e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(2.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.63452659158632535349648745626466375370661702427253e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(2.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.18107352643844092577238041212187564083206726822056e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(2.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04840867577215219812315602202859291564396444891271e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(3))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.15978035591850473786135203626730317231876547935253e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(3.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.45576815036790322986175114501424442292398775002753e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(3.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.89152652981222928500336992235218785823347685619486e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(3.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.43368449353064312968788810247763526151579823896375e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(4))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.05754562114095147060025732340404110273918791128410e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(4.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.48187609484894380042750815185628187744383173362701e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.06690871401161907905603672675126774851685959830498e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(5.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.75666660350027417616255772996472547678914784256620e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(6))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51762231495437260392500526250344186445407172790817e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(6.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.32879215771628180157680826233073460442661996294112e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(7))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.17650210666181954854746854311074259783552639989383e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(7.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05151820222095115651805511916474920483994631160437e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(8))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.47408470248235665279366712356669208770258273408139e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(9))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.84633233633455623701916449563937321750458546930453e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(10))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.63980919776847052871529866313101745651230650390958e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(11))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.71560271091813267790502831701953317735310509411390e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.98877952779840995427042841099634486251917561421235e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(13))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.40474538743684446341559852404247422921805516802754e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.92694975034713587589009244180464471384939103569360e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(15))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.53008216069181937774819568728358865566934398876406e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.19610991747326725339429696634365931201323237447865e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(18))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.66754697245984312281273324441306444625571550964874e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.27055303995134836245432119316955904009319977641407e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(22))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.96335385591609284864855802297989450933958012331026e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.71983068404058084817697571696065106175519154567134e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(26))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52289416073896095009461377823763903270627907120760e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36093802515022944719982175339249822123873546752029e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(30))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.22583027731897389283291308558313649709444449306352e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.11172037056341396583040940446061500559620114648017e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(36))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.30343276748924876383449972567328892540120922780153e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.93479451609843506274951848311637162210971363421001e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(44))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.87195324030611990483144403072151789810819131065125e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.02706331251660616582062908165140543120249377843861e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(52))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.34227281260431186934023112980425214646324423530835e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.77808682390572890160969127059116197868923042197157e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(60))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.30671561098656496307105837586195479010992455366704e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.90809577465797739887717333706777298095814323854594e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(72))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.27353325758395877256315285908308787899438871193344e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.79392283157821028307612118603031347679870090601645e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(88))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42100764912263851750335808792156725434230560510519e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.12427366298380215713674931256380175628765437052256e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(104))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.88357904993849478063900853297202135211787374336745e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.68514784935653217641685603828708555083243580835252e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(120))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51927236784831507287987712585213807190192778503378e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.37893523202524132194116984313653211252949573780743e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.87179879353850251536193247663317269917137569329013e-5), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(512))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.72200715673082274403568012456413425331659480927047e-5), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1024))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.08767256634253255597053159005214917567906016620942e-6), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 11))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15224951834965340756402503731619739933629215689572e-6), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.60926645137475638433041259135060814007792759468100e-7), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 13))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.69027136710097153757239920401079588116557633592788e-7), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.51153240121827639330112195094153363441740650435701e-8), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 15))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.36283287602527689849064009106938913094716520594050e-8), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.18894075854698171408179022464997418218329601220535e-8), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 17))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.20354010552543796231728241342645692784842686349965e-9), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 18))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.48617582449547816069323420820736862370145659607645e-9), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 19))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.25442497729649541267939242007563203416972765165476e-10), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.85771976129306035185873711236944017216967773980517e-10), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 21))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.56803119746276025902637885330726865801883592203156e-11), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 22))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.32214969859659307190062902673645385449168267230206e-11), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 23))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.21003899305378486738410997502574389330326609057126e-12), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.90268712277390815798081242324390081166198190434103e-12), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.02625487407274396069298698869802596448489279633645e-12), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 26))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.62835890339366126281650716118851052269284048205938e-13), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 27))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28281859258171445903392888079435183340041265714998e-13), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.53544862923055721373031196622890601888700626111182e-14), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 29))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.60352324072570315319362346398633880353985161880622e-14), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 30))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.66931078653639661641440656550426788294070266782671e-15), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 31))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.00440405090690395389846895694672344247801107283103e-15), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.08663848317021453602605776312368607691806298813143e-16), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 34))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.85829810396272422714320494875293186097734524880995e-17), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 36))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10728726299533984178525425523566315206520781873938e-17), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 38))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38410907874417469494912307476988489629927133322828e-18), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.73013634843021835192352185216943643167993641440545e-19), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 42))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.16267043553777293728520200407227686276581114275508e-20), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 44))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.70333804442221617119725245647479628568092558840977e-21), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 46))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.37917255552777021393262025049731570198920941773050e-22), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.22396569440971276740578385685661655637545268535833e-23), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 50))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.27995711801214095925566865602936005935821644314758e-24), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 52))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.59994639751517619906934188799897966230541134026964e-25), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 54))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.24993299689397024883663924561783076352358304956329e-26), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.03124162461174628110457931016502737959110130110786e-26), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 58))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28905203076468285138072404465359649544991622324619e-27), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 60))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61131503845585356422590504127751316165005771606733e-28), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 62))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.01414379806981695528238129932509731805283190086691e-29), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.51767974758727119410297662380140381412701796292469e-30), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 68))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.93387460560511124078590097461169759773383672872924e-32), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 72))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.14667907125798631372797027282887330061342582520339e-34), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 76))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.60418604884060361519995355129506804305208883665969e-36), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.50065407013134431487499274238985426822797191535889e-37), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 84))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.34477198458022549199217615998414729133523646527342e-39), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 88))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.66370622590660233123777524997523014264365635070860e-41), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 92))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.72454097797906614255902382808629709787906142136400e-43), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94459527809229084774847473138483921543599314796577e-45), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 100))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.39759301220192044496069917677888112741187383092503e-46), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 104))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18373908156550069525109246371700176158105285841693e-48), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 108))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.41209231494609483632983197455781525247039509121778e-50), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.33139424210327318176536246024658633198499233002634e-52), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 116))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.33030350328636434650837884413529114372655051566613e-54), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 120))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.30160992238849442914193419439613924120727351807283e-55), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 124))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.03376550373202254553427217874396756438636487198880e-57), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.17775859958128522739730027928744931935369511248250e-59), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.17775859958128522739730027928744931935369511248250e-59), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 136))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.75819970600899713720044013497912431482835720820923e-63), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 144))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.89409172509985281669932620482888777217489189653546e-66), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 152))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.62424737573206254076983936725802678753635716927602e-70), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 160))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12896664446583558124263656427197919617586844953028e-73), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 168))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.75626622184041889951815567449213670941374133186103e-77), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 176))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.72916558066508520390174725217806813821714192348884e-81), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 184))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.64286269059206181735882501273878616655691941491427e-84), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 192))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.01089524070327592128619387875680216444560404031804e-88), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 200))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.79222470874823222970262177430859903429102548905771e-92), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 208))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.39067986053423638420474164411831031110620739478948e-95), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 216))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.83662075325741304737485752958571853297413914743525e-99), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 224))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.42495623858823560726925232655901331371438944029181e-102), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 232))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.47889706686580958805969806288821609793552109446243e-106), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 240))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.49340104215285543959887222384818383285039329702741e-110), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 248))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.07358423880684947255831841402543550606699055103208e-113), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.06246152052453484511308206549178590348386364998067e-117), tolerance); - - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 600))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.35984768491636685338723260976696756010081951066709e-272), tolerance); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-2))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94960170345170829219212314700442993280391160852854e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.83709874023713352349412076492620965428173444148145e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.70993905185659685565448300554224723067807322985204e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.56662511399665276754597478656326742781408980413322e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.40571195475001402595110042683273853427524358307944e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.22588056304767261354826003665099085710305382197378e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.02602325286877324498471186427925939079810622779565e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.80533718126241937910370331127088781990218118983044e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.56342024399270464500104119207015796843310537396767e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.9375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.43450668999084041907642885050924290452625964879284e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.30036178671543212233835078639075334195251996343038e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.8125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.16108610295171261719456067987917809570631253102226e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.01681930991043498068070026278743207815360775405991e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.6875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.86774116737348756125695520720456850162571512931120e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.71407195098624164198188776350896212310137879603652e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.5625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55607227342145257441172869528512713062484497901124e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.39404226481271602074147096121855217331363256871153e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.22832009253168446124804977697949684572593612908546e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.05927981664013228047856600966236535952537040650040e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.88732859466333119486760055823439712935994862455496e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.71290326710297768671957829351300787906694214711163e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.53646637268003510006685362621183255658080494654570e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.35850165899084712041833575798706330055881646024020e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.0625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.17950916940440830983054166794204227142543025478911e-1), (tolerance) / 100); + CHECK_EQUAL(cdf(complement(dist, static_cast(0))), static_cast(0.5)); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.0625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.82049083059559169016945833205795772857456974521089e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.64149834100915287958166424201293669944118353975980e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.46353362731996489993314637378816744341919505345430e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.28709673289702231328042170648699212093305785288837e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.11267140533666880513239944176560287064005137544504e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.94072018335986771952143399033763464047462959349960e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.77167990746831553875195022302050315427406387091454e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.60595773518728397925852903878144782668636743128847e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.5625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.44392772657854742558827130471487286937515502098876e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.28592804901375835801811223649103787689862120396348e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.6875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13225883262651243874304479279543149837428487068880e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.98318069008956501931929973721256792184639224594009e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.8125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83891389704828738280543932012082190429368746897774e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.69963821328456787766164921360924665804748003656962e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.9375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56549331000915958092357114949075709547374035120716e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.43657975600729535499895880792984203156689462603233e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19466281873758062089629668872911218009781881016957e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.97397674713122675501528813572074060920189377220435e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.77411943695232738645173996334900914289694617802622e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.59428804524998597404889957316726146572475641692056e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43337488600334723245402521343673257218591019586678e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.29006094814340314434551699445775276932192677014796e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.16290125976286647650587923507379034571826555851855e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(2))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05039829654829170780787685299557006719608839147146e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(2.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.63452659158632535349648745626466375370661702427253e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(2.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.18107352643844092577238041212187564083206726822056e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(2.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04840867577215219812315602202859291564396444891271e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(3))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.15978035591850473786135203626730317231876547935253e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(3.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.45576815036790322986175114501424442292398775002753e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(3.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.89152652981222928500336992235218785823347685619486e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(3.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.43368449353064312968788810247763526151579823896375e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(4))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.05754562114095147060025732340404110273918791128410e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(4.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.48187609484894380042750815185628187744383173362701e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.06690871401161907905603672675126774851685959830498e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(5.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.75666660350027417616255772996472547678914784256620e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(6))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51762231495437260392500526250344186445407172790817e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(6.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.32879215771628180157680826233073460442661996294112e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(7))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.17650210666181954854746854311074259783552639989383e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(7.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05151820222095115651805511916474920483994631160437e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(8))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.47408470248235665279366712356669208770258273408139e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(9))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.84633233633455623701916449563937321750458546930453e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(10))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.63980919776847052871529866313101745651230650390958e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(11))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.71560271091813267790502831701953317735310509411390e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.98877952779840995427042841099634486251917561421235e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(13))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.40474538743684446341559852404247422921805516802754e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.92694975034713587589009244180464471384939103569360e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(15))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.53008216069181937774819568728358865566934398876406e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.19610991747326725339429696634365931201323237447865e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(18))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.66754697245984312281273324441306444625571550964874e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.27055303995134836245432119316955904009319977641407e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(22))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.96335385591609284864855802297989450933958012331026e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.71983068404058084817697571696065106175519154567134e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(26))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52289416073896095009461377823763903270627907120760e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36093802515022944719982175339249822123873546752029e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(30))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.22583027731897389283291308558313649709444449306352e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.11172037056341396583040940446061500559620114648017e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(36))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.30343276748924876383449972567328892540120922780153e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.93479451609843506274951848311637162210971363421001e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(44))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.87195324030611990483144403072151789810819131065125e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.02706331251660616582062908165140543120249377843861e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(52))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.34227281260431186934023112980425214646324423530835e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.77808682390572890160969127059116197868923042197157e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(60))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.30671561098656496307105837586195479010992455366704e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.90809577465797739887717333706777298095814323854594e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(72))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.27353325758395877256315285908308787899438871193344e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.79392283157821028307612118603031347679870090601645e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(88))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42100764912263851750335808792156725434230560510519e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.12427366298380215713674931256380175628765437052256e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(104))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.88357904993849478063900853297202135211787374336745e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.68514784935653217641685603828708555083243580835252e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(120))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51927236784831507287987712585213807190192778503378e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.37893523202524132194116984313653211252949573780743e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.87179879353850251536193247663317269917137569329013e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(512))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.72200715673082274403568012456413425331659480927047e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1024))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.08767256634253255597053159005214917567906016620942e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 11))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15224951834965340756402503731619739933629215689572e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.60926645137475638433041259135060814007792759468100e-7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 13))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.69027136710097153757239920401079588116557633592788e-7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.51153240121827639330112195094153363441740650435701e-8), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 15))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.36283287602527689849064009106938913094716520594050e-8), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.18894075854698171408179022464997418218329601220535e-8), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 17))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.20354010552543796231728241342645692784842686349965e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 18))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.48617582449547816069323420820736862370145659607645e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 19))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.25442497729649541267939242007563203416972765165476e-10), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.85771976129306035185873711236944017216967773980517e-10), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 21))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.56803119746276025902637885330726865801883592203156e-11), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 22))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.32214969859659307190062902673645385449168267230206e-11), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 23))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.21003899305378486738410997502574389330326609057126e-12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.90268712277390815798081242324390081166198190434103e-12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.02625487407274396069298698869802596448489279633645e-12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 26))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.62835890339366126281650716118851052269284048205938e-13), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 27))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28281859258171445903392888079435183340041265714998e-13), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.53544862923055721373031196622890601888700626111182e-14), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 29))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.60352324072570315319362346398633880353985161880622e-14), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 30))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.66931078653639661641440656550426788294070266782671e-15), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 31))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.00440405090690395389846895694672344247801107283103e-15), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.08663848317021453602605776312368607691806298813143e-16), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 34))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.85829810396272422714320494875293186097734524880995e-17), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 36))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10728726299533984178525425523566315206520781873938e-17), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 38))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38410907874417469494912307476988489629927133322828e-18), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.73013634843021835192352185216943643167993641440545e-19), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 42))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.16267043553777293728520200407227686276581114275508e-20), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 44))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.70333804442221617119725245647479628568092558840977e-21), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 46))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.37917255552777021393262025049731570198920941773050e-22), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.22396569440971276740578385685661655637545268535833e-23), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 50))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.27995711801214095925566865602936005935821644314758e-24), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 52))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.59994639751517619906934188799897966230541134026964e-25), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 54))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.24993299689397024883663924561783076352358304956329e-26), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.03124162461174628110457931016502737959110130110786e-26), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 58))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28905203076468285138072404465359649544991622324619e-27), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 60))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61131503845585356422590504127751316165005771606733e-28), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 62))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.01414379806981695528238129932509731805283190086691e-29), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.51767974758727119410297662380140381412701796292469e-30), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 68))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.93387460560511124078590097461169759773383672872924e-32), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 72))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.14667907125798631372797027282887330061342582520339e-34), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 76))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.60418604884060361519995355129506804305208883665969e-36), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.50065407013134431487499274238985426822797191535889e-37), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 84))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.34477198458022549199217615998414729133523646527342e-39), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 88))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.66370622590660233123777524997523014264365635070860e-41), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 92))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.72454097797906614255902382808629709787906142136400e-43), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94459527809229084774847473138483921543599314796577e-45), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 100))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.39759301220192044496069917677888112741187383092503e-46), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 104))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18373908156550069525109246371700176158105285841693e-48), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 108))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.41209231494609483632983197455781525247039509121778e-50), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.33139424210327318176536246024658633198499233002634e-52), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 116))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.33030350328636434650837884413529114372655051566613e-54), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 120))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.30160992238849442914193419439613924120727351807283e-55), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 124))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.03376550373202254553427217874396756438636487198880e-57), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.17775859958128522739730027928744931935369511248250e-59), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.17775859958128522739730027928744931935369511248250e-59), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 136))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.75819970600899713720044013497912431482835720820923e-63), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 144))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.89409172509985281669932620482888777217489189653546e-66), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 152))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.62424737573206254076983936725802678753635716927602e-70), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 160))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12896664446583558124263656427197919617586844953028e-73), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 168))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.75626622184041889951815567449213670941374133186103e-77), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 176))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.72916558066508520390174725217806813821714192348884e-81), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 184))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.64286269059206181735882501273878616655691941491427e-84), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 192))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.01089524070327592128619387875680216444560404031804e-88), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 200))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.79222470874823222970262177430859903429102548905771e-92), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 208))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.39067986053423638420474164411831031110620739478948e-95), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 216))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.83662075325741304737485752958571853297413914743525e-99), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 224))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.42495623858823560726925232655901331371438944029181e-102), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 232))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.47889706686580958805969806288821609793552109446243e-106), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 240))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.49340104215285543959887222384818383285039329702741e-110), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 248))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.07358423880684947255831841402543550606699055103208e-113), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.06246152052453484511308206549178590348386364998067e-117), (tolerance) / 100); + + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 600))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.35984768491636685338723260976696756010081951066709e-272), (tolerance) / 100); // The test is terminated because x is inf after this in fp64. if (N <= 53) { return; } - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 10000))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.07856314267954244808378917796336533616174400834444e-4517), tolerance); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 10000))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.07856314267954244808378917796336533616174400834444e-4517), (tolerance) / 100); } template @@ -526,149 +523,149 @@ void do_test_holtsmark_quantile_nearzero() { holtsmark_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.03125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.95154561868642736172727541497862573947423988108440e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.70076903638473389271107254016757513871156973570753e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.09375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.14334937403136202998120100318789158621074793095204e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.78777320599109327486003359289950832456660816353247e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.15625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.52359744792606448551215814625237535910408488746319e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.31030403921397562363480619469818801698833367088973e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.21875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.12887694529692805365864437467349833307816315605127e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, -9.68933181713583005208786313049614919507807226788256e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.28125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.24180933056718074475811972779037648260058221511975e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.90498457639035315478919560434827057700411821656397e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.34375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.65011034985136468564856594364133703131867596374603e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.45602574935161564367593993713685007358536186330925e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.40625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.30636223130194458226267853223267146033119688836326e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.18783126811804488668597304309230757418655445388316e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.46875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.08910089454817618171205461377219663239656206354005e-1), tolerance); - BOOST_CHECK_EQUAL(quantile(dist, static_cast(0.5)), static_cast(0)); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.50390625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.35942281074760935023421465350943213907657016740203e-2), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.5078125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.71903117534558589826852519194663375075753566669865e-2), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.51171875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.07901080568320221484687881885423066805647774437405e-2), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.515625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.43954773006081419776089446583406196027634755818438e-2), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.51953125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.80082845222988104915780076816665811376325257794804e-2), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.5234375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.16304011143799846843111212111260495740955724460844e-2), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.52734375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.52637064382003902226333974540096053392566128735022e-2), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.53125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08910089454817618171205461377219663239656206354005e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.53515625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.22571450376289000001278843371459783620761964026442e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.5390625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36249702341028008589045826702986410397012912904709e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.54296875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.49946773116932301309732751744953722231029126346486e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.546875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.63664606836100199300226165836560082654887238338208e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.55078125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.77405165765079089783419383641965337744707947259452e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.5546875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.91170432114732759551367174850419509782585472590891e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.55859375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.04962409893975946705863512977926741730110899605668e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18783126811804488668597304309230757418655445388316e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.56640625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.32634636232249536218129854873203382200612639970098e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.5703125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.46519019187105731139818680492599864661432850376167e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.57421875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.60438386451527503677057942069112096470660708202704e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.578125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.74394880687856404334281468719091417527159191461011e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.58203125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.88390678663337502806483517706706303095739191330472e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.5859375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.02427993547706435128366410334899635275725704584021e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.58984375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.16509077296982960387421259319514641259915543447926e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.59375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.30636223130194458226267853223267146033119688836326e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.59765625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.44811768106176498805637646337817923388445968601566e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.6015625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.59038095808060603000739360761949422570819209911788e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.60546875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.73317639143565086527888233910690716885943557654200e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.609375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.87652883269757340156275635385373789172745768932299e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.61328125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.02046368651559365036792703758158149784555601527522e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.6171875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.16500694263927667044145946879116606537710528519644e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.62109375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.31018520948359067342384024222999190532594772267877e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.45602574935161564367593993713685007358536186330925e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.62890625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.60255651543790720669175415204007861250418903243190e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.6328125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.74980619074494545171846930824082767773201407564280e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.63671875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.89780422905541754178666731200120149076546958331875e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.640625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.04658089811438846102378009478135229217539543328542e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.64453125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.19616732518780928821098759267869073306168616762584e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.6484375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.34659554517741239172052324381351337830662490680744e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.65234375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.49789855148697728320168560667825948269915149112198e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.65625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.65011034985136468564856594364133703131867596374603e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.66015625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.80326601535777269419392897717286438879602729753825e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.6640625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.95740175290855108336930680485963056005472680796594e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.66796875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.11255496139682430686772264889247897534154814090188e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.671875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.26876430189035334589546274389116075758343949758676e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.67578125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.42606977014577414303134971466049624688623181490963e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.6796875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.58451277380488310882288163359470075488686595989134e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.68359375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.74413621465733462219129425896964561569492923310844e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.90498457639035315478919560434827057700411821656397e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.69140625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.06710401828627699619029762829527775785025847826609e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.6953125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.23054247537343446268743874344186034038860806575417e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.69921875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.39534976558556849766533672421653104101284193327489e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.703125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.56157770454041251979362066603791706893576777672076e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.70703125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.72928022860981170501224651695596294779402544635284e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.7109375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.89851352702281826568041708053406482267060399077072e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.71484375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.06933618382042868991732981731903327683778049211437e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.71875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.24180933056718074475811972779037648260058221511975e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.72265625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.41599681082196095188647911444502703373377770261645e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.7265625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.59196535747955714353182241432999465132648793939716e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.73046875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.76978478421742214185140384463517803619244579498785e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.734375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94952819242075830879661206434669971092120406861116e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.73828125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.13127219511566873406119301005062170096048576202346e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.7421875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.31509715961740080067603245114697688184732500932588e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.74609375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.50108747080172235764142816696014524944397797022118e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.68933181713583005208786313049614919507807226788256e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.75390625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.87992350186512083533727177758662092012850600324604e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.7578125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.00729607820486228792863859054788768644744365249151e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.76171875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.02685472384747190194216544893563951741322238866541e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.765625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.04667921798768908218602656800798525125137666299761e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.76953125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.06678110853147091220341113291781102477507787382916e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.7734375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08717260890978562986849760571609969494354300822263e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.77734375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10786665132220733188524032283620543957825067010411e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.78125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12887694529692805365864437467349833307816315605127e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.78515625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.15021804221161134460394215947401773984635551400974e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.7890625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.17190540651154074066537741066806130017312231661434e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.79296875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.19395549446874295273954813640902172894636549828066e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.796875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21638584145104788446634880619086527181141939030279e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.80078125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.23921515881685008719278461299232510042094064507963e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.8046875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.26246344172387198181843263481470665031951188807903e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.80859375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28615208934364044613153187689263023500565577152964e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.31030403921397562363480619469818801698833367088973e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.81640625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.33494391774730388327762461486718746182135887404098e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.8203125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36009820925261741664314298719135880075160309673291e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.82421875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38579544623528308147561770378298998291069435447743e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.828125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41206642422644329402039008236727065491131379281346e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.83203125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43894444498096320102061428365633543440558564852878e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.8359375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.46646559259303986239248263261753112540493595538180e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.83984375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.49466904794112146248736006028509653369456653722975e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.84375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52359744792606448551215814625237535910408488746319e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.84765625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55329729725622722446696215102952397443200898053734e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.8515625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.58381944212178952767489242020964875845531372433107e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.85546875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61521961706725528436767664289542667668084392814972e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.859375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.64755907881888895242774154629775987069182281943649e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.86328125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.68090534388763421593277486421165006597881155937148e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.8671875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.71533305062559095290467926282068904086311880655794e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.87109375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.75092497130127405520149304919663885139873951807268e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.78777320599109327486003359289950832456660816353247e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.87890625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.82598059808698758538443295349421685195378444570311e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.8828125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.86566242157090907181680189290396765394233286379846e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.88671875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90694840369852884963353039612138690706293500611801e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.890625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.94998516446439884497123835171451955479771823102329e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.89453125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.99493917772297054805704471816059443529057908424094e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.8984375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.04200039028200656353168185848438653746136511354273e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.90234375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.09138667776446768039690693058064390661207192288310e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.90625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.14334937403136202998120100318789158621074793095204e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.91015625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19818019103302928413100774795456740418726081571239e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.9140625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25621995785515543565780905111478616154698242356459e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.91796875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.31786976613802108820384089261971867032207069978249e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.921875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.38360533647314959687029290315016585988822268727435e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.92578125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.45399575188877505107943151191453137828469465461499e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.9296875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.52972819582716132188558325053476431645151134471514e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.93359375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.61164107343000684767083444817632028828927968917161e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.70076903638473389271107254016757513871156973570753e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.94140625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.79840522818853957979403024307775647164832128717134e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.9453125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.90618896524175502682103322803168945370341377670787e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.94921875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.02623187745561328365781914812219941666139382669240e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.953125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.16130376436882129187002225210296787778679380216571e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.95703125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.31511403805596290718635028471440503099806209998330e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.9609375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.49275168669289561003117954123304779848451307206373e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.96484375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.70139933971958385705119882168933347231988022896107e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.96875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.95154561868642736172727541497862573947423988108440e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.97265625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.25916037511354144395537844168672288266598351274466e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.9765625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.64987772024289138285743520182808805983174934278635e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.98046875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.16779337095862086311250586064141028622224308218889e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.984375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.89632696959562976212621758577393939287586784169403e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.98828125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.01689760146742972661016754806402368873114241071209e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.9921875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.02446937207505244639190533898754565373763855739835e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.99609375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40479269149807902190125365288201718857308359786880e1), tolerance); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.03125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.95154561868642736172727541497862573947423988108440e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.70076903638473389271107254016757513871156973570753e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.09375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.14334937403136202998120100318789158621074793095204e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.78777320599109327486003359289950832456660816353247e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.15625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.52359744792606448551215814625237535910408488746319e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.31030403921397562363480619469818801698833367088973e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.21875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.12887694529692805365864437467349833307816315605127e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, -9.68933181713583005208786313049614919507807226788256e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.28125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.24180933056718074475811972779037648260058221511975e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.90498457639035315478919560434827057700411821656397e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.34375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.65011034985136468564856594364133703131867596374603e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.45602574935161564367593993713685007358536186330925e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.40625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.30636223130194458226267853223267146033119688836326e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.18783126811804488668597304309230757418655445388316e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.46875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.08910089454817618171205461377219663239656206354005e-1), (tolerance) / 100); + CHECK_EQUAL(quantile(dist, static_cast(0.5)), static_cast(0)); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.50390625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.35942281074760935023421465350943213907657016740203e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.5078125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.71903117534558589826852519194663375075753566669865e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.51171875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.07901080568320221484687881885423066805647774437405e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.515625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.43954773006081419776089446583406196027634755818438e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.51953125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.80082845222988104915780076816665811376325257794804e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.5234375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.16304011143799846843111212111260495740955724460844e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.52734375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.52637064382003902226333974540096053392566128735022e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.53125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08910089454817618171205461377219663239656206354005e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.53515625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.22571450376289000001278843371459783620761964026442e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.5390625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36249702341028008589045826702986410397012912904709e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.54296875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.49946773116932301309732751744953722231029126346486e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.546875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.63664606836100199300226165836560082654887238338208e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.55078125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.77405165765079089783419383641965337744707947259452e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.5546875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.91170432114732759551367174850419509782585472590891e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.55859375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.04962409893975946705863512977926741730110899605668e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18783126811804488668597304309230757418655445388316e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.56640625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.32634636232249536218129854873203382200612639970098e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.5703125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.46519019187105731139818680492599864661432850376167e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.57421875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.60438386451527503677057942069112096470660708202704e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.578125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.74394880687856404334281468719091417527159191461011e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.58203125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.88390678663337502806483517706706303095739191330472e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.5859375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.02427993547706435128366410334899635275725704584021e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.58984375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.16509077296982960387421259319514641259915543447926e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.59375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.30636223130194458226267853223267146033119688836326e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.59765625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.44811768106176498805637646337817923388445968601566e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.6015625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.59038095808060603000739360761949422570819209911788e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.60546875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.73317639143565086527888233910690716885943557654200e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.609375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.87652883269757340156275635385373789172745768932299e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.61328125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.02046368651559365036792703758158149784555601527522e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.6171875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.16500694263927667044145946879116606537710528519644e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.62109375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.31018520948359067342384024222999190532594772267877e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.45602574935161564367593993713685007358536186330925e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.62890625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.60255651543790720669175415204007861250418903243190e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.6328125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.74980619074494545171846930824082767773201407564280e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.63671875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.89780422905541754178666731200120149076546958331875e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.640625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.04658089811438846102378009478135229217539543328542e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.64453125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.19616732518780928821098759267869073306168616762584e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.6484375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.34659554517741239172052324381351337830662490680744e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.65234375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.49789855148697728320168560667825948269915149112198e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.65625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.65011034985136468564856594364133703131867596374603e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.66015625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.80326601535777269419392897717286438879602729753825e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.6640625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.95740175290855108336930680485963056005472680796594e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.66796875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.11255496139682430686772264889247897534154814090188e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.671875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.26876430189035334589546274389116075758343949758676e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.67578125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.42606977014577414303134971466049624688623181490963e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.6796875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.58451277380488310882288163359470075488686595989134e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.68359375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.74413621465733462219129425896964561569492923310844e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.90498457639035315478919560434827057700411821656397e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.69140625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.06710401828627699619029762829527775785025847826609e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.6953125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.23054247537343446268743874344186034038860806575417e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.69921875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.39534976558556849766533672421653104101284193327489e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.703125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.56157770454041251979362066603791706893576777672076e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.70703125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.72928022860981170501224651695596294779402544635284e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.7109375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.89851352702281826568041708053406482267060399077072e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.71484375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.06933618382042868991732981731903327683778049211437e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.71875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.24180933056718074475811972779037648260058221511975e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.72265625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.41599681082196095188647911444502703373377770261645e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.7265625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.59196535747955714353182241432999465132648793939716e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.73046875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.76978478421742214185140384463517803619244579498785e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.734375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94952819242075830879661206434669971092120406861116e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.73828125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.13127219511566873406119301005062170096048576202346e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.7421875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.31509715961740080067603245114697688184732500932588e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.74609375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.50108747080172235764142816696014524944397797022118e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.68933181713583005208786313049614919507807226788256e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.75390625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.87992350186512083533727177758662092012850600324604e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.7578125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.00729607820486228792863859054788768644744365249151e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.76171875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.02685472384747190194216544893563951741322238866541e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.765625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.04667921798768908218602656800798525125137666299761e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.76953125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.06678110853147091220341113291781102477507787382916e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.7734375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08717260890978562986849760571609969494354300822263e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.77734375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10786665132220733188524032283620543957825067010411e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.78125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12887694529692805365864437467349833307816315605127e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.78515625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.15021804221161134460394215947401773984635551400974e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.7890625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.17190540651154074066537741066806130017312231661434e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.79296875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.19395549446874295273954813640902172894636549828066e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.796875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21638584145104788446634880619086527181141939030279e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.80078125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.23921515881685008719278461299232510042094064507963e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.8046875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.26246344172387198181843263481470665031951188807903e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.80859375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28615208934364044613153187689263023500565577152964e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.31030403921397562363480619469818801698833367088973e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.81640625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.33494391774730388327762461486718746182135887404098e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.8203125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.36009820925261741664314298719135880075160309673291e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.82421875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38579544623528308147561770378298998291069435447743e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.828125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41206642422644329402039008236727065491131379281346e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.83203125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43894444498096320102061428365633543440558564852878e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.8359375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.46646559259303986239248263261753112540493595538180e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.83984375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.49466904794112146248736006028509653369456653722975e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.84375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52359744792606448551215814625237535910408488746319e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.84765625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55329729725622722446696215102952397443200898053734e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.8515625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.58381944212178952767489242020964875845531372433107e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.85546875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61521961706725528436767664289542667668084392814972e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.859375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.64755907881888895242774154629775987069182281943649e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.86328125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.68090534388763421593277486421165006597881155937148e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.8671875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.71533305062559095290467926282068904086311880655794e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.87109375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.75092497130127405520149304919663885139873951807268e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.78777320599109327486003359289950832456660816353247e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.87890625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.82598059808698758538443295349421685195378444570311e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.8828125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.86566242157090907181680189290396765394233286379846e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.88671875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90694840369852884963353039612138690706293500611801e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.890625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.94998516446439884497123835171451955479771823102329e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.89453125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.99493917772297054805704471816059443529057908424094e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.8984375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.04200039028200656353168185848438653746136511354273e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.90234375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.09138667776446768039690693058064390661207192288310e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.90625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.14334937403136202998120100318789158621074793095204e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.91015625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19818019103302928413100774795456740418726081571239e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.9140625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25621995785515543565780905111478616154698242356459e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.91796875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.31786976613802108820384089261971867032207069978249e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.921875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.38360533647314959687029290315016585988822268727435e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.92578125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.45399575188877505107943151191453137828469465461499e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.9296875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.52972819582716132188558325053476431645151134471514e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.93359375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.61164107343000684767083444817632028828927968917161e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.70076903638473389271107254016757513871156973570753e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.94140625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.79840522818853957979403024307775647164832128717134e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.9453125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.90618896524175502682103322803168945370341377670787e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.94921875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.02623187745561328365781914812219941666139382669240e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.953125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.16130376436882129187002225210296787778679380216571e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.95703125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.31511403805596290718635028471440503099806209998330e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.9609375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.49275168669289561003117954123304779848451307206373e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.96484375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.70139933971958385705119882168933347231988022896107e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.96875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.95154561868642736172727541497862573947423988108440e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.97265625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.25916037511354144395537844168672288266598351274466e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.9765625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.64987772024289138285743520182808805983174934278635e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.98046875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.16779337095862086311250586064141028622224308218889e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.984375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.89632696959562976212621758577393939287586784169403e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.98828125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.01689760146742972661016754806402368873114241071209e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.9921875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.02446937207505244639190533898754565373763855739835e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.99609375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40479269149807902190125365288201718857308359786880e1), (tolerance) / 100); } template @@ -684,40 +681,40 @@ void do_test_holtsmark_quantile_lower() { holtsmark_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -3)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.78777320599109327486003359289950832456660816353247e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -4)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.70076903638473389271107254016757513871156973570753e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -5)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.95154561868642736172727541497862573947423988108440e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -6)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.89632696959562976212621758577393939287586784169403e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -7)), BOOST_MATH_BIG_CONSTANT(RealType, N, -9.02446937207505244639190533898754565373763855739835e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -8)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.40479269149807902190125365288201718857308359786880e1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -10)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.48634712845212854436829850825868101882854019691874e1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -12)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.75100888665534247471443047755794084714498529274899e1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -14)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.20296704598194178128278789813687898595549252840676e2), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -16)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.54977454632239578277064855837334284482347724412824e2), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -20)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.52361836255645260708087122768062244544827526253646e3), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -24)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.23734752970824778029419146983721335265273533376700e4), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -28)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.42062670553125367339285994800008811139726501576815e5), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -32)), BOOST_MATH_BIG_CONSTANT(RealType, N, -9.02041713923935805934169232925253585383521252378005e5), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -40)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.63680429392084153704899843149763443252941653727485e7), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -48)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.46626761095577290791010108814328116732395911944180e9), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -56)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.91162056903107188819131273099660458893079363542047e10), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -64)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.38341606205240162091324729036756554251581053237655e12), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -80)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.87423965612020298589373786039770640757408383939246e15), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -96)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.29757143623897661671305188560924841842505858740001e18), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -112)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.02366940392761715971201478542352832996294475084257e22), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -128)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.66397326199025580692950800332626492430331068544172e25), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -160)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.39662661178492965217151228166250717006976010266469e31), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -192)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.16169688570203891305395889425358741905195655516409e38), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -224)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.06948889094299024072567114732250581789838857797378e44), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -256)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.11034458952573565292573972403491751744218292992004e50), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -256)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.11034458952573565292573972403491751744218292992004e50), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -320)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.66220760083199094068657639449976729910923748932480e63), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -384)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.95304965911372717286692649124348058110571556299024e76), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -448)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.75980725346824443030445016705237404631255977139835e89), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -512)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.92674940440883821350824836233864795634501852860731e102), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -640)), BOOST_MATH_BIG_CONSTANT(RealType, N, -9.39113744455748572074441450789762236967081046313794e127), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -768)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.57731878887639063343639480262468437174058078877170e153), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -896)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.23102338973254024994084948896750440849135610207358e179), tolerance); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -3)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.78777320599109327486003359289950832456660816353247e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -4)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.70076903638473389271107254016757513871156973570753e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -5)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.95154561868642736172727541497862573947423988108440e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -6)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.89632696959562976212621758577393939287586784169403e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -7)), BOOST_MATH_BIG_CONSTANT(RealType, N, -9.02446937207505244639190533898754565373763855739835e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -8)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.40479269149807902190125365288201718857308359786880e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -10)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.48634712845212854436829850825868101882854019691874e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -12)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.75100888665534247471443047755794084714498529274899e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -14)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.20296704598194178128278789813687898595549252840676e2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -16)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.54977454632239578277064855837334284482347724412824e2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -20)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.52361836255645260708087122768062244544827526253646e3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -24)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.23734752970824778029419146983721335265273533376700e4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -28)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.42062670553125367339285994800008811139726501576815e5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -32)), BOOST_MATH_BIG_CONSTANT(RealType, N, -9.02041713923935805934169232925253585383521252378005e5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -40)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.63680429392084153704899843149763443252941653727485e7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -48)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.46626761095577290791010108814328116732395911944180e9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -56)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.91162056903107188819131273099660458893079363542047e10), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -64)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.38341606205240162091324729036756554251581053237655e12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -80)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.87423965612020298589373786039770640757408383939246e15), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -96)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.29757143623897661671305188560924841842505858740001e18), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -112)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.02366940392761715971201478542352832996294475084257e22), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -128)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.66397326199025580692950800332626492430331068544172e25), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -160)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.39662661178492965217151228166250717006976010266469e31), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -192)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.16169688570203891305395889425358741905195655516409e38), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -224)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.06948889094299024072567114732250581789838857797378e44), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -256)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.11034458952573565292573972403491751744218292992004e50), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -256)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.11034458952573565292573972403491751744218292992004e50), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -320)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.66220760083199094068657639449976729910923748932480e63), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -384)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.95304965911372717286692649124348058110571556299024e76), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -448)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.75980725346824443030445016705237404631255977139835e89), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -512)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.92674940440883821350824836233864795634501852860731e102), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -640)), BOOST_MATH_BIG_CONSTANT(RealType, N, -9.39113744455748572074441450789762236967081046313794e127), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -768)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.57731878887639063343639480262468437174058078877170e153), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -896)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.23102338973254024994084948896750440849135610207358e179), (tolerance) / 100); } template @@ -733,17 +730,17 @@ void do_test_holtsmark_quantile_upper() { holtsmark_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -3))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.78777320599109327486003359289950832456660816353247e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -4))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.70076903638473389271107254016757513871156973570753e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.95154561868642736172727541497862573947423988108440e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -6))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.89632696959562976212621758577393939287586784169403e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -7))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.02446937207505244639190533898754565373763855739835e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -8))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40479269149807902190125365288201718857308359786880e1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -10))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.48634712845212854436829850825868101882854019691874e1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.75100888665534247471443047755794084714498529274899e1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.20296704598194178128278789813687898595549252840676e2), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.54977454632239578277064855837334284482347724412824e2), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.52361836255645260708087122768062244544827526253646e3), tolerance); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -3))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.78777320599109327486003359289950832456660816353247e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -4))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.70076903638473389271107254016757513871156973570753e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.95154561868642736172727541497862573947423988108440e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -6))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.89632696959562976212621758577393939287586784169403e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -7))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.02446937207505244639190533898754565373763855739835e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -8))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40479269149807902190125365288201718857308359786880e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -10))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.48634712845212854436829850825868101882854019691874e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.75100888665534247471443047755794084714498529274899e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.20296704598194178128278789813687898595549252840676e2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.54977454632239578277064855837334284482347724412824e2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.52361836255645260708087122768062244544827526253646e3), (tolerance) / 100); } template @@ -761,162 +758,216 @@ void do_test_holtsmark_locscale_param() { holtsmark_distribution dist_0_1(static_cast(0), static_cast(1)); holtsmark_distribution dist_1_3(static_cast(1), static_cast(3)); - BOOST_CHECK_CLOSE(entropy(dist_0_1), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.0694485051346244003155800384542166381), tolerance); - BOOST_CHECK_CLOSE(entropy(dist_1_3), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.0694485051346244003155800384542166381) + log(static_cast(3)), tolerance); + CHECK_RELATIVE_ERROR(entropy(dist_0_1), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.0694485051346244003155800384542166381), (tolerance) / 100); + CHECK_RELATIVE_ERROR(entropy(dist_1_3), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.0694485051346244003155800384542166381) + log(static_cast(3)), (tolerance) / 100); - BOOST_CHECK_EQUAL(median(dist_0_1), static_cast(0)); - BOOST_CHECK_EQUAL(median(dist_1_3), static_cast(1)); + CHECK_EQUAL(median(dist_0_1), static_cast(0)); + CHECK_EQUAL(median(dist_1_3), static_cast(1)); - BOOST_CHECK_EQUAL(mode(dist_0_1), static_cast(0)); - BOOST_CHECK_EQUAL(mode(dist_1_3), static_cast(1)); + CHECK_EQUAL(mode(dist_0_1), static_cast(0)); + CHECK_EQUAL(mode(dist_1_3), static_cast(1)); - BOOST_CHECK_EQUAL(mean(dist_0_1), static_cast(0)); - BOOST_CHECK_EQUAL(mean(dist_1_3), static_cast(1)); + CHECK_EQUAL(mean(dist_0_1), static_cast(0)); + CHECK_EQUAL(mean(dist_1_3), static_cast(1)); - BOOST_CHECK((boost::math::isinf)(variance(dist_0_1))); + CHECK_TRUE((boost::math::isinf)(variance(dist_0_1))); - BOOST_CHECK_CLOSE(pdf(dist_0_1, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02038159607840130388931544845552929991729709746772e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist_1_3, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.87352751452164445024482162286994868261727837966217e-1) / 3, tolerance); + CHECK_RELATIVE_ERROR(pdf(dist_0_1, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02038159607840130388931544845552929991729709746772e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist_1_3, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.87352751452164445024482162286994868261727837966217e-1) / 3, (tolerance) / 100); - BOOST_CHECK_CLOSE(cdf(dist_0_1, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94960170345170829219212314700442993280391160852854e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist_1_3, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94960170345170829219212314700442993280391160852854e-1), tolerance); + CHECK_RELATIVE_ERROR(cdf(dist_0_1, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94960170345170829219212314700442993280391160852854e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist_1_3, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.94960170345170829219212314700442993280391160852854e-1), (tolerance) / 100); - BOOST_CHECK_CLOSE(cdf(dist_0_1, quantile(dist_0_1, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), tolerance); - BOOST_CHECK_CLOSE(cdf(dist_1_3, quantile(dist_1_3, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), tolerance); + CHECK_RELATIVE_ERROR(cdf(dist_0_1, quantile(dist_0_1, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist_1_3, quantile(dist_1_3, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), (tolerance) / 100); - BOOST_CHECK_CLOSE(cdf(dist_0_1, quantile(dist_0_1, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), tolerance); - BOOST_CHECK_CLOSE(cdf(dist_1_3, quantile(dist_1_3, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), tolerance); + CHECK_RELATIVE_ERROR(cdf(dist_0_1, quantile(dist_0_1, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist_1_3, quantile(dist_1_3, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), (tolerance) / 100); } -BOOST_AUTO_TEST_CASE(holtsmark_pdf_fp64) +void holtsmark_pdf_fp64() { do_test_holtsmark_pdf(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(holtsmark_pdf_std64) +void holtsmark_pdf_std64() { do_test_holtsmark_pdf(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(holtsmark_pdf_fp128) +void holtsmark_pdf_fp128() { do_test_holtsmark_pdf(); } #endif -BOOST_AUTO_TEST_CASE(holtsmark_cdf_fp64) +void holtsmark_cdf_fp64() { do_test_holtsmark_cdf(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(holtsmark_cdf_std64) +void holtsmark_cdf_std64() { do_test_holtsmark_cdf(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(holtsmark_cdf_fp128) +void holtsmark_cdf_fp128() { do_test_holtsmark_cdf(); } #endif -BOOST_AUTO_TEST_CASE(holtsmark_ccdf_fp64) +void holtsmark_ccdf_fp64() { do_test_holtsmark_ccdf(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(holtsmark_ccdf_std64) +void holtsmark_ccdf_std64() { do_test_holtsmark_ccdf(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(holtsmark_ccdf_fp128) +void holtsmark_ccdf_fp128() { do_test_holtsmark_ccdf(); } #endif -BOOST_AUTO_TEST_CASE(holtsmark_quantile_nearzero_fp64) +void holtsmark_quantile_nearzero_fp64() { do_test_holtsmark_quantile_nearzero(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(holtsmark_quantile_nearzero_std64) +void holtsmark_quantile_nearzero_std64() { do_test_holtsmark_quantile_nearzero(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(holtsmark_quantile_nearzero_fp128) +void holtsmark_quantile_nearzero_fp128() { do_test_holtsmark_quantile_nearzero(); } #endif -BOOST_AUTO_TEST_CASE(holtsmark_quantile_lower_fp64) +void holtsmark_quantile_lower_fp64() { do_test_holtsmark_quantile_lower(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(holtsmark_quantile_lower_std64) +void holtsmark_quantile_lower_std64() { do_test_holtsmark_quantile_lower(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(holtsmark_quantile_lower_fp128) +void holtsmark_quantile_lower_fp128() { do_test_holtsmark_quantile_lower(); } #endif -BOOST_AUTO_TEST_CASE(holtsmark_quantile_upper_fp64) +void holtsmark_quantile_upper_fp64() { do_test_holtsmark_quantile_upper(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(holtsmark_quantile_upper_std64) +void holtsmark_quantile_upper_std64() { do_test_holtsmark_quantile_upper(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(holtsmark_quantile_upper_fp128) +void holtsmark_quantile_upper_fp128() { do_test_holtsmark_quantile_upper(); } #endif -BOOST_AUTO_TEST_CASE(holtsmark_locscale_fp64) +void holtsmark_locscale_fp64() { do_test_holtsmark_locscale_param(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(holtsmark_locscale_std64) +void holtsmark_locscale_std64() { do_test_holtsmark_locscale_param(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(holtsmark_locscale_fp128) +void holtsmark_locscale_fp128() { do_test_holtsmark_locscale_param(); } #endif + +int main() +{ + holtsmark_pdf_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + holtsmark_pdf_std64(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + holtsmark_pdf_fp128(); +#endif + holtsmark_cdf_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + holtsmark_cdf_std64(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + holtsmark_cdf_fp128(); +#endif + holtsmark_ccdf_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + holtsmark_ccdf_std64(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + holtsmark_ccdf_fp128(); +#endif + holtsmark_quantile_nearzero_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + holtsmark_quantile_nearzero_std64(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + holtsmark_quantile_nearzero_fp128(); +#endif + holtsmark_quantile_lower_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + holtsmark_quantile_lower_std64(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + holtsmark_quantile_lower_fp128(); +#endif + holtsmark_quantile_upper_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + holtsmark_quantile_upper_std64(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + holtsmark_quantile_upper_fp128(); +#endif + holtsmark_locscale_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + holtsmark_locscale_std64(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + holtsmark_locscale_fp128(); +#endif + return boost::math::test::report_errors(); +} diff --git a/test/test_hyperexponential_dist.cpp b/test/test_hyperexponential_dist.cpp index c7d3c9843b..d5ccaf18a8 100644 --- a/test/test_hyperexponential_dist.cpp +++ b/test/test_hyperexponential_dist.cpp @@ -242,6 +242,21 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(mean, RealT, test_types) BOOST_CHECK_CLOSE( boost::math::mean(dist), static_cast(1.0333333333333333333333333333333333L), tol ); } +BOOST_AUTO_TEST_CASE_TEMPLATE(entropy, RealT, test_types) +{ + // Reference values: -int f log(f) by mpmath quadrature at 60 digits; no closed form. + const RealT tol = 32 * boost::math::tools::epsilon(); + auto check = [&](std::vector probs, std::vector rates, RealT h) + { + boost::math::hyperexponential_distribution dist(probs, rates); + BOOST_CHECK_CLOSE_FRACTION( boost::math::entropy(dist), h, tol ); + }; + check({ RealT(0.25), RealT(0.75) }, { RealT(1), RealT(4) }, static_cast(0.109445936650126717767786548059487248397216076L)); + check({ RealT(0.5), RealT(0.5) }, { RealT(1), RealT(1000) }, static_cast(-1.77740270917310631903398987519165669943776624L)); + // A single exponential: 1 - log(rate). + check({ RealT(1) }, { RealT(2) }, static_cast(0.306852819440054690582767878541823431924499866L)); +} + BOOST_AUTO_TEST_CASE_TEMPLATE(variance, RealT, test_types) { const RealT tol = make_tolerance(); diff --git a/test/test_hypergeometric_dist.cpp b/test/test_hypergeometric_dist.cpp index 961e5394a6..5365178f92 100644 --- a/test/test_hypergeometric_dist.cpp +++ b/test/test_hypergeometric_dist.cpp @@ -18,6 +18,7 @@ #include #include +#include using std::cout; using std::endl; using std::setprecision; @@ -57,7 +58,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } @@ -69,7 +70,7 @@ void expected_results() largest_type = "(long\\s+)?double"; #endif #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if((boost::math::tools::digits() > boost::math::tools::digits()) + if(boost::math::policies::promote_double<>() && (boost::math::tools::digits() > boost::math::tools::digits()) && (boost::math::tools::digits() < 100)) { // @@ -491,20 +492,112 @@ void test_spots(RealType /*T*/, const char* type_name) BOOST_MATH_CHECK_THROW(d = boost::math::hypergeometric_distribution(501, 40, 500), std::domain_error); BOOST_MATH_CHECK_THROW(d = boost::math::hypergeometric_distribution(40, 501, 500), std::domain_error); + + // + // Integer x beyond the factorial table, where Loader's saddle-point method is used, with prime + // factorisation in the tails up to N = 104729. Values from mpmath at 60 digits. + // + struct large_case { unsigned x, r, n, N; long double pdf; RealType tol; }; + const large_case large_cases[] = { + { 600, 1500, 2000, 5000, 0.025126012323870050456659927618198748L, tolerance }, + { 700, 1500, 2000, 5000, 0.0000000000708147414413862429733772355814014052L, tolerance }, + { 24000, 60000, 80000, 200000, 0.0039735405018628404013758812090728637L, tolerance }, + { 24123, 60000, 80000, 200000, 0.00187568978055549884111723163694289891L, tolerance }, + { 23500, 60000, 80000, 200000, 0.000000016112756785169958209568753951147937L, 4 * tolerance }, + { 1200000, 3000000, 4000000, 10000000, 0.000561946220334811372962916024931211627L, tolerance }, + { 1203456, 3000000, 4000000, 10000000, 0.00000000402250531175235295684236178111301572L, 4 * tolerance }, + }; + for (auto const& c : large_cases) + { + boost::math::hypergeometric_distribution dist(c.r, c.n, c.N); + BOOST_CHECK_CLOSE(pdf(dist, c.x), static_cast(c.pdf), c.tol); + } + // At an end of the support the result must not underflow before it is complete (true value 1.466e-322). + if (std::numeric_limits::min_exponent10 < -320) + { + boost::math::hypergeometric_distribution dist(100000, 1065, 200000); + BOOST_CHECK(pdf(dist, 0u) > 0); + } + + // + // Non-integer x: the analytic continuation C(r, x) C(N - r, n - x) / C(N, n). + // Values from mpmath at 50 digits; the tolerance scales with the condition number + // |x d/dx ln pdf|, which is how much a rounding of x itself is amplified. + // + struct noninteger_case { const char* x; unsigned r, n, N; long double pdf, cond; }; + static const noninteger_case noninteger_cases[] = { + { "2.5", 7, 9, 20, 0.306765408837835280425772348087512074L, 1.27L }, + { "0.25", 7, 9, 20, 0.00923344250444341451195317576706156765L, 0.72L }, + { "6.75", 7, 9, 20, 0.00121681025252355074963724021736470271L, 24.4L }, + { "60.5", 200, 150, 500, 0.0788614625136665537116488597232431263L, 1.29L }, + { "45.125", 200, 150, 500, 0.000938770338227857359230205729668782774L, 27.4L }, + { "12000.5", 30000, 40000, 100000, 0.00561924531383347907377494860263026125L, 1.29L }, + }; + for (auto const& c : noninteger_cases) + { + boost::math::hypergeometric_distribution dist(c.r, c.n, c.N); + const RealType x = static_cast(std::strtold(c.x, nullptr)); + BOOST_CHECK_CLOSE(pdf(dist, x), static_cast(c.pdf), tolerance * static_cast(1 + c.cond)); + } + // Integer-valued x of any type takes the exact integer path. + boost::math::hypergeometric_distribution d2(200, 150, 500); + for (unsigned k = 0; k <= 150; k += 10) + { + BOOST_CHECK_EQUAL(pdf(d2, static_cast(k)), pdf(d2, static_cast(k))); + } + // The continuation is log-concave in x, so between integers away from the mode it is monotone. + BOOST_CHECK(pdf(d2, static_cast(40.5)) > pdf(d2, static_cast(40))); + BOOST_CHECK(pdf(d2, static_cast(40.5)) < pdf(d2, static_cast(41))); + BOOST_CHECK(pdf(d2, static_cast(80.5)) < pdf(d2, static_cast(80))); + BOOST_CHECK(pdf(d2, static_cast(80.5)) > pdf(d2, static_cast(81))); + // Counts too large for the type to hold exactly (here N > 2^24 for an unpromoted float): their + // differences must be formed exactly, or at the bottom of the support (7) a gamma argument hits a pole. + { + using no_promote = boost::math::policies::policy, boost::math::policies::promote_double>; + boost::math::hypergeometric_distribution big(30000001 - 3, 10, 30000001); + const RealType p = pdf(big, static_cast(7.5)); + BOOST_CHECK((boost::math::isfinite)(p) && (p >= 0)); + } + // Outside the support is still an error. + BOOST_MATH_CHECK_THROW(pdf(d2, static_cast(150.5)), std::domain_error); + BOOST_MATH_CHECK_THROW(pdf(d2, static_cast(-0.5)), std::domain_error); } +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](std::uint64_t a, std::uint64_t b, std::uint64_t c, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(boost::math::entropy(boost::math::hypergeometric_distribution(a, b, c)), h, tol); + }; + check(30, 40, 100, static_cast(2.23251995010132138603305010352835455335946637L)); + check(5, 10, 20, static_cast(1.41017899258903122865281944730670874143759777L)); + check(1, 1, 2, static_cast(0.693147180559945309417232121458176568075500134L)); + check(10, 1000, 1000000, static_cast(0.0560825642231663484256230658066717444208256013L)); + check(300000, 400000, 1000000, static_cast(6.83281224965225896648567487522138918484639344L)); + check(250000000, 333333333, 1000000000, static_cast(10.1915445366983499530007834277413067488348034L)); + BOOST_CHECK_EQUAL(boost::math::entropy(boost::math::hypergeometric_distribution(5, 5, 5)), RealType(0)); +} + BOOST_AUTO_TEST_CASE( test_main ) { expected_results(); // Basic sanity-check spot values. // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F, "float"); // Test float. OK at decdigits = 0 tolerance = 0.0001 % + test_entropy(0.0F); test_spots(0.0, "double"); // Test double. OK at decdigits 7, tolerance = 1e07 % + test_entropy(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L, "long double"); // Test long double. + test_entropy(0.0L); #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS test_spots(boost::math::concepts::real_concept(0), "real_concept"); // Test real_concept. + test_entropy(boost::math::concepts::real_concept(0)); #endif #else std::cout << "The long double tests have been disabled on this platform " diff --git a/test/hypot_test.cpp b/test/test_hypot.cpp similarity index 100% rename from test/hypot_test.cpp rename to test/test_hypot.cpp diff --git a/test/test_ibeta.cpp b/test/test_ibeta.cpp index 0059b46619..40c24ae0ba 100644 --- a/test/test_ibeta.cpp +++ b/test/test_ibeta.cpp @@ -60,7 +60,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } @@ -145,7 +145,11 @@ void expected_results() largest_type, // test type(s) "(?i).*large.*", // test data group ".*", 200000, 10000); // test function - if (std::numeric_limits::digits == 64) + // + // Unpromoted double gets the largest type rows: the worst large cases have cond 700 to 4e4 in a and b, + // except betac(34657.7, 103.4, 0.815) at 3700 eps (5x cond), whose result 1.6e-307 is next to underflow. + // + if (boost::math::policies::promote_double<>() && (std::numeric_limits::digits == 64)) { // 80-bit long double, errors spill over: add_expected_result( @@ -235,7 +239,7 @@ void expected_results() "(?i).*small.*", // test data group ".*", 130, 30); // test function // - // MinGW: + // MinGW (real_concept is its 80-bit long double, whose libm is less accurate; measured 704 and mean 52): // add_expected_result( "GNU[^|]*", // compiler @@ -243,14 +247,15 @@ void expected_results() "Win32[^|]*", // platform "real_concept", // test type(s) "(?i).*medium.*", // test data group - ".*", 400, 50); // test function - add_expected_result( - "GNU.*", // compiler - ".*", // stdlib - "Win32.*", // platform - "double", // test type(s) - "(?i).*large.*", // test data group - ".*", 20, 10); // test function + ".*", 800, 60); // test function + if (boost::math::policies::promote_double<>()) + add_expected_result( + "GNU.*", // compiler + ".*", // stdlib + "Win32.*", // platform + "double", // test type(s) + "(?i).*large.*", // test data group + ".*", 20, 10); // test function add_expected_result( "GNU.*", // compiler ".*", // stdlib @@ -268,13 +273,14 @@ void expected_results() "real_concept", // test type(s) "(?i).*medium.*", // test data group ".*", 400, 50); // test function - add_expected_result( - "GNU.*", // compiler - ".*", // stdlib - "Cygwin*", // platform - "double", // test type(s) - "(?i).*large.*", // test data group - ".*", 20, 10); // test function + if (boost::math::policies::promote_double<>()) + add_expected_result( + "GNU.*", // compiler + ".*", // stdlib + "Cygwin*", // platform + "double", // test type(s) + "(?i).*large.*", // test data group + ".*", 20, 10); // test function add_expected_result( "GNU.*", // compiler ".*", // stdlib diff --git a/test/test_ibeta.hpp b/test/test_ibeta.hpp index 13ff157f9d..98e34bcfc2 100644 --- a/test/test_ibeta.hpp +++ b/test/test_ibeta.hpp @@ -406,6 +406,28 @@ void test_spots(T, const char* name) static_cast(0.825L)), static_cast(0.996883849270604867987018345952777458206564642094991979259788L), tolerance); + // + // https://github.com/boostorg/math/issues/1523 + // Integer a and b < 40 use a finite sum of binomial terms, the first of which underflowed (or was + // denormal and had lost most of its digits) when the result is still a normal number. + // Reference values calculated with Arb. + // + if((std::numeric_limits::digits == 53) && (std::numeric_limits::max_exponent == 1024)) + { + BOOST_CHECK_CLOSE( + ::boost::math::ibeta(static_cast(355), static_cast(30), static_cast(0.125)), + static_cast(1.796632735766621150661223125033790309249801096395e-279L), tolerance * 2); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta(static_cast(360), static_cast(30), static_cast(0.125)), + static_cast(8.092463621017578599073247171071767737149917413962e-284L), tolerance * 2); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta(static_cast(365), static_cast(30), static_cast(0.125)), + static_cast(3.626281949877933614152039221277820028263770136555e-288L), tolerance * 2); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta(static_cast(350), static_cast(20), static_cast(0.125)), + static_cast(2.012450499868551870681489937548499305656442752329e-286L), tolerance * 2); + } + // // Bug cases from Rocco Romeo: // @@ -516,7 +538,83 @@ void test_spots(T, const char* name) BOOST_CHECK_MESSAGE(boost::math::ibeta(a, b, x - delta[j]) > boost::math::ibeta(a, b, x - delta[j+1]), "ibeta not monotonically increasing below a/(a+b) for ibeta(" << a << ", " << b << ", " << x << ") and delta=" << delta[j] << ": [" << boost::math::ibeta(a, b, x - delta[j]) << " >= " << boost::math::ibeta(a, b, x - delta[j+1]) << "]"); } + // Without a Lanczos approximation, the power terms here once came out 12x too small. The density is ~1e8, + // so the rounding of x and the continued fraction leave ~1e-8 of error. Arb, with x = a / (a + b) + 1e-11 in double: + BOOST_CHECK_CLOSE_FRACTION(boost::math::ibeta(a, b, T(x + delta[5])), static_cast(0.50112741311964152717889063178639807L), T(1e-7)); } } + // + // Integer a and b, one of them large, x beyond a/(a+b). The finite binomial + // sum used here started from pow(x, n) with x = 1 - y close to 1, which + // multiplied the rounding error in x by n. The low bit in x makes 1 - x + // inexact for double and long double (for float it is simply lost, which + // changes the result by far less than the tolerance). + // Reference values are from the finite sum in exact decimal arithmetic. + // + T x_int = ldexp(static_cast(1), -28) + ldexp(static_cast(1), -68); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta(static_cast(2), static_cast(1.0e9L), x_int), + static_cast(0.886091673490414896866866835148507163568245289L), tolerance); + BOOST_CHECK_CLOSE( + ::boost::math::ibetac(static_cast(2), static_cast(1.0e9L), x_int), + static_cast(0.113908326509585103133133164851492836431754711L), tolerance); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta(static_cast(3), static_cast(1.0e9L), x_int), + static_cast(0.718821994107927404618541727411257158457373858L), tolerance); + BOOST_CHECK_CLOSE( + ::boost::math::ibetac(static_cast(3), static_cast(1.0e9L), x_int), + static_cast(0.281178005892072595381458272588742841542626142L), tolerance); + // + // Large a and b near the mode. The bases of the exponents in the power terms + // (x^a)(y^b)/B(a, b) were formed from x b - y a, with y = 1 - x rounded, which + // lost about eps max(a, b) min(x, y): these were off by 300 and 140 epsilon, + // and by up to 1e-11 where the compiler contracts x b - y a into an fma. + // The generic (non-Lanczos) code used by real_concept is far less accurate here. + // + T tolerance_large = tolerance * (boost::is_floating_point::value ? 1 : 100000000); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta(static_cast(1.0e5L), static_cast(2.5e7L), static_cast(4158) / 1048576), + static_cast(0.06845490339638190702573107740432918859230714009L), tolerance_large); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta(static_cast(3.0e4L), static_cast(1.0e7L), static_cast(3119) / 1048576), + static_cast(0.1690982393949004438961071516113973441276481773L), tolerance_large); + // + // Near the mean with b < 40, where sidestepping to the series lost up to 250 eps. + // Reference value from a 100-digit evaluation, doubles only: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + typedef boost::math::policies::policy > no_promote; + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta(T(124.93519797258834), T(35.625649490623374), T(0.74635077170289033), no_promote()), static_cast(0.1654537324451929478298745553715453707115L), boost::math::tools::epsilon() * 8); + } + // + // The series for the complement started from -1 and rounded each term onto the coarse grid of that running + // sum, which lost 5-10 eps for a, b < 1; and for a <= 15 near the mean the sidestep to a series (b < 40), and the + // forward evaluation of the continued fraction (b >= 40), lost as much. The prefix error of that series is + // multiplied by S / (1 - S) in 1 - S, 5-15 eps for S > 1/2. Reference values from Arb, doubles only: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + typedef boost::math::policies::policy > no_promote; + // Measured: at most 2.8 eps with contraction (-ffp-contract=on or fast), 3.03 eps without (x86 CI): + T tolerance = boost::math::tools::epsilon() * 4; + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta(T(0.06487), T(0.1276), T(0.3528), no_promote()), static_cast(0.641466056762343904103825L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta(T(0.3301), T(0.16), T(0.3677), no_promote()), static_cast(0.27439745512337435015174L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(2.207), T(13.56), T(0.1469), no_promote()), static_cast(0.400192942359675404658327L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta(T(1.974), T(32.96), T(0.05104), no_promote()), static_cast(0.530751012427838743979204L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(1.974), T(32.96), T(0.05104), no_promote()), static_cast(0.469248987572161256020796L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(1.728), T(10.6), T(0.1423), no_promote()), static_cast(0.412692486775009981483788L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(1.221), T(296.3), T(0.004113), no_promote()), static_cast(0.379883178660505860442496L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta(T(1.221), T(296.3), T(0.004113), no_promote()), static_cast(0.620116821339494139557504L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(1.081), T(225.2), T(0.004949), no_promote()), static_cast(0.360005149325214614768655L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(1.241), T(116.3), T(0.0108), no_promote()), static_cast(0.373352830867477269482944L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(1.435), T(377.2), T(0.003875), no_promote()), static_cast(0.379795123779314547118388L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(1.249), T(248.3), T(0.005199), no_promote()), static_cast(0.366349117098876110163662L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(0.02942), T(0.2289), T(0.0253), no_promote()), static_cast(0.196810945256536317102582L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(0.08087), T(0.06533), T(0.6775), no_promote()), static_cast(0.529113561442567211501508L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta(T(0.7857), T(0.0817), T(0.7627), no_promote()), static_cast(0.13545630774913902473231L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta(T(0.9848), T(0.1066), T(0.6446), no_promote()), static_cast(0.106135652852894343731671L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(0.06833), T(0.7126), T(0.2048), no_promote()), static_cast(0.133607615095624763603441L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac(T(0.05328), T(0.5656), T(0.08573), no_promote()), static_cast(0.168174045733948386362056L), tolerance); + } } - diff --git a/test/test_ibeta_derivative.cpp b/test/test_ibeta_derivative.cpp index ae968b106f..65ed312d6e 100644 --- a/test/test_ibeta_derivative.cpp +++ b/test/test_ibeta_derivative.cpp @@ -48,7 +48,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } diff --git a/test/test_ibeta_derivative.hpp b/test/test_ibeta_derivative.hpp index 9bb4ced4ce..d3fce9e22d 100644 --- a/test/test_ibeta_derivative.hpp +++ b/test/test_ibeta_derivative.hpp @@ -174,5 +174,23 @@ void test_spots(T) BOOST_CHECK_THROW(boost::math::ibeta_derivative(T(-1), T(2), T(0.5)), std::domain_error); BOOST_CHECK_THROW(boost::math::ibeta_derivative(T(1), T(0), T(0.5)), std::domain_error); BOOST_CHECK_THROW(boost::math::ibeta_derivative(T(1), T(-1), T(0.5)), std::domain_error); + // + // The leading terms x^a y^b / beta(a, b) lost up to 9 eps near the mean to the rounding of the first term of + // the exponent, which is about -g. Reference values from Arb, doubles only: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + typedef boost::math::policies::policy > no_promote; + // Measured: at most 2.2 eps with contraction (-ffp-contract=on or fast), 3.004 eps without (x86 CI): + T tolerance = boost::math::tools::epsilon() * 4; + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_derivative(T(13.75), T(132.2), T(0.09503), no_promote()), static_cast(16.2620218649512813145L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_derivative(T(10.09), T(26.7), T(0.2817), no_promote()), static_cast(5.26015522153723928254L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_derivative(T(21.98), T(41.93), T(0.3487), no_promote()), static_cast(6.61952926053123374081L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_derivative(T(15.21), T(30.7), T(0.3279), no_promote()), static_cast(5.72958483402182718067L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_derivative(T(56.2), T(52.75), T(0.5072), no_promote()), static_cast(8.17282632294558333472L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_derivative(T(782), T(13.67), T(0.9832), no_promote()), static_cast(87.6857498074179632276L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_derivative(T(23.37), T(12.38), T(0.6454), no_promote()), static_cast(4.89312563681850804428L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_derivative(T(27.93), T(12.74), T(0.6779), no_promote()), static_cast(5.32487717695550616177L), tolerance); + } } diff --git a/test/test_ibeta_inv.cpp b/test/test_ibeta_inv.cpp index 63a24e8db7..d55ec39088 100644 --- a/test/test_ibeta_inv.cpp +++ b/test/test_ibeta_inv.cpp @@ -71,7 +71,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } @@ -91,6 +91,8 @@ void expected_results() // if(std::numeric_limits::digits == 64) { + if(boost::math::policies::promote_double<>()) + { add_expected_result( ".*", // compiler ".*", // stdlib @@ -98,6 +100,7 @@ void expected_results() "double", // test type(s) ".*", // test data group ".*", 20, 10); // test function + } add_expected_result( ".*", // compiler ".*", // stdlib @@ -119,13 +122,16 @@ void expected_results() // Extended exponent range of long double // causes more extreme test cases to be executed: // - add_expected_result( - "GNU.*", // compiler - ".*", // stdlib - "Win32.*", // platform - "double", // test type(s) - ".*", // test data group - ".*", 10, 10); // test function + // Unpromoted double gets the largest type row: ibeta_inv(2.96e-4, 0.318, 0.815) = 1.9e-300 is off by + // 8600 eps, with cond 3400 in p and 700 in a. + if (boost::math::policies::promote_double<>()) + add_expected_result( + "GNU.*", // compiler + ".*", // stdlib + "Win32.*", // platform + "double", // test type(s) + ".*", // test data group + ".*", 10, 10); // test function add_expected_result( "GNU.*", // compiler ".*", // stdlib diff --git a/test/test_ibeta_inv.hpp b/test/test_ibeta_inv.hpp index 8be95b7413..9a4116e056 100644 --- a/test/test_ibeta_inv.hpp +++ b/test/test_ibeta_inv.hpp @@ -329,5 +329,167 @@ void test_spots(T) static_cast(1.0e13L), static_cast(0.995L)), static_cast(0.0099010703473402885173268397418009652L), 5e-10); + // + // min(a, b) == 1000 exactly used to fall between two strict comparisons + // when selecting the initial guess, so that no guess was set at all: + // https://github.com/boostorg/math/issues/1511 + // + // The generic (non-Lanczos) code used by real_concept is far less + // accurate for arguments this large, whatever the value of min(a, b), + // so only the built-in floating point types get the usual tolerance: + // + T tolerance_1511 = tolerance * (boost::is_floating_point::value ? 1 : 100000000); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv( + static_cast(1000), + static_cast(1.0e9L), + static_cast(0.025L)), + static_cast(9.389721085563963404180136990833102726849528911e-7L), tolerance_1511); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv( + static_cast(1.0e9L), + static_cast(1000), + static_cast(0.975L)), + static_cast(0.999999061027891443603659581986300916689727315L), tolerance_1511); + BOOST_CHECK_CLOSE( + ::boost::math::ibetac_inv( + static_cast(1000), + static_cast(1.0e9L), + static_cast(0.975L)), + static_cast(9.389721085563963404180136990833102726849528911e-7L), tolerance_1511); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv( + static_cast(1000), + static_cast(1.0e9L), + static_cast(0.5L)), + static_cast(9.996656874277116690802174656563429711990058656e-7L), tolerance_1511); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv( + static_cast(1000), + static_cast(2.0e7L), + static_cast(0.025L)), + static_cast(4.694637640096960118983038721439854358366856456e-5L), tolerance_1511); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv( + static_cast(1000), + static_cast(1.0e12L), + static_cast(0.025L)), + static_cast(9.389730174978430291685459639013695242587542550e-10L), tolerance_1511); + // + // The same case with promotion to a wider type switched off, so that it is + // exercised in the working precision on every platform: with promotion to + // an 80-bit long double the iteration could recover from the missing guess. + // + { + boost::math::policies::policy, boost::math::policies::promote_double > no_promotion; + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(1000), static_cast(1.0e9L), static_cast(0.025L), no_promotion), + static_cast(9.389721085563963404180136990833102726849528911e-7L), tolerance_1511); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(1.0e9L), static_cast(1000), static_cast(0.975L), no_promotion), + static_cast(0.999999061027891443603659581986300916689727315L), tolerance_1511); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(1000), static_cast(2.0e7L), static_cast(0.025L), no_promotion), + static_cast(4.694637640096960118983038721439854358366856456e-5L), tolerance_1511); + } + // + // For large a and b, the power terms (x^a)(y^b)/B(a, b) in ibeta lost about + // eps max(a, b) min(x, y) in the bases of the exponents. Where the compiler + // contracts x b - y a into an fma, that was a relative error of 1e-11 here, + // and the inverse converged to the root of the inaccurate function: + // + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(1.0e5L), static_cast(1.0e7L), static_cast(0.5L)), + static_cast(0.009900957749257592174244117422247546495548854468L), tolerance_1511); + { + boost::math::policies::policy, boost::math::policies::promote_double > no_promotion; + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(1.0e5L), static_cast(1.0e7L), static_cast(0.5L), no_promotion), + static_cast(0.009900957749257592174244117422247546495548854468L), tolerance_1511); + } + // + // The second derivative handed to the root finder had the wrong sign + // whenever the target was p rather than q. Check it against cases with + // simple closed forms: I_x(2, 1) = x^2 and I_x(2, 3) = 6x^2 - 8x^3 + 3x^4. + // + { + typedef boost::math::policies::policy<> pol_type; + boost::math::detail::ibeta_roots r1(static_cast(2), static_cast(1), static_cast(0.5), false); + boost::math::detail::ibeta_roots r1c(static_cast(2), static_cast(1), static_cast(0.5), true); + BOOST_CHECK_CLOSE(boost::math::get<1>(r1(static_cast(0.25))), static_cast(0.5), tolerance); + BOOST_CHECK_CLOSE(boost::math::get<2>(r1(static_cast(0.25))), static_cast(2), tolerance); + BOOST_CHECK_CLOSE(boost::math::get<1>(r1c(static_cast(0.25))), static_cast(-0.5), tolerance); + BOOST_CHECK_CLOSE(boost::math::get<2>(r1c(static_cast(0.25))), static_cast(-2), tolerance); + boost::math::detail::ibeta_roots r2(static_cast(2), static_cast(3), static_cast(0.5), false); + boost::math::detail::ibeta_roots r2c(static_cast(2), static_cast(3), static_cast(0.5), true); + BOOST_CHECK_CLOSE(boost::math::get<1>(r2(static_cast(0.25))), static_cast(1.6875), tolerance); + BOOST_CHECK_CLOSE(boost::math::get<2>(r2(static_cast(0.25))), static_cast(2.25), tolerance); + BOOST_CHECK_CLOSE(boost::math::get<1>(r2c(static_cast(0.25))), static_cast(-1.6875), tolerance); + BOOST_CHECK_CLOSE(boost::math::get<2>(r2c(static_cast(0.25))), static_cast(-2.25), tolerance); + } + // + // With that sign wrong, Halley iteration was only second order, which left + // errors of tens to hundreds of ulps for large a and b whenever the evaluation + // was not promoted to a wider type. These points were among the worst: + // + if (std::numeric_limits::is_specialized && (std::numeric_limits::digits == std::numeric_limits::digits)) + { + boost::math::policies::policy > no_promotion; + T tol = boost::math::tools::epsilon() * 2000; // 20 eps as a percentage + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(2000), static_cast(1.0e9), static_cast(0.006940925861941986), no_promotion), + static_cast(1.891653812057568512817838421240351406e-06L), tol); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(1000), static_cast(1.0e9), static_cast(0.006940925861941986), no_promotion), + static_cast(9.238836420371353708007156030941301367e-07L), tol); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(40), static_cast(80), static_cast(0.05189222238401044), no_promotion), + static_cast(2.651352194946371952577010439645915240e-01L), tol); + } + // + // Far out in the lower tail the asymptotic starting guesses are poor, and + // the iteration could run out of steps before reaching the root. The start + // now comes from the power series there. Reference values are from the + // finite sum for integer a in exact decimal arithmetic. + // + if (std::numeric_limits::is_specialized && (std::numeric_limits::min_exponent10 < -260)) + { + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(2), static_cast(4), static_cast(1e-100L)), + static_cast(3.1622776601683793319988935444327185337196e-51L), tolerance); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(3), static_cast(3), static_cast(1e-200L)), + static_cast(1.0e-67L), tolerance); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(10), static_cast(10000), static_cast(1e-250L)), + static_cast(4.5266918634202858901451019656158915843844e-29L), tolerance); + BOOST_CHECK_CLOSE( + ::boost::math::ibeta_inv(static_cast(5), static_cast(1.0e6L), static_cast(1e-150L)), + static_cast(2.6051658743682083165731837839652844149311e-36L), tolerance); + BOOST_CHECK_EQUAL( + ::boost::math::ibetac_inv(static_cast(4), static_cast(2), static_cast(1e-100L)), + static_cast(1)); + } + // + // a == b and p == 1/2: the root is exactly the inflection point, which was also the upper + // bound of the search, and the root finder only crept up on it, to ~sqrt(eps). For real_concept ibeta itself + // is ~7 eps out at x = 1/2, which the inverse divides by the density there; with a 113-bit long double + // (aarch64 Linux) real_concept's inverse at a = b = 1.0002 was measured 109 eps out: + // + T inflection_tolerance = (std::is_same::value ? (boost::math::tools::digits() > 64 ? 160 : 64) : 8) * boost::math::tools::epsilon(); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_inv(T(1.0002383038393605L), T(1.0002383038393605L), T(0.5)), T(0.5), inflection_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_inv(T(0.36209832717702123L), T(0.36209832717702123L), T(0.5)), T(0.5), inflection_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_inv(T(2.495355969835936L), T(2.495355969835936L), T(0.5)), T(0.5), inflection_tolerance); + // + // Near the mean ibeta used to sidestep to a series that lost up to 250 eps, which the inverses inherited. + // Reference values from a 100-digit evaluation, doubles only: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + typedef boost::math::policies::policy > no_promote; + T fine_tolerance = boost::math::tools::epsilon() * 4; + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_inv(T(26.915348039269173), T(31.260793671239576), T(0.5), no_promote()), static_cast(0.462221785758236606742689160666476137835L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibetac_inv(T(30.902954325135934), T(305.49211132155142), T(0.025), no_promote()), static_cast(0.1248965682964306624656343882252054888054L), fine_tolerance); + } } diff --git a/test/test_ibeta_inv_ab.cpp b/test/test_ibeta_inv_ab.cpp index 9efb0cc603..098e248061 100644 --- a/test/test_ibeta_inv_ab.cpp +++ b/test/test_ibeta_inv_ab.cpp @@ -57,7 +57,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_ibeta_inv_ab.hpp b/test/test_ibeta_inv_ab.hpp index b91ab5261d..49800f7f1f 100644 --- a/test/test_ibeta_inv_ab.hpp +++ b/test/test_ibeta_inv_ab.hpp @@ -237,5 +237,19 @@ void test_beta(T, const char* name) BOOST_MATH_CHECK_THROW(::boost::math::ibeta_invb(static_cast(2.125), static_cast(1.125), static_cast(-n)), std::domain_error); } + // + // ibeta and ibetac for a, b < 1 were up to 10 eps out, which the inverses inherited, divided by the sensitivity of + // the function to the parameter: 24 eps for the first of these. Reference values from Arb, doubles only: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + typedef boost::math::policies::policy > no_promote; + // The forward functions are still a few eps out here, more with gcc's default -ffp-contract=fast, and the inverses + // divide that by their sensitivity to the parameter: + T tolerance = boost::math::tools::epsilon() * 10; + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_invb(T(0.10797751623277096), T(0.65150235550348956), T(0.5), no_promote()), static_cast(0.096646123284035831240382L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_invb(T(0.09555), T(0.05486), T(0.6881), no_promote()), static_cast(0.555050462429118307720304L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::ibeta_inva(T(0.04377), T(0.6669), T(0.3244), no_promote()), static_cast(0.0991673416391090870153045L), tolerance); + } } diff --git a/test/test_igamma.cpp b/test/test_igamma.cpp index b113eb064c..df838159d1 100644 --- a/test/test_igamma.cpp +++ b/test/test_igamma.cpp @@ -51,7 +51,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_igamma.hpp b/test/test_igamma.hpp index 74256fed25..a43752741c 100644 --- a/test/test_igamma.hpp +++ b/test/test_igamma.hpp @@ -316,6 +316,24 @@ void test_spots(T, const char* name = nullptr) // Check large a, x values. Precision just isn't great here. BOOST_CHECK_CLOSE(::boost::math::lgamma_p(static_cast(1450.25), static_cast(1500.75)), static_cast(-0.09812447528127799786140178403478691390753413399549580160096975713L), tolerance * (std::is_same::value ? 16 : 1)); BOOST_CHECK_CLOSE(::boost::math::lgamma_p(static_cast(2000), static_cast(1900)), static_cast(-4.448523733381445722945397105917814000790587922314824687065050805L), tolerance * gcc_win_mul * (std::is_same::value ? 8 : 1)); + // log P is finite where P underflows (#1564), and for large a it is computed in logs. Without a + // Lanczos approximation the prefix is a log(x) - x - lgamma(a), which cancels ~100-fold here: + { + T log_tolerance = tolerance * (std::is_same >::type, boost::math::lanczos::undefined_lanczos>::value ? 200 : 4); + BOOST_CHECK_CLOSE(::boost::math::lgamma_p(static_cast(1000000), static_cast(500000)), static_cast(-193154.3141086602556152285324604561949543258601759776033022052943L), log_tolerance); + BOOST_CHECK_CLOSE(::boost::math::lgamma_p(static_cast(10000), static_cast(5000)), static_cast(-1936.302975331597581776736325409680160786732605632025420667837257L), log_tolerance); + if (!std::is_same >::type, boost::math::lanczos::undefined_lanczos>::value) + { + BOOST_CHECK_CLOSE(::boost::math::lgamma_p(static_cast(100000), static_cast(90000)), static_cast(-540.4252806833238788932453223532282504424226780607045633973466037L), log_tolerance); + BOOST_CHECK_CLOSE(::boost::math::lgamma_p(static_cast(1000000), static_cast(990000)), static_cast(-53.56704246543242809844092012858294405874181248142883790959132019L), log_tolerance); + } + } + // Without a Lanczos approximation, the prefix x^a e^-x / tgamma(a) near x = a was once ~1e4 eps out. Arb: + if (std::is_same >::type, boost::math::lanczos::undefined_lanczos>::value) + { + BOOST_CHECK_CLOSE(::boost::math::gamma_p(static_cast(100000), static_cast(100300)), static_cast(0.828636311251207647668620176040716549542805025L), tolerance); + BOOST_CHECK_CLOSE(::boost::math::gamma_q(static_cast(100000), static_cast(100300)), static_cast(0.171363688748792352331379823959283450457194975L), tolerance); + } // // Coverage: diff --git a/test/test_igamma_inv.cpp b/test/test_igamma_inv.cpp index 40a4191d93..99c4793e27 100644 --- a/test/test_igamma_inv.cpp +++ b/test/test_igamma_inv.cpp @@ -61,7 +61,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_igamma_inv.hpp b/test/test_igamma_inv.hpp index cf481537e7..e8adb1c45c 100644 --- a/test/test_igamma_inv.hpp +++ b/test/test_igamma_inv.hpp @@ -208,6 +208,18 @@ void test_spots(T, const char* type_name) T tolerance = boost::math::tools::epsilon() * 15000; if(tolerance < 1e-25f) tolerance = 1e-25f; // limit of test data? + // + // Temme's expansion used by gamma_p was only good to ~100 eps for x < a, a ~ 20 and (a - x) / a ~ 0.4, + // which the inverse inherits. Reference values from Arb: the x with P(x) = p, and P at that x rounded + // to double, for doubles only: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + typedef boost::math::policies::policy, boost::math::policies::promote_double > no_promote; + T fine_tolerance = boost::math::tools::epsilon() * 3; + BOOST_CHECK_CLOSE_FRACTION(boost::math::gamma_p_inv(T(20.339175013722919), T(0.021704055520888658), no_promote()), static_cast(12.288770943973497911L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(boost::math::gamma_p(T(20.339175013722919), T(12.288770943973498), no_promote()), static_cast(0.021704055520888660013558011624319002363L), fine_tolerance * 3); + } BOOST_CHECK_CLOSE(::boost::math::gamma_q_inv(static_cast(1)/100, static_cast(1.0/128)), static_cast(0.35767144525455121503672919307647515332256996883787L), tolerance); BOOST_CHECK_CLOSE(::boost::math::gamma_q_inv(static_cast(1)/100, static_cast(0.5)), static_cast(4.4655350189103486773248562646452806745879516124613e-31L), tolerance*10); // @@ -230,5 +242,23 @@ void test_spots(T, const char* type_name) BOOST_CHECK_CLOSE(::boost::math::gamma_q_inv(static_cast(10000), static_cast(1.0/128)), static_cast(10243.369973939134157953734588122880006091919872879L), tolerance); BOOST_CHECK_CLOSE(::boost::math::gamma_q_inv(static_cast(10000), static_cast(1.0/2)), static_cast(9999.6666686420474237369661574633153551436435884101L), tolerance); BOOST_CHECK_CLOSE(::boost::math::gamma_q_inv(static_cast(10000), static_cast(1.0-1.0/128)), static_cast(9759.8597223369324083191194574874497413261589080204L), tolerance); + // + // For small a the median is about 2^(-1/a), so this a puts it a little + // below the smallest normal number. The result underflows to zero; + // the root finder must not report it as a failure to find a root: + // + BOOST_MATH_STD_USING + // Take log(min_value / 4) as log(min_value) - log(4): min_value / 4 is + // subnormal, and flushes to zero under fast floating-point models (icpx). + T a_underflow = log(static_cast(0.5)) / (log(boost::math::tools::min_value()) - log(static_cast(4))); + BOOST_CHECK_EQUAL(::boost::math::gamma_p_inv(a_underflow, static_cast(0.5)), static_cast(0)); + BOOST_CHECK_EQUAL(::boost::math::gamma_q_inv(a_underflow, static_cast(0.5)), static_cast(0)); + if (boost::math::tools::min_value() >= boost::math::tools::min_value()) + { + // From example/chi_square_std_dev_test.cpp, where Halley walked onto + // the lower bound and reported "no root found": + BOOST_CHECK_EQUAL(::boost::math::gamma_q_inv(static_cast(0.0019582569458115118 / 2), static_cast(0.5)), static_cast(0)); + BOOST_CHECK_EQUAL(::boost::math::gamma_p_inv(static_cast(0.0019582569458115118 / 2), static_cast(0.5)), static_cast(0)); + } } diff --git a/test/test_inverse_chi_squared_distribution.cpp b/test/test_inverse_chi_squared_distribution.cpp index 6d51bda277..1a59045945 100644 --- a/test/test_inverse_chi_squared_distribution.cpp +++ b/test/test_inverse_chi_squared_distribution.cpp @@ -325,6 +325,22 @@ void test_spots(RealType) } // template void test_spots(RealType) +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType b, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(entropy(inverse_chi_squared_distribution(a, b)), h, tol); + }; + check(static_cast(3.0L), static_cast(0.5L), static_cast(1.00031075496653254881770338072141427422753657L)); + check(static_cast(0.5L), static_cast(1.0L), static_cast(5.43604508029851859864805887992421863148343284L)); + check(static_cast(40.0L), static_cast(2.0L), static_cast(0.647759804228300270654711536822405806757989866L)); + check(static_cast(1000000.0L), static_cast(0.125L), static_cast(-7.22168336384366091723894728684831957747986429L)); +} + BOOST_AUTO_TEST_CASE( test_main ) { BOOST_MATH_CONTROL_FP; @@ -366,7 +382,8 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_EQUAL(ichisq5.scale(), 1./5.); // check default is 1/df BOOST_CHECK_CLOSE_FRACTION(pdf(ichisq5, 0.2), 3.0510380337346841, tol4eps); BOOST_CHECK_CLOSE_FRACTION(cdf(ichisq5, 0.5), 0.84914503608460956, tol4eps); - BOOST_CHECK_CLOSE_FRACTION(cdf(complement(ichisq5, 0.5)), 1 - 0.84914503608460956, tol4eps); + // The expected value is formed by subtraction, which magnifies the rounding of the constant about six times: + BOOST_CHECK_CLOSE_FRACTION(cdf(complement(ichisq5, 0.5)), 1 - 0.84914503608460956, tol4eps * 2); BOOST_CHECK_CLOSE_FRACTION(quantile(ichisq5, 0.84914503608460956), 0.5, tol4eps*100); BOOST_CHECK_CLOSE_FRACTION(quantile(complement(ichisq5, 1. - 0.84914503608460956)), 0.5, tol4eps*100); @@ -503,11 +520,15 @@ BOOST_AUTO_TEST_CASE( test_main ) // Basic sanity-check spot values. // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. OK at decdigits = 0 tolerance = 0.0001 % + test_entropy(0.0F); test_spots(0.0); // Test double. OK at decdigits 7, tolerance = 1e07 % + test_entropy(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. + test_entropy(0.0L); #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0582)) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #else std::cout << "The long double tests have been disabled on this platform " diff --git a/test/test_inverse_gamma_distribution.cpp b/test/test_inverse_gamma_distribution.cpp index 4115e1e0c1..e38cbb1d43 100644 --- a/test/test_inverse_gamma_distribution.cpp +++ b/test/test_inverse_gamma_distribution.cpp @@ -351,6 +351,22 @@ void test_spots(RealType) check_out_of_range >(1, 1); } // template void test_spots(RealType) +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType b, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(entropy(inverse_gamma_distribution(a, b)), h, tol); + }; + check(static_cast(0.5L), static_cast(1.0L), static_cast(4.01762998195683530623317817517466270661338681L)); + check(static_cast(3.0L), static_cast(2.0L), static_cast(0.695157020726022061260512603245962860319637612L)); + check(static_cast(25.0L), static_cast(1.0L), static_cast(-3.38257593603900503164249716259444886211057541L)); + check(static_cast(100000000.0L), static_cast(3.0L), static_cast(-25.1134702873890991000403224939953383411487738L)); +} + BOOST_AUTO_TEST_CASE( test_main ) { BOOST_MATH_CONTROL_FP; @@ -424,11 +440,15 @@ BOOST_AUTO_TEST_CASE( test_main ) // Basic sanity-check spot values. // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. OK at decdigits = 0 tolerance = 0.0001 % + test_entropy(0.0F); test_spots(0.0); // Test double. OK at decdigits 7, tolerance = 1e07 % + test_entropy(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. + test_entropy(0.0L); #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #else std::cout << "The long double tests have been disabled on this platform " diff --git a/test/test_inverse_gaussian.cpp b/test/test_inverse_gaussian.cpp index 0fe64223dc..1e6b0bfc11 100644 --- a/test/test_inverse_gaussian.cpp +++ b/test/test_inverse_gaussian.cpp @@ -173,8 +173,35 @@ void test_spots(RealType) static_cast(10-3), tolerance); BOOST_CHECK_CLOSE_FRACTION(kurtosis_excess(dist), static_cast(10), tolerance); + // + // Far left tail, where Phi(-b) in the second term underflowed to a subnormal and lost most of its digits. + // The cdf is conditioned to ~lambda / 2x = 600 eps here. Value from Arb, doubles only: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + typedef boost::math::policies::policy > no_promote; + BOOST_CHECK_CLOSE_FRACTION(cdf(inverse_gaussian_distribution(1, 128.331518555765), RealType(0.10592537251772893)), RealType(1.166199182184273491e-212), 1000 * std::numeric_limits::epsilon()); + } } // template void test_spots(RealType) +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType b, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(entropy(inverse_gaussian_distribution(a, b)), h, tol); + }; + check(static_cast(1.0L), static_cast(1.0L), static_cast(0.876945607872338864734587249887507731429511511L)); + check(static_cast(2.0L), static_cast(0.25L), static_cast(1.14047831735744598636464486736437321653394965L)); + check(static_cast(0.5L), static_cast(8.0L), static_cast(-0.705997065541163057743050284110759942046857868L)); + check(static_cast(1.0L), static_cast(0.00000095367431640625L), static_cast(-10.5384996985259774833274273221877458085646934L)); + check(static_cast(1.0L), static_cast(1000000.0L), static_cast(-5.48881749577708931064864406514859998012941543L)); + check(static_cast(1000.0L), static_cast(1000000000.0L), static_cast(1.41893778320504774140533029890449264267388904L)); +} + BOOST_AUTO_TEST_CASE( test_main ) { using boost::math::inverse_gaussian; @@ -373,11 +400,15 @@ BOOST_AUTO_TEST_CASE( test_main ) // Basic sanity-check spot values for all floating-point types.. // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. OK at decdigits = 0 tolerance = 0.0001 % + test_entropy(0.0F); test_spots(0.0); // Test double. OK at decdigits 7, tolerance = 1e07 % + test_entropy(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. + test_entropy(0.0L); #ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); #endif #else std::cout << "The long double tests have been disabled on this platform " @@ -387,6 +418,16 @@ BOOST_AUTO_TEST_CASE( test_main ) #endif /* */ + // Large shape: independent high-precision values from the defining CDF. + check_inverse_gaussian(1., 1000., 1., + 0.506306255528466690646614735956978724498991, 0.493693744471533309353385264043021275501009, tolfeweps); + check_inverse_gaussian(1., 1000., 0.96875, + 0.161492549505796665675678816590357590761845, 0.838507450494203334324321183409642409238155, tolfeweps); + check_inverse_gaussian(1., 1000., 1.03125, + 0.838681329955945237527053545092684829137562, 0.161318670044054762472946454907315170862438, tolfeweps); + // The CDF rounds to one here, but its complement is still representable. + BOOST_CHECK_CLOSE_FRACTION(cdf(complement(inverse_gaussian_distribution(1, 1000), 1.5)), + 1.580094156944363444323823384185312e-38, 100 * tolfeweps); } // BOOST_AUTO_TEST_CASE( test_main ) /* @@ -395,5 +436,3 @@ BOOST_AUTO_TEST_CASE( test_main ) */ - - diff --git a/test/test_jacobi.cpp b/test/test_jacobi.cpp index d4e7cc0aa8..6c5ccaadf8 100644 --- a/test/test_jacobi.cpp +++ b/test/test_jacobi.cpp @@ -39,7 +39,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double|real_concept"; } diff --git a/test/test_jacobi.hpp b/test/test_jacobi.hpp index ce2ec9c4e8..a612eaa877 100644 --- a/test/test_jacobi.hpp +++ b/test/test_jacobi.hpp @@ -186,6 +186,23 @@ void test_spots(T, const char* type_name) BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_sn(T(0.5), T(0.5)), static_cast(0.475082936028536510082218324703870258745078171807428948028252L), tol); BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_sn(T(0.5), T(0.5), pol), static_cast(0.475082936028536510082218324703870258745078171807428948028252L), tol); + // + // Near u = (2n+1)K, cn is small and dn used to lose digits. Values are from Arb (via the theta function + // expansion), the abscissas are doubles so we can only test double: + // + BOOST_IF_CONSTEXPR (std::is_same::value) + { + T dn_tol = boost::math::tools::epsilon() * 10; + BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_dn(T(0.7332930440917852), T(9.4366833450051786)), static_cast(0.6799127564738345663478755436187154687815L), dn_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_nd(T(0.7332930440917852), T(9.4366833450051786)), static_cast(1.4707769349500115112320436272161322849164L), dn_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_sd(T(0.7332930440917852), T(9.4366833450051786)), static_cast(1.4707768735044084534575192612018116663588L), dn_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_ds(T(0.7332930440917852), T(9.4366833450051786)), static_cast(0.6799127848789924803863790532625343731021L), dn_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_dn(T(0.66553658429940632), T(5.4260257958150389)), static_cast(0.7463652591027747757683386865740851556893L), dn_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_dn(T(0.1), T(11.023218930621491)), static_cast(0.99498743710661995417657175944133777893L), dn_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_dn(T(0.9), T(6.841647415268311)), static_cast(0.43588989435406730937722480659848075219L), dn_tol); + BOOST_CHECK_CLOSE_FRACTION(boost::math::jacobi_dn(T(0.99), T(10.069801570083575)), static_cast(0.14106735979665890658400749043180858813L), dn_tol); + } + // // Bug cases and coverage: // diff --git a/test/jacobi_test.cpp b/test/test_jacobi_polynomial.cpp similarity index 100% rename from test/jacobi_test.cpp rename to test/test_jacobi_polynomial.cpp diff --git a/test/test_jacobi_theta.cpp b/test/test_jacobi_theta.cpp index 744991508a..d520c9572c 100644 --- a/test/test_jacobi_theta.cpp +++ b/test/test_jacobi_theta.cpp @@ -85,17 +85,137 @@ BOOST_AUTO_TEST_CASE( test_main ) BOOST_CHECK_THROW(jacobi_theta4tau(0.0, 0.0), std::domain_error); BOOST_CHECK_THROW(jacobi_theta4tau(0.0, -1.0), std::domain_error); + // Non-finite arguments must raise a domain error. Previously a NaN tau or q + // (or a NaN or infinite z when tau < 1) never satisfied the convergence + // test and the series loops ran forever. + double nan = std::numeric_limits::quiet_NaN(); + double inf = std::numeric_limits::infinity(); + BOOST_CHECK_THROW(jacobi_theta1(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta2(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3m1(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4m1(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta1tau(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta2tau(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3tau(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4tau(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3m1tau(1.0, nan), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4m1tau(1.0, nan), std::domain_error); + for (double tau : { 0.5, 1.5 }) { + BOOST_CHECK_THROW(jacobi_theta1tau(nan, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta2tau(nan, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3tau(nan, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4tau(nan, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3m1tau(nan, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4m1tau(nan, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta1tau(inf, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta2tau(-inf, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3tau(inf, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4tau(-inf, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3m1tau(inf, tau), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4m1tau(-inf, tau), std::domain_error); + } + for (double q : { 0.5, 0.01 }) { + BOOST_CHECK_THROW(jacobi_theta1(nan, q), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta2(inf, q), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3(nan, q), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4(-inf, q), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta3m1(nan, q), std::domain_error); + BOOST_CHECK_THROW(jacobi_theta4m1(inf, q), std::domain_error); + } + double eps = std::numeric_limits::epsilon(); - for (double q=0.0078125; q<1.0; q += 0.0078125) { // = 1/128 - for (double z=-8.0; z<=8.0; z += 0.125) { - test_periodicity(z, q, 100 * eps); + + // theta1 with tau < 1 is evaluated via the imaginary transformation, where + // it was previously computed as a difference of two nearly equal Gaussians + // and lost precision proportional to 1/z (about 1e9 ulps at z = 1e-10). + // Reference values: direct Fourier series in 40-digit arithmetic (mpmath). + struct theta1_case { double z, tau, expected; }; + const theta1_case theta1_small_z[] = { + { 1e-4, 0.5, 0.0001175932162452335795142692 }, + { 1e-8, 0.5, 1.175932162099660862653499e-8 }, + { -1e-8, 0.5, -1.175932162099660862653499e-8 }, + { 1e-10, 0.9, 9.76024299466749337952347e-11 }, + { 1e-6, 0.1, 2.455212638799910177735142e-8 }, + // Exercise the fold from [-pi, pi] into [-pi/2, pi/2] and the sign of the odd reflection + { 3.0, 0.5, 0.1665975725928680619270942 }, + { -2.5, 0.5, -0.7534671707347227485840592 }, + { 1.5, 0.9, 0.987286730404979118338758 }, + }; + for (const theta1_case& c : theta1_small_z) { + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta1tau(c.z, c.tau), c.expected, 20 * eps); + } + + // The q-parameterized functions previously went through tau = -log(q)/pi + // and back through exp(), which amplified rounding by |log q| (about 100 + // ulps at q = 1e-200). They now evaluate q^n directly with pow() when q is + // small enough for the direct series to be used. + struct q_case { double q, theta1, theta2, theta3m1, theta4m1; }; + const q_case small_q[] = { + { 1e-8, 0.01288435374475381934703355, 0.01529684374568976751542499, 1.650671229819356594481906e-8, -1.650671229819356594481904e-8 }, + { 1e-100, 1.288435374475382107345229e-25, 1.52968437456897685251172e-25, 1.650671229819356594481905e-100, -1.650671229819356594481905e-100 }, + { 1e-200, 1.288435374475382107345229e-50, 1.52968437456897685251172e-50, 1.650671229819356594481905e-200, -1.650671229819356594481905e-200 }, + }; + for (const q_case& c : small_q) { + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta1(0.7, c.q), c.theta1, 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta2(0.7, c.q), c.theta2, 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta3m1(0.3, c.q), c.theta3m1, 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta4m1(0.3, c.q), c.theta4m1, 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta3(0.3, c.q), 1 + c.theta3m1, 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta4(0.3, c.q), 1 + c.theta4m1, 10 * eps); + } + + + // The argument reduction for tau < 1 previously chose the multiple of the + // period from a 24-bit pi, which picked the wrong multiple for z above a + // few times 1e7 and returned zero from z = 1e9 on. The reduction now uses + // the full pi and folds its error into the remainder, so these are exact + // to a few ulps. Reference values: mpmath with 40 digits. + struct large_z_case { double z, tau, theta1, theta2, theta3, theta4; }; + const large_z_case large_z[] = { + { 4e7, 0.05, -3.757318694348920055753796, -0.00001545462079485293420015852, 0.00001549605722685305986708678, 3.757318694348920055753799 }, + { 4e7, 0.9, -0.9759572565724512898452158, -0.1607607523378354523430388, 0.8881057607381379901037041, 1.11193291050224539104741 }, + { 1e9, 0.05, 0.00835757877707516055357722, 0.5355121416942209933299827, 0.5355121416942209992545699, 0.008357578778633724488455624 }, + { 1e9, 0.9, 0.5350024815437516287353571, 0.8259223040518742875028426, 1.047801422217507380865766, 0.9521655733653082082851415 }, + { 1e12, 0.05, -0.02213061047237238578451432, 0.2849830841470243476666576, 0.2849830841470244257276671, 0.02213061047253907642968685 }, + { 1e12, 0.9, -0.5997376814987367699456432, 0.7793174854358325013985754, 1.029889184690759448919078, 0.9700680662824351299496771 }, + }; + for (const large_z_case& c : large_z) { + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta1tau(c.z, c.tau), c.theta1, 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta2tau(c.z, c.tau), c.theta2, 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta3tau(c.z, c.tau), c.theta3, 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta4tau(c.z, c.tau), c.theta4, 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta1tau(-c.z, c.tau), -c.theta1, 10 * eps); + if (c.z <= 1e9) { // exactly representable as a float + // Beyond 1/epsilon the reduction's accuracy degrades as z*epsilon^2, + // about 50 ulps at z = 1e9 in float + float feps = std::numeric_limits::epsilon(); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta1tau(static_cast(c.z), static_cast(c.tau)), static_cast(c.theta1), 100 * feps); + BOOST_CHECK_CLOSE_FRACTION(jacobi_theta3tau(static_cast(c.z), static_cast(c.tau)), static_cast(c.theta3), 100 * feps); + } + } + + // q = 1/128, 3/128, ..., 127/128: every other point of the 1/128 grid, which keeps both extremes. + for (double q=0.0078125; q<1.0; q += 0.015625) { + // The periodicity test shifts z by the rounded constant two_pi, which + // differs from the true period by about eps. For large q the theta + // functions are steep enough (their logarithmic derivative is of + // order 1/tau = -pi/ln q) that this shift changes them by more than + // the rounding of the evaluation itself, so allow for it. + double periodicity_tol = 100 * eps + 4 * constants::pi() * constants::pi() * eps / -log(q); + for (double z=-8.0; z<=8.0; z += 0.25) { + test_periodicity(z, q, periodicity_tol); test_argument_translation(z, q, 100 * eps); test_sums_of_squares(z, q, 100 * eps); // The addition formula is complicated, cut it some extra slack test_addition_formulas(z, constants::ln_two(), q, sqrt(sqrt(eps))); test_duplication_formula(z, q, 100 * eps); test_transformations_of_nome(z, q, 100 * eps); - test_watsons_identities(z, 0.5, q, 101 * eps); + // Watson's identities subtract products of order 1 to leave a much + // smaller remainder, so single-ulp differences in the individual + // theta values are amplified by up to a couple of orders of magnitude. + test_watsons_identities(z, 0.5, q, 200 * eps); test_landen_transformations(z, -log(q)/constants::pi(), sqrt(eps)); test_elliptic_functions(z, q, 5 * sqrt(eps)); } @@ -105,10 +225,22 @@ BOOST_AUTO_TEST_CASE( test_main ) test_special_values(eps); for (double s=0.125; s<3.0; s+=0.125) { - test_mellin_transforms(2.0 + s, eps, 3 * eps); + // The integrals sum thousands of theta values, so allow a few ulps + test_mellin_transforms(2.0 + s, eps, 6 * eps); test_laplace_transforms(s, eps, 4 * eps); } + // Laplace transforms at fixed z, for all four functions. The z values + // include the small-z regime where theta1 with tau < 1 used to lose + // precision, and the ranges cover both series branches in tau. + for (double a : { 0.5, 1.0, 2.0, 5.0 }) { + for (double z : { 1e-6, 1e-3, 0.1, 0.5, 1.0, 1.5, -0.7, 2.5, 3.0 }) { + test_laplace_transforms_in_z(static_cast(a), static_cast(z), + std::numeric_limits::epsilon(), 25 * std::numeric_limits::epsilon()); + test_laplace_transforms_in_z(a, z, eps, 25 * eps); + } + } + test_spots(0.0F, "float"); test_spots(0.0, "double"); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS diff --git a/test/test_jacobi_theta.hpp b/test/test_jacobi_theta.hpp index 472f37350c..451c9935b0 100644 --- a/test/test_jacobi_theta.hpp +++ b/test/test_jacobi_theta.hpp @@ -698,8 +698,77 @@ inline void test_laplace_transforms(RealType s, RealType integration_eps, RealTy l/sqrt(s)*cosh(beta*sqrt(s))/sinh(l*sqrt(s)), result_eps); - // TODO - DLMF defines two additional relations for theta2 and theta3, but - // these do not match the computed values at all. + // DLMF 20.10.6 and 20.10.7 give the theta2 and theta3 transforms; the + // equivalent identities in the (z, tau) parameterization, with theta2 and + // theta3m1 covered, are checked in test_laplace_transforms_in_z below. +} + +// Laplace transforms in tau at fixed z, for all four functions. +// +// Integrating the Fourier series (DLMF 20.2.1 to 20.2.4) term by term with +// +// int_0^inf exp(-a tau) exp(-pi tau m^2) dtau = 1 / (a + pi m^2) +// +// and summing the classical partial fractions +// +// sum_{n>=0} (-1)^n sin((2n+1)x) / ((2n+1)^2 + c^2) = (pi/4c) sinh(c x) sech(pi c/2), |x| < pi/2 +// sum_{n>=0} cos((2n+1)x) / ((2n+1)^2 + c^2) = (pi/4c) sinh(c(pi/2 - x)) sech(pi c/2), 0 < x < pi +// sum_{n>=1} cos(2nx) / (n^2 + c^2) = (pi/2c) cosh(c(pi - 2x)) csch(pi c) - 1/(2c^2), 0 <= x <= pi +// +// gives, with c = sqrt(a/pi) and s = sqrt(a pi), +// +// int_0^inf exp(-a tau) theta1(z | i tau) dtau = sqrt(pi/a) sinh(2 c z) sech(s), |z| < pi/2 +// int_0^inf exp(-a tau) theta2(z | i tau) dtau = sqrt(pi/a) sinh(c (pi - 2 z)) sech(s), 0 < z < pi +// int_0^inf exp(-a tau) theta3m1(z | i tau) dtau = sqrt(pi/a) cosh(c (pi - 2 z)) csch(s) - 1/a, 0 <= z <= pi +// int_0^inf exp(-a tau) theta4m1(z | i tau) dtau = sqrt(pi/a) cosh(2 c z) csch(s) - 1/a, |z| <= pi/2 +// +// The integrals run through both the tau < 1 (imaginary transformation) and +// tau >= 1 (direct series) branches, so this checks that they agree with each +// other and that the small-z, small-tau regime of theta1 is accurate. +// +// The quadrature error is relative to the L1 norm of the integrand, and the +// two "m1" closed forms subtract 1/a from a quantity of similar size, so the +// tolerance is scaled by (L1 + 1/a) rather than by the result itself. +template +inline void test_laplace_transforms_in_z(RealType a, RealType z, RealType integration_eps, RealType result_eps) { + using namespace boost::math; + BOOST_MATH_STD_USING + + boost::math::quadrature::exp_sinh integrator; + + const RealType pi = constants::pi(); + const RealType c = sqrt(a / pi); + const RealType s = sqrt(a * pi); + const RealType scale = sqrt(pi / a); + + auto check = [&](const RealType& computed, const RealType& expected, const RealType& tolerance) + { + BOOST_CHECK_MESSAGE(abs(computed - expected) <= tolerance, + "a = " << a << ", z = " << z << ": computed " << computed + << " vs expected " << expected << ", tolerance " << tolerance); + }; + + RealType error, L1; + + if (abs(z) < pi / 2) { + auto f1 = [&](RealType t) { return exp(-a * t) * jacobi_theta1tau(z, t); }; + RealType Q1 = integrator.integrate(f1, integration_eps, &error, &L1); + check(Q1, scale * sinh(2 * c * z) / cosh(s), result_eps * L1); + + auto f4 = [&](RealType t) { return exp(-a * t) * jacobi_theta4m1tau(z, t); }; + RealType Q4 = integrator.integrate(f4, integration_eps, &error, &L1); + check(Q4, scale * cosh(2 * c * z) / sinh(s) - 1 / a, result_eps * (L1 + 1 / a)); + } + + if (z > 0 && z < pi) { + auto f2 = [&](RealType t) { return exp(-a * t) * jacobi_theta2tau(z, t); }; + RealType Q2 = integrator.integrate(f2, integration_eps, &error, &L1); + check(Q2, scale * sinh(c * (pi - 2 * z)) / cosh(s), result_eps * L1); + + auto f3 = [&](RealType t) { return exp(-a * t) * jacobi_theta3m1tau(z, t); }; + RealType Q3 = integrator.integrate(f3, integration_eps, &error, &L1); + check(Q3, scale * cosh(c * (pi - 2 * z)) / sinh(s) - 1 / a, result_eps * (L1 + 1 / a)); + } } template diff --git a/test/test_jacobi_zeta.cpp b/test/test_jacobi_zeta.cpp index a11e278f34..3b7a404e0f 100644 --- a/test/test_jacobi_zeta.cpp +++ b/test/test_jacobi_zeta.cpp @@ -45,7 +45,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } diff --git a/test/test_jso.cpp b/test/test_jso.cpp new file mode 100644 index 0000000000..bbf266a3e4 --- /dev/null +++ b/test/test_jso.cpp @@ -0,0 +1,178 @@ +/* + * Copyright Nick Thompson, 2024 + * 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) + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" +#include "test_functions_for_optimization.hpp" +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif + +using boost::math::optimization::jso; +using boost::math::optimization::jso_parameters; +using boost::math::optimization::detail::weighted_lehmer_mean; + +void test_default_population_with_many_threads() { + using ArgType = std::array; + auto jso_params = jso_parameters(); + jso_params.lower_bounds = {-5, -5}; + jso_params.upper_bounds = {5, 5}; + jso_params.threads = 128; + + boost::math::optimization::validate_jso_parameters(jso_params); + CHECK_GE(jso_params.initial_population_size, jso_params.threads); +} + +void test_weighted_lehmer_mean() { + size_t n = 50; + std::vector weights(n, 1.0); + std::vector values(n, 2.5); + // Technically, this is not a fully general weighted Lehmer mean, + // but just a weighted contraharmonic mean. + // So we have a few more invariants available to us: + CHECK_ULP_CLOSE(2.5, weighted_lehmer_mean(values, weights), n); + std::mt19937_64 gen(12345); + std::uniform_real_distribution unif(std::numeric_limits::epsilon(),1); + for (size_t i = 0; i < n; ++i) { + weights[i] = unif(gen); + values[i] = unif(gen); + } + auto mean = weighted_lehmer_mean(values, weights); + CHECK_LE(mean, 1.0); + CHECK_LE(std::numeric_limits::epsilon(), mean); +} + +template void test_ackley() { + std::cout << "Testing jSO on Ackley function . . .\n"; + using ArgType = std::array; + auto jso_params = jso_parameters(); + jso_params.lower_bounds = {-5, -5}; + jso_params.upper_bounds = {5, 5}; + + std::mt19937_64 gen(12345); + auto local_minima = jso(ackley, jso_params, gen); + CHECK_LE(std::abs(local_minima[0]), std::sqrt(std::numeric_limits::epsilon())); + CHECK_LE(std::abs(local_minima[1]), std::sqrt(std::numeric_limits::epsilon())); + + // Does it work with a lambda? + auto ack = [](std::array const &x) { return ackley(x); }; + local_minima = jso(ack, jso_params, gen); + CHECK_LE(std::abs(local_minima[0]), std::sqrt(std::numeric_limits::epsilon())); + CHECK_LE(std::abs(local_minima[1]), std::sqrt(std::numeric_limits::epsilon())); + + // Test that if an intial guess is the exact solution, the returned solution is the exact solution: + std::array initial_guess{0, 0}; + jso_params.initial_guess = &initial_guess; + local_minima = jso(ack, jso_params, gen); + + using std::fabs; + CHECK_LE(fabs(local_minima[0]), 128 * boost::math::tools::epsilon()); + CHECK_LE(fabs(local_minima[1]), 128 * boost::math::tools::epsilon()); +} + +template void test_rosenbrock_saddle() { + std::cout << "Testing jSO on Rosenbrock saddle . . .\n"; + using ArgType = std::array; + jso_parameters jso_params { }; + jso_params.lower_bounds = {0.5, 0.5}; + jso_params.upper_bounds = {2.048, 2.048}; + std::mt19937_64 gen(234568); + auto local_minima = jso(rosenbrock_saddle, jso_params, gen); + + CHECK_ABSOLUTE_ERROR(Real(1), local_minima[0], std::sqrt(std::numeric_limits::epsilon())); + CHECK_ABSOLUTE_ERROR(Real(1), local_minima[1], std::sqrt(std::numeric_limits::epsilon())); + + // Does cancellation work? + std::atomic cancel = true; + gen.seed(12345); + local_minima = + jso(rosenbrock_saddle, jso_params, gen, std::numeric_limits::quiet_NaN(), &cancel); + CHECK_GE(std::abs(local_minima[0] - Real(1)), std::sqrt(std::numeric_limits::epsilon())); +} + + + +template void test_rastrigin() { + std::cout << "Testing jSO on Rastrigin function (global minimum = (0,0,...,0))\n"; + using ArgType = std::vector; + auto jso_params = jso_parameters(); + jso_params.lower_bounds.resize(3, static_cast(-5.12)); + jso_params.upper_bounds.resize(3, static_cast(5.12)); + jso_params.initial_population_size = 5000; + jso_params.max_function_evaluations = 1000000; + std::mt19937_64 gen(34567); + + // By definition, the value of the function which a target value is provided must be <= target_value. + Real target_value = 1e-3; + auto local_minima = jso(rastrigin, jso_params, gen, target_value); + CHECK_LE(rastrigin(local_minima), target_value); +} + +// Tests NaN return types and return type != input type: +void test_sphere() { + std::cout << "Testing jSO on sphere . . .\n"; + using ArgType = std::vector; + auto jso_params = jso_parameters(); + jso_params.lower_bounds.resize(8, -1); + jso_params.upper_bounds.resize(8, 1); + std::mt19937_64 gen(56789); + auto local_minima = jso(sphere, jso_params, gen); + for (auto x : local_minima) { + CHECK_ABSOLUTE_ERROR(0.0f, x, 2e-4f); + } +} + +template +void test_three_hump_camel() { + std::cout << "Testing jSO on three hump camel . . .\n"; + using ArgType = std::array; + auto jso_params = jso_parameters(); + jso_params.lower_bounds[0] = -5.0; + jso_params.lower_bounds[1] = -5.0; + jso_params.upper_bounds[0] = 5.0; + jso_params.upper_bounds[1] = 5.0; + std::mt19937_64 gen(56789); + auto local_minima = jso(three_hump_camel, jso_params, gen); + for (auto x : local_minima) { + CHECK_ABSOLUTE_ERROR(0.0f, x, 2e-4f); + } +} + +template +void test_beale() { + std::cout << "Testing jSO on the Beale function . . .\n"; + using ArgType = std::array; + auto jso_params = jso_parameters(); + jso_params.lower_bounds[0] = -5.0; + jso_params.lower_bounds[1] = -5.0; + jso_params.upper_bounds[0]= 5.0; + jso_params.upper_bounds[1]= 5.0; + std::mt19937_64 gen(56789); + auto local_minima = jso(beale, jso_params, gen); + CHECK_ABSOLUTE_ERROR(Real(3), local_minima[0], Real(2e-4)); + CHECK_ABSOLUTE_ERROR(Real(1)/Real(2), local_minima[1], Real(2e-4)); +} + +int main() { + test_default_population_with_many_threads(); + test_ackley(); + test_ackley(); + test_rosenbrock_saddle(); + test_rastrigin(); + test_three_hump_camel(); + test_beale(); + test_sphere(); + test_weighted_lehmer_mean(); + return boost::math::test::report_errors(); +} diff --git a/test/test_kolmogorov_smirnov.cpp b/test/test_kolmogorov_smirnov.cpp index 58dad8cd5d..230978258d 100644 --- a/test/test_kolmogorov_smirnov.cpp +++ b/test/test_kolmogorov_smirnov.cpp @@ -12,6 +12,8 @@ #include // for BOOST_CHECK_CLOSE #include #include +#include +#include template // Any floating-point type RealType. void test_spots(RealType) @@ -35,13 +37,14 @@ void test_spots(RealType) RealType x = 1.0 * (i+1) / 1001; RealType p = cdf(dist, x); RealType p1 = cdf(complement(dist, x)); - RealType x1; - if (p < 0.5) - x1 = quantile(dist, p); - else - x1 = quantile(complement(dist, p1)); - if (p > tol && p1 > tol) // skip the extreme tails + if (p > tol && p1 > tol) { // skip the extreme tails + RealType x1; + if (p < 0.5) + x1 = quantile(dist, p); + else + x1 = quantile(complement(dist, p1)); BOOST_CHECK_CLOSE_FRACTION(x, x1, tol); + } } } @@ -87,17 +90,159 @@ void test_spots(RealType) BOOST_CHECK_CLOSE_FRACTION(kurt, kurtosis_excess(dist) + 3, eps); } +// Checks that x is the quantile of p to within a few ulps, by bracketing: +// cdf(x * (1 - margin)) <= p <= cdf(x * (1 + margin)). Unlike a round-trip +// comparison of cdf(quantile(p)) with p, this remains meaningful deep in the +// tails, where the CDF is so steep that one ulp of x corresponds to many +// ulps of p. +template +void check_quantile(const boost::math::kolmogorov_smirnov_distribution& dist, RealType p, RealType x, bool complemented) +{ + using namespace boost::math; + RealType margin = 8 * tools::epsilon(); + RealType lo = complemented ? cdf(complement(dist, RealType(x * (1 + margin)))) : cdf(dist, RealType(x * (1 - margin))); + RealType hi = complemented ? cdf(complement(dist, RealType(x * (1 - margin)))) : cdf(dist, RealType(x * (1 + margin))); + BOOST_TEST_CHECK(lo <= p); + BOOST_TEST_CHECK(p <= hi); +} + +template +void test_quantile_extremes(RealType) +{ + using namespace boost::math; + RealType eps = tools::epsilon(); + + // Small n, where the quantile exceeds unity in the upper tail + for (RealType n : { RealType(1), RealType(2), RealType(3), RealType(1000000) }) { + kolmogorov_smirnov_distribution dist(n); + for (int i = 1; i < 100; i++) { + RealType p = RealType(i) / 100; + check_quantile(dist, p, quantile(dist, p), false); + check_quantile(dist, p, quantile(complement(dist, p)), true); + } + } + + kolmogorov_smirnov_distribution dist(10); + + // Deep tails, down to where the CDF itself is no longer evaluated to + // full precision because its terms become denormal + for (RealType p = RealType(0.1); p > 10000 * tools::min_value(); p /= 1000) { + check_quantile(dist, p, quantile(dist, p), false); + check_quantile(dist, p, quantile(complement(dist, p)), true); + } + + // Limits of the probability range + BOOST_CHECK_EQUAL(quantile(dist, RealType(0)), RealType(0)); + BOOST_CHECK_EQUAL(quantile(complement(dist, RealType(1))), RealType(0)); + BOOST_CHECK_THROW(quantile(dist, RealType(1)), std::overflow_error); + BOOST_CHECK_THROW(quantile(complement(dist, RealType(0))), std::overflow_error); + + // The median is the quantile of one half + BOOST_CHECK_CLOSE_FRACTION(cdf(dist, median(dist)), RealType(0.5), 10 * eps); + BOOST_CHECK_CLOSE_FRACTION(median(dist), quantile(dist, RealType(0.5)), 10 * eps); +} + +// Reference values computed from the two series at 60 decimal digits and given +// to 40, which is enough for a 113-bit long double. +template +void test_reference_values(RealType) +{ + using namespace boost::math; + BOOST_MATH_STD_USING // without it sqrt(long double) can bind to ::sqrt(double) + RealType eps = tools::epsilon(); + static const struct { double n, x; long double pdf, cdf, ccdf; } data[] = { + { 10, 0.125, 0.2794000234541079717388096723565994485867L, 0.002361174787509568195989680164454239235797L, 0.9976388252124904318040103198355457607642L }, + { 10, 0.25, 5.193400831298942628933394720192144589244L, 0.4404402898047362231585527709511894227082L, 0.5595597101952637768414472290488105772918L }, + { 10, 0.375, 1.800079163884122092670200607964937329104L, 0.8799166787843709758060153896938758782439L, 0.1200833212156290241939846103061241217561L }, + { 10, 0.5, 0.2695175501788391040012563523532817140662L, 0.9865241101241363106265931874745960750216L, 0.01347588987586368937340681252540392497843L }, + { 10, 0.75, 7.804378592440503887211784902487782139377e-4L, 0.9999739854046918648152915125506947553913L, 2.601459530813518470848744930524460867172e-5L }, + { 10, 1.0, 1.648922897950846262372752246369412370047e-7L, 0.9999999958776927551228843440681192757854L, 4.122307244877115655931880724214614195843e-9L }, + { 1, 0.25, 4.128551064736226095083086707053011290815e-6L, 2.682381008482982753810582973667256706209e-8L, 0.9999999731761899151701724618941702633274L }, + { 1, 0.5, 0.6395828509404566346454593384123317079184L, 0.03605475633512490561408610371791087180628L, 0.9639452436648750943859138962820891281937L }, + { 1, 0.75, 1.683460951304975381694233065698018862373L, 0.3728329582237383585063344713966983906617L, 0.6271670417762616414936655286033016093383L }, + { 1, 1.5, 0.1333072274198802100373204656125755644301L, 0.9777820373834748712794563853895431189662L, 0.02221796261652512872054361461045688103382L }, + { 1, 2.5, 7.453306344157340442849824580766625946801e-5L, 0.9999925466936558426583999002666408827042L, 7.453306344157341600099733359117295757206e-6L }, + }; + for (const auto& d : data) { + kolmogorov_smirnov_distribution dist(static_cast(d.n)); + RealType x = static_cast(d.x); + BOOST_CHECK_CLOSE_FRACTION(pdf(dist, x), static_cast(d.pdf), 20 * eps); + BOOST_CHECK_CLOSE_FRACTION(cdf(dist, x), static_cast(d.cdf), 50 * eps); + // Above 2*x*x*n = pi the complement is computed from the nome with a + // compensated exponent; below it goes through the Jacobi Theta + // function with a rounded tau, whose error is amplified by the + // exponent. + RealType ccdf_tol = (2 * x * x * d.n > constants::pi()) ? 10 * eps : 200 * eps; + BOOST_CHECK_CLOSE_FRACTION(cdf(complement(dist, x)), static_cast(d.ccdf), ccdf_tol); + } + + // The moment constants agree with the closed forms they were computed from + kolmogorov_smirnov_distribution dist(10); + RealType n = 10; + RealType mean = boost::math::mean(dist); + RealType var = variance(dist); + RealType ex3 = RealType(0.5625) * constants::root_half_pi() * constants::zeta_three() / n / sqrt(n); + RealType ex4 = 7 * constants::pi_sqr_div_six() * constants::pi_sqr_div_six() / 20 / n / n; + RealType skew = (ex3 - 3 * mean * var - mean * mean * mean) / var / sqrt(var); + RealType kurt = (ex4 - 4 * mean * skew * var * sqrt(var) - 6 * mean * mean * var - mean * mean * mean * mean) / var / var; + BOOST_CHECK_CLOSE_FRACTION(skewness(dist), skew, 500 * eps); + BOOST_CHECK_CLOSE_FRACTION(kurtosis(dist), kurt, 500 * eps); + BOOST_CHECK_CLOSE_FRACTION(kurtosis_excess(dist), kurt - 3, 2000 * eps); +} + +// Types with more than 100 decimal digits compute the mode, median and +// moments at run-time; check that they agree with the tabulated constants. +void test_high_precision() +{ + using namespace boost::math; + typedef boost::multiprecision::number > RealType; + kolmogorov_smirnov_distribution dist(1); + RealType tol = RealType("1e-99"); + BOOST_CHECK_CLOSE_FRACTION(mode(dist), RealType("0.7354679079165719820624448513051825390913503143340225122926732679283442751250018638342479353073554823"), tol); + BOOST_CHECK_CLOSE_FRACTION(median(dist), RealType("0.8275735551899076901138270828889768075843727832232029452002281054669822747682290224084911530683945353"), tol); + BOOST_CHECK_CLOSE_FRACTION(skewness(dist), RealType("0.8604261371436682558667183685173007452393495203060929924698665373211030237490355834020123201092217303"), tol); + BOOST_CHECK_CLOSE_FRACTION(kurtosis_excess(dist), RealType("0.8816189679105236704015538304328295408355055629289034536289160037385510119639244078254098968815665536"), tol); +} + +template +void test_entropy(RealType) +{ + // Reference values from mpmath at 60 digits: closed forms, or -sum p log(p) for the discrete + // distributions, which have none. Parameters are exact in every type. + RealType tol = 16 * boost::math::tools::epsilon(); + auto check = [&](RealType a, RealType h) + { + BOOST_CHECK_CLOSE_FRACTION(boost::math::entropy(boost::math::kolmogorov_smirnov_distribution(a)), h, tol); + }; + check(static_cast(1.0L), static_cast(0.000890322654402673706663823838286072983848397531L)); + check(static_cast(10.0L), static_cast(-1.15040222384262016830233190350389603081670235L)); + check(static_cast(1000.0L), static_cast(-3.45298731683666585232032335818826023841780384L)); +} + BOOST_AUTO_TEST_CASE( test_main ) { BOOST_MATH_CONTROL_FP; // (Parameter value, arbitrarily zero, only communicates the floating point type). - test_spots(0.0F); // Test float. - test_spots(0.0); // Test double. + test_spots(0.0F); // Test float. + test_entropy(0.0F); + test_spots(0.0); // Test double. + test_entropy(0.0); + test_quantile_extremes(0.0F); + test_quantile_extremes(0.0); + test_reference_values(0.0F); + test_reference_values(0.0); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. + test_entropy(0.0L); + test_quantile_extremes(0.0L); + test_reference_values(0.0L); #if !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. + test_entropy(boost::math::concepts::real_concept(0.)); + test_quantile_extremes(boost::math::concepts::real_concept(0.)); + test_reference_values(boost::math::concepts::real_concept(0.)); #endif #endif + test_high_precision(); } diff --git a/test/test_laguerre.cpp b/test/test_laguerre.cpp index e4290c7a1a..64ae90b88a 100644 --- a/test/test_laguerre.cpp +++ b/test/test_laguerre.cpp @@ -3,6 +3,10 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// The test data contains overflows, which the test expects to come back as infinities, as in the +// test_instances library (which is compiled with this policy). The headers are included here as well, +// so the policy has to agree with the library's to avoid two different definitions of the same functions: +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error #include #include "test_laguerre.hpp" @@ -38,7 +42,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } @@ -54,7 +58,7 @@ void expected_results() // even though the implementation contains nothing but basic // arithmetic? // - if((std::numeric_limits::digits <= 64) + if(boost::math::policies::promote_double<>() && (std::numeric_limits::digits <= 64) && (std::numeric_limits::digits != std::numeric_limits::digits)) { #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS diff --git a/test/test_laguerre.hpp b/test/test_laguerre.hpp index 8f49b681c4..dd1bd39296 100644 --- a/test/test_laguerre.hpp +++ b/test/test_laguerre.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include "functor.hpp" @@ -129,6 +130,31 @@ void test_spots(T, const char* t) BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(20, static_cast(4.5L)), static_cast(1.437239150257817378525582974722170737587L), tolerance); BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(50, static_cast(4.5L)), static_cast(-0.7795068145562651416494321484050019245248L), tolerance); + // + // Large n, where the plain recurrence loses up to n^1.5 epsilon or so. + // Values from Arb, summing the power series with ball arithmetic: + // + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(100, static_cast(0.0068359375L)), static_cast(0.423801679702102671995527499546438407167L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(100, static_cast(-0.0126953125L)), static_cast(2.728030280575653737375641683876867341864L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(300, static_cast(0.0185546875L)), static_cast(-0.26543197876082762751661668583129080036L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(50, static_cast(0.08984375L)), static_cast(-0.38457758508627425771987804342644330632L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(200, static_cast(0.04296875L)), static_cast(0.115650412589651806567199804324877580583L), tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(1000, static_cast(0.009765625L)), static_cast(0.214478845717718726380897093043899969172L), tolerance); + // + // The corrected recurrence should be good to an epsilon or two everywhere, without promotion to a wider + // type too. Exact values, from the recurrence in rational arithmetic: + // + { + typedef boost::math::policies::policy, boost::math::policies::promote_double > no_promote; + T fine_tolerance = boost::math::tools::epsilon() * 4; + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(300, static_cast(0.25L), no_promote()), static_cast(-0.1459220863189830924214270638214961311852L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(100, static_cast(2.5L), no_promote()), static_cast(0.4257949400323675465623240248736101499633L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(1000, static_cast(0.5L), no_promote()), static_cast(0.1530641781102510973600254467704571049436L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(50, static_cast(12.5L), no_promote()), static_cast(14.31526804586314374951422376822543024939L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(200, static_cast(1.375L), no_promote()), static_cast(0.1504238825858422683351257809206239809714L), fine_tolerance); + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(100, static_cast(0.0068359375L), no_promote()), static_cast(0.423801679702102671995527499546438407167L), fine_tolerance); + } + BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(4, 5, static_cast(0.5L)), static_cast(88.31510416666666666666666666666666666667L), tolerance); BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(10, 0, static_cast(2.5L)), static_cast(-0.8802526766660982969576719576719576719577L), tolerance); BOOST_CHECK_CLOSE_FRACTION(::boost::math::laguerre(10, 1, static_cast(4.5L)), static_cast(1.564311458042689732142857142857142857143L), tolerance); diff --git a/test/test_lambert_w.cpp b/test/test_lambert_w.cpp index e0cbd24f66..cda0d724c7 100644 --- a/test/test_lambert_w.cpp +++ b/test/test_lambert_w.cpp @@ -33,14 +33,10 @@ #include // for BOOST_MSVC versions. // Boost macros -#define BOOST_TEST_MAIN -#define BOOST_LIB_DIAGNOSTIC "on" // Report library file details. //#define BOOST_TEST_LOG_LEVEL all // Appears not to work??? // run with --log_level="message" -#include // Boost.Test -// #include // Boost.Test -#include +#include "math_unit_test.hpp" #include #include @@ -183,7 +179,7 @@ void wolfram_test_moderate_values() tolerance *= 4; // arbitrary precision types have lower accuracy on exp(z). for (unsigned i = 0; i < wolfram_test_small_neg.size(); ++i) { - BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w0(T(wolfram_test_small_neg[i][0])), T(wolfram_test_small_neg[i][1]), tolerance); + CHECK_RELATIVE_ERROR(boost::math::lambert_w0(T(wolfram_test_small_neg[i][0])), T(wolfram_test_small_neg[i][1]), tolerance); } } @@ -202,7 +198,7 @@ void wolfram_test_small_pos() tolerance *= 3; // arbitrary precision types have lower accuracy on exp(z). for (unsigned i = 0; i < wolfram_test_small_neg.size(); ++i) { - BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w0(T(wolfram_test_small_neg[i][0])), T(wolfram_test_small_neg[i][1]), tolerance); + CHECK_RELATIVE_ERROR(boost::math::lambert_w0(T(wolfram_test_small_neg[i][0])), T(wolfram_test_small_neg[i][1]), tolerance); } } @@ -222,7 +218,7 @@ void wolfram_test_small_neg() tolerance *= 3; // arbitrary precision types have lower accuracy on exp(z). for (unsigned i = 0; i < wolfram_test_small_neg.size(); ++i) { - BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w0(T(wolfram_test_small_neg[i][0])), T(wolfram_test_small_neg[i][1]), tolerance); + CHECK_RELATIVE_ERROR(boost::math::lambert_w0(T(wolfram_test_small_neg[i][0])), T(wolfram_test_small_neg[i][1]), tolerance); } } @@ -241,7 +237,7 @@ void wolfram_test_large(const std::true_type&) tolerance *= 3; // arbitrary precision types have lower accuracy on exp(z). for (unsigned i = 0; i < wolfram_test_large_data.size(); ++i) { - BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w0(T(wolfram_test_large_data[i][0])), T(wolfram_test_large_data[i][1]), tolerance); + CHECK_RELATIVE_ERROR(boost::math::lambert_w0(T(wolfram_test_large_data[i][0])), T(wolfram_test_large_data[i][1]), tolerance); } } template @@ -273,7 +269,7 @@ void wolfram_test_near_singularity() if (wolfram_test_near_singularity_data[i][0] <= endpoint) break; else - BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w0(T(wolfram_test_near_singularity_data[i][0])), T(wolfram_test_near_singularity_data[i][1]), tolerance); + CHECK_RELATIVE_ERROR(boost::math::lambert_w0(T(wolfram_test_near_singularity_data[i][0])), T(wolfram_test_near_singularity_data[i][1]), tolerance); } } @@ -295,7 +291,7 @@ void wolfram_test_near_singularity() if (wolfram_test_near_singularity_data[i][0] <= endpoint) break; else - BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w0(wolfram_test_near_singularity_data[i][0]), wolfram_test_near_singularity_data[i][1], tolerance); + CHECK_RELATIVE_ERROR(boost::math::lambert_w0(wolfram_test_near_singularity_data[i][0]), wolfram_test_near_singularity_data[i][1], tolerance); } } @@ -321,7 +317,7 @@ void wolfram_test_near_singularity() if (wolfram_test_near_singularity_data[i][0] <= endpoint) break; else - BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w0(wolfram_test_near_singularity_data[i][0]), wolfram_test_near_singularity_data[i][1], tolerance); + CHECK_RELATIVE_ERROR(boost::math::lambert_w0(wolfram_test_near_singularity_data[i][0]), wolfram_test_near_singularity_data[i][1], tolerance); } } @@ -350,24 +346,24 @@ void test_spots(RealType) // Test some bad parameters to the function, with default policy and also with ignore_all policy. #ifndef BOOST_NO_EXCEPTIONS - BOOST_CHECK_THROW(lambert_w0(-1.), std::domain_error); - BOOST_CHECK_THROW(lambert_wm1(-1.), std::domain_error); - BOOST_CHECK_THROW(lambert_wm1(1.), std::domain_error); + CHECK_THROW(lambert_w0(-1.), std::domain_error); + CHECK_THROW(lambert_wm1(-1.), std::domain_error); + CHECK_THROW(lambert_wm1(1.), std::domain_error); if (std::numeric_limits::has_denorm) { - BOOST_CHECK_THROW(lambert_wm1(-std::numeric_limits::denorm_min()), std::overflow_error); + CHECK_THROW(lambert_wm1(-std::numeric_limits::denorm_min()), std::overflow_error); } if (std::numeric_limits::has_quiet_NaN) { - BOOST_CHECK_THROW(lambert_w0(std::numeric_limits::quiet_NaN()), std::domain_error); // Would be NaN. + CHECK_THROW(lambert_w0(std::numeric_limits::quiet_NaN()), std::domain_error); // Would be NaN. //BOOST_CHECK_EQUAL(lambert_w0(std::numeric_limits::quiet_NaN(), ignore_all_policy()), std::numeric_limits::quiet_NaN()); // Should be NaN. // Fails as NaN != NaN by definition. - BOOST_CHECK(boost::math::isnan(lambert_w0(std::numeric_limits::quiet_NaN(), ignore_all_policy()))); + CHECK_TRUE(boost::math::isnan(lambert_w0(std::numeric_limits::quiet_NaN(), ignore_all_policy()))); //BOOST_MATH_CHECK_EQUAL(boost::math::lambert_w0(std::numeric_limits::infinity(), ignore_all_policy()), std::numeric_limits(std::numeric_limits::infinity()), std::domain_error); // Was if infinity should throw, now infinity. - BOOST_CHECK_THROW(lambert_w0(-static_cast(0.4)), std::domain_error); // Would be complex. + CHECK_THROW(lambert_w0(-static_cast(0.4)), std::domain_error); // Would be complex. #else // No exceptions, so set policy to ignore and check result is NaN. BOOST_MATH_CHECK_EQUAL(boost::math::lambert_w0(std::numeric_limits::quiet_NaN(), ignore_all_policy()), std::numeric_limits > : // Error in function boost::math::lambert_w0() : Argument z is infinite! //BOOST_CHECK_EQUAL(lambert_w0(std::numeric_limits::infinity()), +std::numeric_limits::infinity()); // If infinity allowed. - BOOST_CHECK_THROW(lambert_wm1(std::numeric_limits::infinity()), std::domain_error); // Infinity NOT allowed at all (not an edge case). + CHECK_THROW(lambert_wm1(std::numeric_limits::infinity()), std::domain_error); // Infinity NOT allowed at all (not an edge case). } if (std::numeric_limits::has_quiet_NaN) { // Argument Z == NaN is always an throwable error for both branches. // BOOST_CHECK_EQUAL(lambert_w0(std::numeric_limits::quiet_NaN()), +std::numeric_limits::infinity()); // message is: // Error in function boost::math::lambert_w0(): Argument z is NaN! - BOOST_CHECK_THROW(lambert_w0(std::numeric_limits::quiet_NaN()), std::domain_error); - BOOST_CHECK_THROW(lambert_wm1(std::numeric_limits::quiet_NaN()), std::domain_error); + CHECK_THROW(lambert_w0(std::numeric_limits::quiet_NaN()), std::domain_error); + CHECK_THROW(lambert_wm1(std::numeric_limits::quiet_NaN()), std::domain_error); } // denorm - but might be == min or zero? if (boost::math::detail::has_denorm_now()) { // Might also return infinity like z == 0? - BOOST_CHECK_THROW(lambert_wm1(std::numeric_limits::denorm_min()), std::overflow_error); + CHECK_THROW(lambert_wm1(std::numeric_limits::denorm_min()), std::overflow_error); } // Tests of Lambert W-1 branch. - BOOST_CHECK_CLOSE_FRACTION( // Check -exp(-1) ~= -0.367879450 == -1 at the singularity branch point. + CHECK_RELATIVE_ERROR( // Check -exp(-1) ~= -0.367879450 == -1 at the singularity branch point. lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.36787944117144232159552377016146086744581113103176783450783680169746149574489980335714727434591964374662732527)), BOOST_MATH_TEST_VALUE(RealType, -1.), tolerance); // Near singularity and using series approximation. // N[productlog(-1, -0.36), 50] = -1.2227701339785059531429380734238623131735264411311 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.36)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.36)), BOOST_MATH_TEST_VALUE(RealType, -1.2227701339785059531429380734238623131735264411311), 10 * tolerance); // tolerance OK for quad // -1.2227701339785059531429380734238623131735264411311 @@ -517,7 +513,7 @@ void test_spots(RealType) // Just using series approximation (switch at -0.35). // N[productlog(-0.351), 50] = -0.72398644140937651483634596143951001600417138085814 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.351)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.351)), BOOST_MATH_TEST_VALUE(RealType, -0.72398644140937651483634596143951001600417138085814), // 2 * tolerance); // Note 2 * tolerance for PB fukushima // got -0.723986441409376931150560229265736446 without Halley @@ -528,63 +524,63 @@ void test_spots(RealType) // Float is OK // Same for W-1 branch - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.351)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.351)), BOOST_MATH_TEST_VALUE(RealType, -1.3385736984773431852492145715526995809854973408320), 10 * tolerance); // 2 tolerance OK for quad // Near singularity and NOT using series approximation (switch at -0.35) // N[productlog(-1, -0.34), 50] - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.34)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.34)), BOOST_MATH_TEST_VALUE(RealType, -1.4512014851325470735077533710339268100722032730024), 10 * tolerance); // tolerance OK for quad // // Decreasing z until near zero (small z) . //N[productlog(-1, -0.3), 50] = -1.7813370234216276119741702815127452608215583564545 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.3)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.3)), BOOST_MATH_TEST_VALUE(RealType, -1.7813370234216276119741702815127452608215583564545), 2 * tolerance); // -1.78133702342162761197417028151274526082155835645446 //N[productlog(-1, -0.2), 50] = -2.5426413577735264242938061566618482901614749075294 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.2)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.2)), BOOST_MATH_TEST_VALUE(RealType, -2.5426413577735264242938061566618482901614749075294), 2 * tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.1)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.1)), BOOST_MATH_TEST_VALUE(RealType, -3.577152063957297218409391963511994880401796257793), tolerance); //N[productlog(-1, -0.01), 50] = -6.4727751243940046947410578927244880371043455902257 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.01)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.01)), BOOST_MATH_TEST_VALUE(RealType, -6.4727751243940046947410578927244880371043455902257), tolerance); // N[productlog(-1, -0.001), 50] = -9.1180064704027401212583371820468142742704349737639 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.001)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.001)), BOOST_MATH_TEST_VALUE(RealType, -9.1180064704027401212583371820468142742704349737639), tolerance); // N[productlog(-1, -0.000001), 50] = -16.626508901372473387706432163984684996461726803805 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.000001)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.000001)), BOOST_MATH_TEST_VALUE(RealType, -16.626508901372473387706432163984684996461726803805), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-12)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-12)), BOOST_MATH_TEST_VALUE(RealType, -31.067172842017230842039496250208586707880448763222), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-25)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-25)), BOOST_MATH_TEST_VALUE(RealType, -61.686695602074505366866968627049381352503620377944), tolerance); // z nearly too small. - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -2e-26)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -2e-26)), BOOST_MATH_TEST_VALUE(RealType, -63.322302839923597803393585145387854867226970485197), tolerance* 2); // z very nearly too small. G(k=64) g[63] = -1.0264389699511303e-26 to using 1.027e-26 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.027e-26)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.027e-26)), BOOST_MATH_TEST_VALUE(RealType, -63.999444896732265186957073549916026532499356695343), tolerance); // So -64 is the most negative value that can be determined using lookup. @@ -593,189 +589,189 @@ void test_spots(RealType) // z too small for G(k=64) g[63] = -1.0264389699511303e-26 to using 1.027e-26 // N[productlog(-1, -10 ^ -26), 50] = -31.067172842017230842039496250208586707880448763222 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-26)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-26)), BOOST_MATH_TEST_VALUE(RealType, -64.026509628385889681156090340691637712441162092868), tolerance); // -64.0265121 #ifndef BOOST_MATH_NO_EXCEPTIONS - BOOST_CHECK_THROW(lambert_wm1(0), std::overflow_error); + CHECK_THROW(lambert_wm1(0), std::overflow_error); #else - BOOST_CHECK_EQUAL(lambert_wm1(0), -std::numeric_limits::infinity()); + CHECK_EQUAL(lambert_wm1(0), -std::numeric_limits::infinity()); #endif if (std::numeric_limits::has_quiet_NaN) { // BOOST_CHECK_EQUAL(lambert_w0(std::numeric_limits::quiet_NaN()), +std::numeric_limits::infinity()); // message is: // Error in function boost::math::lambert_w0(): Argument z is NaN! - BOOST_CHECK_THROW(lambert_wm1(std::numeric_limits::quiet_NaN()), std::domain_error); + CHECK_THROW(lambert_wm1(std::numeric_limits::quiet_NaN()), std::domain_error); } // W0 Tests for too big and too small to use lookup table. // Exactly W = 64, not enough to be OK for lookup. - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 3.9904954117194348050619127737142206366920907815909119e+29)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 3.9904954117194348050619127737142206366920907815909119e+29)), BOOST_MATH_TEST_VALUE(RealType, 64.0), tolerance); // Just below z for F[64] - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 3.99045411719434e+29)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 3.99045411719434e+29)), BOOST_MATH_TEST_VALUE(RealType, 63.999989810930513468726486827408823607175844852495), tolerance); // Fails for quad_float -1.22277013397850595265 // -1.22277013397850595319 // Just too big, so using log approx and Halley refinement. - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 4e+29)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 4e+29)), BOOST_MATH_TEST_VALUE(RealType, 64.002342375637950350970694519073803643686041499677), tolerance); // Check at reduced precision. - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 4e+29), policy >()), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 4e+29), policy >()), BOOST_MATH_TEST_VALUE(RealType, 64.002342375637950350970694519073803643686041499677), - 0.00002); // 0.00001 fails. + static_cast(0.00002)); // 0.00001 fails. // Tests to ensure that all JM rational polynomials are being checked. // 1st polynomial if (z < 0.5) // 0.05 < z < 0.5 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.49)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.49)), BOOST_MATH_TEST_VALUE(RealType, 0.3465058086974944293540338951489158955895910665452626949), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.051)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.051)), BOOST_MATH_TEST_VALUE(RealType, 0.04858156174600359264950777241723801201748517590507517888), tolerance); // 2st polynomial if 0.5 < z < 2 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.51)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.51)), BOOST_MATH_TEST_VALUE(RealType, 0.3569144916935871518694242462560450385494399307379277704), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.9)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.9)), BOOST_MATH_TEST_VALUE(RealType, 0.8291763302658400337004358009672187071638421282477162293), tolerance); // 3rd polynomials 2 < z < 6 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 2.1)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 2.1)), BOOST_MATH_TEST_VALUE(RealType, 0.8752187586805470099843211502166029752154384079916131962), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 5.9)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 5.9)), BOOST_MATH_TEST_VALUE(RealType, 1.422521411785098213935338853943459424120416844150520831), tolerance); // 4th polynomials 6 < z < 18 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 6.1)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 6.1)), BOOST_MATH_TEST_VALUE(RealType, 1.442152194116056579987235881273412088690824214100254315), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 17.9)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 17.9)), BOOST_MATH_TEST_VALUE(RealType, 2.129100923757568114366514708174691237123820852409339147), tolerance); // 5th polynomials if (z < 9897.12905874) // 2.8 < log(z) < 9.2 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 18.1)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 18.1)), BOOST_MATH_TEST_VALUE(RealType, 2.136665501382339778305178680563584563343639180897328666), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 9897.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 9897.)), BOOST_MATH_TEST_VALUE(RealType, 7.222751047988674263127929506116648714752441161828893633), tolerance); // 6th polynomials if (z < 7.896296e+13) // 9.2 < log(z) <= 32 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 9999.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 9999.)), BOOST_MATH_TEST_VALUE(RealType, 7.231758181708737258902175236106030961433080976032516996), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 7.7e+13)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 7.7e+13)), BOOST_MATH_TEST_VALUE(RealType, 28.62069643025822480911439831021393125282095606713326376), tolerance); // 7th polynomial // 32 < log(z) < 100 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 8.0e+18)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 8.0e+18)), BOOST_MATH_TEST_VALUE(RealType, 39.84107480517853176296156400093560722439428484537515586), tolerance); // Largest 32-bit float. (Larger values for other types tested using max()) - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.e38)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.e38)), BOOST_MATH_TEST_VALUE(RealType, 83.07844821316409592720410446942538465411465113447713574), tolerance); // Using z small series function if z < 0.05 if (z < -0.051) -0.27 < z < -0.051 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.28)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.28)), BOOST_MATH_TEST_VALUE(RealType, -0.4307588745271127579165306568413721388196459822705155385), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.25)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.25)), BOOST_MATH_TEST_VALUE(RealType, -0.3574029561813889030688111040559047533165905550760120436), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, +0.25)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, +0.25)), BOOST_MATH_TEST_VALUE(RealType, 0.2038883547022401644431818313271398701493524772101596350), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.051)), // just above 0.05 cutoff. + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.051)), // just above 0.05 cutoff. BOOST_MATH_TEST_VALUE(RealType, -0.05382002772543396036830469500362485089791914689728115249), tolerance * 4); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.05)), // at cutoff. + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.05)), // at cutoff. BOOST_MATH_TEST_VALUE(RealType, -0.05270598355154634795995650617915721289427674396592395160), tolerance * 8); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.049)), // Just below cutoff. + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.049)), // Just below cutoff. BOOST_MATH_TEST_VALUE(RealType, 0.04676143671340832342497289393737051868103596756298863555), tolerance * 4); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.01)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.01)), BOOST_MATH_TEST_VALUE(RealType, 0.009901473843595011885336326816570107953627746494917415483), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.01)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.01)), BOOST_MATH_TEST_VALUE(RealType, -0.01010152719853875327292018767138623973670903993475235877), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.049)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.049)), BOOST_MATH_TEST_VALUE(RealType, -0.05159448479219405354564920228913331280713177046648170658), tolerance * 8); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1e-6)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1e-6)), BOOST_MATH_TEST_VALUE(RealType, 9.999990000014999973333385416558666900096702096424344715e-7), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -1e-6)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -1e-6)), BOOST_MATH_TEST_VALUE(RealType, -1.000001000001500002666671875010800023343107568372593753e-6), tolerance); // Near Smallest float. - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1e-38)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1e-38)), BOOST_MATH_TEST_VALUE(RealType, 9.99999999999999999999999999999999999990000000000000000e-39), tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -1e-38)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -1e-38)), BOOST_MATH_TEST_VALUE(RealType, -1.000000000000000000000000000000000000010000000000000000e-38), tolerance); // Similar 'too near zero' tests for W-1 branch. // lambert_wm1(-1.0264389699511283e-26) = -64.000000000000000 // Exactly z for W=-64 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.026438969951128225904695701851094643838952857740385870e-26)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.026438969951128225904695701851094643838952857740385870e-26)), BOOST_MATH_TEST_VALUE(RealType, -64.000000000000000000000000000000000000), 2 * tolerance); // Just more negative than G[64 max] = wm1zs[63] so can't use lookup table. - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.5e-27)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.5e-27)), BOOST_MATH_TEST_VALUE(RealType, -65.953279000145077719128800110134854577850889171784), tolerance); // -65.9532776 // Just less negative than G[64 max] = wm1zs[63] so can use lookup table. - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.1e-26)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.1e-26)), BOOST_MATH_TEST_VALUE(RealType, -63.929686062157630858625440758283127600360210072859), tolerance); // N[productlog(-1, -10 ^ -26), 50] = -31.067172842017230842039496250208586707880448763222 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-26)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-26)), BOOST_MATH_TEST_VALUE(RealType, -64.026509628385889681156090340691637712441162092868), tolerance); // 1e-28 is too small // N[productlog(-1, -10 ^ -28), 50] = -31.067172842017230842039496250208586707880448763222 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-28)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-28)), BOOST_MATH_TEST_VALUE(RealType, -68.702163291525429160769761667024460023336801014578), tolerance); @@ -790,10 +786,10 @@ void test_spots(RealType) // : Error in function boost::math::lambert_wm1() : // Argument z = -1.00000002e+30 out of range(z < -exp(-1) = -3.6787944) for Lambert W - 1 branch! - BOOST_CHECK_THROW(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e30)), std::domain_error); + CHECK_THROW(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e30)), std::domain_error); // Too negative - BOOST_CHECK_THROW(lambert_wm1(RealType(-0.5)), std::domain_error); + CHECK_THROW(lambert_wm1(RealType(-0.5)), std::domain_error); // This fails for fixed_point type used for other tests because out of range? //BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.0e6)), @@ -806,18 +802,18 @@ void test_spots(RealType) // So need to use some spot tests for specific types, or use a bigger fixed_point type. // Check zero. - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.0)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.0)), BOOST_MATH_TEST_VALUE(RealType, 0.0), tolerance); // // Extra coverage: // - BOOST_CHECK_EQUAL(boost::math::lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, 0.0)), BOOST_MATH_TEST_VALUE(RealType, 1.0)); + CHECK_EQUAL(boost::math::lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, 0.0)), BOOST_MATH_TEST_VALUE(RealType, 1.0)); #ifndef BOOST_MATH_NO_EXEPTIONS - BOOST_CHECK_THROW(boost::math::lambert_w0_prime(-boost::math::constants::exp_minus_one()), std::overflow_error); - BOOST_CHECK_THROW(boost::math::lambert_wm1_prime(-boost::math::constants::exp_minus_one()), std::overflow_error); - BOOST_CHECK_THROW(boost::math::lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, 0.0)), std::overflow_error); + CHECK_THROW(boost::math::lambert_w0_prime(-boost::math::constants::exp_minus_one()), std::overflow_error); + CHECK_THROW(boost::math::lambert_wm1_prime(-boost::math::constants::exp_minus_one()), std::overflow_error); + CHECK_THROW(boost::math::lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, 0.0)), std::overflow_error); #endif // these fail for cpp_dec_float_50 @@ -827,15 +823,13 @@ void test_spots(RealType) } // template void test_spots(RealType) -BOOST_AUTO_TEST_CASE( test_types ) +void test_types() { BOOST_MATH_CONTROL_FP; // BOOST_TEST_MESSAGE output only appears if command line has --log_level="message" // or call set_threshold_level function: // boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test_framework::log_messages); - BOOST_TEST_MESSAGE("\nTest Lambert W function for several types.\n"); - BOOST_TEST_MESSAGE(show_versions()); // Full version of Boost, STL and compiler info. #ifndef BOOST_MATH_TEST_MULTIPRECISION // Fundamental built-in types: test_spots(0.0F); // float @@ -889,12 +883,11 @@ BOOST_AUTO_TEST_CASE( test_types ) } // BOOST_AUTO_TEST_CASE( test_types ) -BOOST_AUTO_TEST_CASE( test_range_of_double_values ) +void test_range_of_double_values() { using boost::math::constants::exp_minus_one; using boost::math::lambert_w0; - BOOST_TEST_MESSAGE("\nTest Lambert W function type double for range of values."); // Want to test almost largest value. // test_value = (std::numeric_limits::max)() / 4; @@ -913,19 +906,19 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) std::cout << "Tolerance " << epsilons << " * epsilon == " << tolerance << std::endl; #ifndef BOOST_MATH_TEST_MULTIPRECISION - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.0e-6)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.0e-6)), BOOST_MATH_TEST_VALUE(RealType, 9.9999900000149999733333854165586669000967020964243e-7), // Output from https://www.wolframalpha.com/input/ N[lambert_w[1e-6],50]) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.0001)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.0001)), BOOST_MATH_TEST_VALUE(RealType, 0.000099990001499733385405869000452213835767629477903460), // Output from https://www.wolframalpha.com/input/ N[lambert_w[0.001],50]) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.001)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.001)), BOOST_MATH_TEST_VALUE(RealType, 0.00099900149733853088995782787410778559957065467928884), // Output from https://www.wolframalpha.com/input/ N[lambert_w[0.001],50]) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.01)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.01)), BOOST_MATH_TEST_VALUE(RealType, 0.0099014738435950118853363268165701079536277464949174), // Output from https://www.wolframalpha.com/input/ N[lambert_w[0.01],50]) tolerance * 25); // <<< Needs a much bigger tolerance??? @@ -938,58 +931,58 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) // 0.00990728209160670 approx // 0.00990147384359511 previous - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.05)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.05)), BOOST_MATH_TEST_VALUE(RealType, 0.047672308600129374726388900514160870747062965933891), // Output from https://www.wolframalpha.com/input/ N[lambert_w[0.01],50]) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.1)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 0.1)), BOOST_MATH_TEST_VALUE(RealType, 0.091276527160862264299895721423179568653119224051472), // Output from https://www.wolframalpha.com/input/ N[lambert_w[1],50]) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.)), BOOST_MATH_TEST_VALUE(RealType, 0.56714329040978387299996866221035554975381578718651), // Output from https://www.wolframalpha.com/input/ N[lambert_w[1],50]) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 2.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 2.)), BOOST_MATH_TEST_VALUE(RealType, 0.852605502013725491346472414695317466898453300151403508772), // Output from https://www.wolframalpha.com/input/?i=lambert_w0(2.) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 3.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 3.)), BOOST_MATH_TEST_VALUE(RealType, 1.049908894964039959988697070552897904589466943706341452932), // Output from https://www.wolframalpha.com/input/?i=lambert_w0(3.) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 5.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 5.)), BOOST_MATH_TEST_VALUE(RealType, 1.326724665242200223635099297758079660128793554638047479789), // Output from https://www.wolframalpha.com/input/?i=lambert_w0(0.5) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 6.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 6.)), BOOST_MATH_TEST_VALUE(RealType, 1.432404775898300311234078007212058694786434608804302025655), // Output from https://www.wolframalpha.com/input/?i=lambert_w0(6) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 10.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 10.)), BOOST_MATH_TEST_VALUE(RealType, 1.7455280027406993830743012648753899115352881290809), // Output from https://www.wolframalpha.com/input/ N[lambert_w[10],50]) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 100.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 100.)), BOOST_MATH_TEST_VALUE(RealType, 3.3856301402900501848882443645297268674916941701578), // Output from https://www.wolframalpha.com/input/?i=lambert_w0(100) tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1000.)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1000.)), BOOST_MATH_TEST_VALUE(RealType, 5.2496028524015962271260563196973062825214723860596), // Output from https://www.wolframalpha.com/input/?i=lambert_w0(1000) tolerance); // This fails for fixed_point type used for other tests because out of range of the type? - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.0e6)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, 1.0e6)), BOOST_MATH_TEST_VALUE(RealType, 11.383358086140052622000156781585004289033774706019), // Output from https://www.wolframalpha.com/input/?i=lambert_w0(1e6) tolerance); // @@ -1007,30 +1000,30 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) // unknown location : fatal error : in "test_range_of_values": class boost::exception_detail::clone_impl >: Error in function boost::math::lambert_w0(): Argument z = %1 too large. // I:\modular - boost\libs\math\test\test_lambert_w.cpp(456) : last checkpoint - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(1.7976931348623157e+308 ), // max_value for IEEE 64-bit double. + CHECK_RELATIVE_ERROR(lambert_w0(1.7976931348623157e+308 ), // max_value for IEEE 64-bit double. static_cast(703.2270331047701868711791887193075929608934699575820028L), // N[productlog[0, 1.7976931348623157*10^308 /2],50] == 702.53487067487671916110655783739076368512998658347 tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(1.7976931348623157e+308 / 2), // max_value/2 for IEEE 64-bit double. + CHECK_RELATIVE_ERROR(lambert_w0(1.7976931348623157e+308 / 2), // max_value/2 for IEEE 64-bit double. static_cast(702.53487067487671916110655783739076368512998658347L), // N[productlog[0, 1.7976931348623157*10^308 /2],50] == 702.53487067487671916110655783739076368512998658347 tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(1.7976931348623157e+308 /4), // near max_value/4 for IEEE 64-bit double. + CHECK_RELATIVE_ERROR(lambert_w0(1.7976931348623157e+308 /4), // near max_value/4 for IEEE 64-bit double. static_cast(701.8427092142920014223182853764045476L), // N[productlog(0, 1.7976931348623157* 10^308 /4 ), 37] =701.8427092142920014223182853764045476 // N[productlog(0, 0.25 * 1.7976931348623157*10^307), 37] tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(4.4942328371557893e+307), // max_value/4 for IEEE 64-bit double. + CHECK_RELATIVE_ERROR(lambert_w0(4.4942328371557893e+307), // max_value/4 for IEEE 64-bit double. static_cast(701.84270921429200143342782556643059L), // N[lambert_w[4.4942328371557893e+307], 35] == 701.8427092142920014334278255664305887 // as a double == 701.83341468208209 // Lambert computed 702.02379914670587 0.000003); // OK Much less precise at the max edge??? - BOOST_CHECK_CLOSE_FRACTION(lambert_w0((std::numeric_limits::max)()), // max_value for IEEE 64-bit double. + CHECK_RELATIVE_ERROR(lambert_w0((std::numeric_limits::max)()), // max_value for IEEE 64-bit double. static_cast(703.2270331047701868711791887193075930), // N[productlog(0, 1.7976931348623157* 10^308), 37] = 703.2270331047701868711791887193075930 // 703.22700325995515 lambert W @@ -1042,7 +1035,7 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) // (below which the result has a non-zero imaginary part). RealType test_value = -exp_minus_one(); test_value += (std::numeric_limits::epsilon() * 1); - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(test_value), + CHECK_RELATIVE_ERROR(lambert_w0(test_value), BOOST_MATH_TEST_VALUE(RealType, -0.99999996349975895), tolerance * 1000000000); // -0.99999996788201051 @@ -1053,12 +1046,12 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) // Can only compare float_next for specific type T = double. // Comparison with Wolfram N[productlog(0,-0.36787944117144228 ), 17] // Note big loss of precision and big tolerance needed to pass. - BOOST_CHECK_CLOSE_FRACTION( // Check float_next(-exp(-1) ) + CHECK_RELATIVE_ERROR( // Check float_next(-exp(-1) ) lambert_w0(BOOST_MATH_TEST_VALUE(double, -0.36787944117144228)), BOOST_MATH_TEST_VALUE(RealType, -0.99999998496215738), 1e8 * tolerance); // diff 6.03558e-09 v 2.2204460492503131e-16 - BOOST_CHECK_CLOSE_FRACTION( // Check float_next(float_next(-exp(-1) )) + CHECK_RELATIVE_ERROR( // Check float_next(float_next(-exp(-1) )) lambert_w0(BOOST_MATH_TEST_VALUE(double, -0.36787944117144222)), BOOST_MATH_TEST_VALUE(RealType, -0.99999997649828679), 5e7 * tolerance);// diff 2.30785e-09 v 2.2204460492503131e-16 @@ -1069,7 +1062,7 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) RealType w0 = lambert_w0(x); RealType w0_prime = boost::math::lambert_w0_prime(x); RealType mu = std::numeric_limits::epsilon()/2; - BOOST_CHECK_CLOSE_FRACTION( // Check float_next(-exp(-1) ) + CHECK_RELATIVE_ERROR( // Check float_next(-exp(-1) ) w0, BOOST_MATH_TEST_VALUE(RealType, -0.9999999849621573837115797120602890516186071783122773515945338502828025975466699519609633476854139977), 2*mu*abs(x*w0_prime/w0)); // diff 6.03558e-09 v 2.2204460492503131e-16 @@ -1077,77 +1070,77 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) x = BOOST_MATH_TEST_VALUE(RealType, -0.36787944117144222); w0 = lambert_w0(x); w0_prime = boost::math::lambert_w0_prime(x); - BOOST_CHECK_CLOSE_FRACTION( // Check float_next(float_next(-exp(-1) )) + CHECK_RELATIVE_ERROR( // Check float_next(float_next(-exp(-1) )) w0, BOOST_MATH_TEST_VALUE(RealType, -0.99999997419043196), 2*mu*abs(x*w0_prime/w0));// diff 2.30785e-09 v 2.2204460492503131e-16 // z increasingly close to singularity. - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.36)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.36)), BOOST_MATH_TEST_VALUE(RealType, -0.8060843159708177782855213616209920019974599683466713016), 2 * tolerance); // -0.806084335 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.365)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.365)), BOOST_MATH_TEST_VALUE(RealType, -0.8798200914159538111724840007674053239388642469453350954), 5 * tolerance); // Note 5 * tolerance - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.3678)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.3678)), BOOST_MATH_TEST_VALUE(RealType, -0.9793607149578284774761844434886481686055949229547379368), 15 * tolerance); // Note 15 * tolerance when this close to singularity. // Just using series approximation (Fukushima switch at -0.35, but JM at 0.01 of singularity < -0.3679). // N[productlog(-0.351), 50] = -0.72398644140937651483634596143951001600417138085814 // N[productlog(-0.351), 55] = -0.7239864414093765148363459614395100160041713808581379727 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.351)), + CHECK_RELATIVE_ERROR(lambert_w0(BOOST_MATH_TEST_VALUE(RealType, -0.351)), BOOST_MATH_TEST_VALUE(RealType, -0.72398644140937651483634596143951001600417138085814), 10 * tolerance); // Note was 2 * tolerance // Check value just not using near_singularity series approximation (and using rational polynomial instead). - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.3)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.3)), BOOST_MATH_TEST_VALUE(RealType, -1.7813370234216276119741702815127452608215583564545), // Output from https://www.wolframalpha.com/input/ //N[productlog(-1, -0.3), 50] = -1.7813370234216276119741702815127452608215583564545 tolerance); // Using table lookup and schroeder with decreasing z to zero. - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.2)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.2)), BOOST_MATH_TEST_VALUE(RealType, -2.5426413577735264242938061566618482901614749075294), // N[productlog[-1, -0.2],50] -2.5426413577735264242938061566618482901614749075294 tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.1)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.1)), BOOST_MATH_TEST_VALUE(RealType, -3.5771520639572972184093919635119948804017962577931), //N[productlog(-1, -0.1), 50] = -3.5771520639572972184093919635119948804017962577931 tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.001)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.001)), BOOST_MATH_TEST_VALUE(RealType, -9.1180064704027401212583371820468142742704349737639), // N[productlog(-1, -0.001), 50] = -9.1180064704027401212583371820468142742704349737639 tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.000001)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -0.000001)), BOOST_MATH_TEST_VALUE(RealType, -16.626508901372473387706432163984684996461726803805), // N[productlog(-1, -0.000001), 50] = -16.626508901372473387706432163984684996461726803805 tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-6)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-6)), BOOST_MATH_TEST_VALUE(RealType, -16.626508901372473387706432163984684996461726803805), // N[productlog(-1, -10 ^ -6), 50] = -16.626508901372473387706432163984684996461726803805 tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.0e-26)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1.0e-26)), BOOST_MATH_TEST_VALUE(RealType, -64.026509628385889681156090340691637712441162092868), // Output from https://www.wolframalpha.com/input/ // N[productlog(-1, -1 * 10^-26 ), 50] = -64.026509628385889681156090340691637712441162092868 tolerance); - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -2e-26)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -2e-26)), BOOST_MATH_TEST_VALUE(RealType, -63.322302839923597803393585145387854867226970485197), // N[productlog[-1, -2*10^-26],50] = -63.322302839923597803393585145387854867226970485197 tolerance * 2); // Smaller than lookup table, so must use approx and Halley refinements. - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-30)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -1e-30)), BOOST_MATH_TEST_VALUE(RealType, -73.373110313822976797067478758120874529181611813766), // N[productlog(-1, -10 ^ -30), 50] = -73.373110313822976797067478758120874529181611813766 tolerance); @@ -1158,7 +1151,7 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) #endif std::cout << "(std::numeric_limits::min)() " << (std::numeric_limits::min)() << std::endl; - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -2.2250738585072014e-308)), + CHECK_RELATIVE_ERROR(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, -2.2250738585072014e-308)), BOOST_MATH_TEST_VALUE(RealType, -714.96865723796647086868547560654825435542227693935), // N[productlog[-1, -2.2250738585072014e-308],50] = -714.96865723796647086868547560654825435542227693935 tolerance); @@ -1167,9 +1160,9 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) if (std::numeric_limits::has_infinity) { #ifndef BOOST_MATH_NO_EXCEPTIONS - BOOST_CHECK_THROW(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, 0.)), std::overflow_error); + CHECK_THROW(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, 0.)), std::overflow_error); #else - BOOST_CHECK_EQUAL(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, 0.)), -std::numeric_limits::infinity()); + CHECK_EQUAL(lambert_wm1(BOOST_MATH_TEST_VALUE(RealType, 0.)), -std::numeric_limits::infinity()); #endif } @@ -1178,15 +1171,21 @@ BOOST_AUTO_TEST_CASE( test_range_of_double_values ) // Comparison with Wolfram N[productlog(0,-0.36787944117144228 ), 17] // Using conversion from double to higher precision cpp_bin_float_quad using boost::multiprecision::cpp_bin_float_quad; - BOOST_CHECK_CLOSE_FRACTION( // Check float_next(-exp(-1) ) + CHECK_RELATIVE_ERROR( // Check float_next(-exp(-1) ) lambert_w0(BOOST_MATH_TEST_VALUE(cpp_bin_float_quad, -0.36787944117144228)), BOOST_MATH_TEST_VALUE(cpp_bin_float_quad, -0.99999998496215738), tolerance); // OK - BOOST_CHECK_CLOSE_FRACTION( // Check float_next(float_next(-exp(-1) )) + CHECK_RELATIVE_ERROR( // Check float_next(float_next(-exp(-1) )) lambert_w0(BOOST_MATH_TEST_VALUE(cpp_bin_float_quad, -0.36787944117144222)), BOOST_MATH_TEST_VALUE(cpp_bin_float_quad, -0.99999997649828679), tolerance);// OK #endif } // BOOST_AUTO_TEST_CASE(test_range_of_double_values) +int main() +{ + test_types(); + test_range_of_double_values(); + return boost::math::test::report_errors(); +} diff --git a/test/test_lambert_w_derivative.cpp b/test/test_lambert_w_derivative.cpp index 55e1a29a32..addd1ecdd6 100644 --- a/test/test_lambert_w_derivative.cpp +++ b/test/test_lambert_w_derivative.cpp @@ -28,11 +28,7 @@ #include // for BOOST_MSVC versions. // Boost macros -#define BOOST_TEST_MAIN -#define BOOST_LIB_DIAGNOSTIC "on" // Report library file details. -#include // Boost.Test -// #include // Boost.Test -#include +#include "math_unit_test.hpp" #include #include @@ -81,10 +77,9 @@ using boost::math::lambert_w0; std::string show_versions(void); -BOOST_AUTO_TEST_CASE( Derivatives_of_lambert_w ) +void Derivatives_of_lambert_w() { std::cout << "Macro BOOST_MATH_LAMBERT_W_DERIVATIVES to test 1st derivatives is defined." << std::endl; - BOOST_TEST_MESSAGE("\nTest Lambert W function 1st differentials."); using boost::math::constants::exp_minus_one; using boost::math::lambert_w0_prime; @@ -108,22 +103,22 @@ BOOST_AUTO_TEST_CASE( Derivatives_of_lambert_w ) // (derivative of N[productlog(-1, x), 55] ) at x = N[-0.1, 55] // W0 branch - BOOST_CHECK_CLOSE_FRACTION(lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, -0.2)), + CHECK_RELATIVE_ERROR(lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, -0.2)), // BOOST_MATH_TEST_VALUE(RealType, 1.7491967609218355), BOOST_MATH_TEST_VALUE(RealType, 1.7491967609218358355273514903396335693828167746571404), tolerance); // 1.7491967609218358355273514903396335693828167746571404 - BOOST_CHECK_CLOSE_FRACTION(lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, 10.)), + CHECK_RELATIVE_ERROR(lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, 10.)), BOOST_MATH_TEST_VALUE(RealType, 0.063577133469345105142021311010780887641928338458371618), tolerance); // W-1 branch - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, -0.1)), + CHECK_RELATIVE_ERROR(lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, -0.1)), BOOST_MATH_TEST_VALUE(RealType, -13.880252213229780748699361486619519025203815492277715), tolerance); // Lambert W_prime -13.880252213229780748699361486619519025203815492277715, double -13.880252213229781 - BOOST_CHECK_CLOSE_FRACTION(lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, -0.2)), + CHECK_RELATIVE_ERROR(lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, -0.2)), BOOST_MATH_TEST_VALUE(RealType, -8.2411940564179044961885598641955579728547896392013239), tolerance); // Lambert W_prime -8.2411940564179044961885598641955579728547896392013239, double -8.2411940564179051 @@ -131,4 +126,8 @@ BOOST_AUTO_TEST_CASE( Derivatives_of_lambert_w ) // Lambert W_prime 0.063577133469345105142021311010780887641928338458371618, double 0.063577133469345098 }; // BOOST_AUTO_TEST_CASE("Derivatives of lambert_w") - +int main() +{ + Derivatives_of_lambert_w(); + return boost::math::test::report_errors(); +} diff --git a/test/test_lambert_w_integrals_double.cpp b/test/test_lambert_w_integrals_double.cpp index ac3f8b610a..0ff18519c8 100644 --- a/test/test_lambert_w_integrals_double.cpp +++ b/test/test_lambert_w_integrals_double.cpp @@ -13,11 +13,7 @@ #include // for BOOST_MSVC versions. // Boost macros -#define BOOST_TEST_MAIN -#define BOOST_LIB_DIAGNOSTIC "on" // Report library file details. -#include // Boost.Test -// #include // Boost.Test -#include +#include "math_unit_test.hpp" #include #include @@ -134,7 +130,7 @@ void test_integrals() return lambert_w0(z); }; Real z = ts.integrate(f, a, b); // OK without any decltype(f) - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::e() - 1, tol); + CHECK_RELATIVE_ERROR(z, boost::math::constants::e() - 1, tol); } { // Integrate for function lambert_W0(z/(z sqrt(z)). @@ -144,7 +140,7 @@ void test_integrals() return lambert_w0(z)/(z * sqrt(z)); }; Real z = es.integrate(f); // OK - BOOST_CHECK_CLOSE_FRACTION(z, 2 * boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, 2 * boost::math::constants::root_two_pi(), tol); } { // Integrate for function lambert_W0(1/z^2). @@ -163,15 +159,14 @@ void test_integrals() } }; Real z = es.integrate(f); - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, boost::math::constants::root_two_pi(), tol); } } // template void test_integrals() -BOOST_AUTO_TEST_CASE( integrals ) +void integrals() { std::cout << "Macro BOOST_MATH_LAMBERT_W0_INTEGRALS is defined." << std::endl; - BOOST_TEST_MESSAGE("\nTest Lambert W0 integrals."); try { // using statements needed to change precision policy. @@ -250,7 +245,7 @@ Real x; // Unexpected exception thrown in integration code at abscissa (x): 3.478765835953569e-23. x = es.integrate(f); std::cout << "es.integrate(f) = " << x << std::endl; - BOOST_CHECK_CLOSE_FRACTION(x, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(x, boost::math::constants::root_two_pi(), tol); // root_two_pi // for BOOST_MSVC versions. // Boost macros -#define BOOST_TEST_MAIN -#define BOOST_LIB_DIAGNOSTIC "on" // Report library file details. -#include // Boost.Test -// #include // Boost.Test -#include +#include "math_unit_test.hpp" #include #include @@ -134,7 +130,7 @@ void test_integrals() return lambert_w0(z); }; Real z = ts.integrate(f, a, b); // OK without any decltype(f) - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::e() - 1, tol * 3); + CHECK_RELATIVE_ERROR(z, boost::math::constants::e() - 1, tol * 3); } { // Integrate for function lambert_W0(z/(z sqrt(z)). @@ -144,7 +140,7 @@ void test_integrals() return lambert_w0(z)/(z * sqrt(z)); }; Real z = es.integrate(f); // OK - BOOST_CHECK_CLOSE_FRACTION(z, 2 * boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, 2 * boost::math::constants::root_two_pi(), tol); } { // Integrate for function lambert_W0(1/z^2). @@ -163,15 +159,14 @@ void test_integrals() } }; Real z = es.integrate(f); - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, boost::math::constants::root_two_pi(), tol); } } // template void test_integrals() -BOOST_AUTO_TEST_CASE( integrals ) +void integrals() { std::cout << "Macro BOOST_MATH_LAMBERT_W0_INTEGRALS is defined." << std::endl; - BOOST_TEST_MESSAGE("\nTest Lambert W0 integrals."); try { // using statements needed to change precision policy. @@ -251,7 +246,7 @@ Real x; // Unexpected exception thrown in integration code at abscissa (x): 3.478765835953569e-23. x = es.integrate(f); std::cout << "es.integrate(f) = " << x << std::endl; - BOOST_CHECK_CLOSE_FRACTION(x, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(x, boost::math::constants::root_two_pi(), tol); // root_two_pi // Boost.Test -#include +#include "math_unit_test.hpp" #include #include @@ -149,7 +146,7 @@ void test_integrals() return lambert_w0(z); }; Real z = ts.integrate(f, a, b); // OK without any decltype(f) - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::e() - 1, tol); + CHECK_RELATIVE_ERROR(z, boost::math::constants::e() - 1, tol); } { // Integrate for function lambert_W0(z/(z sqrt(z)). @@ -159,7 +156,7 @@ void test_integrals() return lambert_w0(z)/(z * sqrt(z)); }; Real z = es.integrate(f); // OK - BOOST_CHECK_CLOSE_FRACTION(z, 2 * boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, 2 * boost::math::constants::root_two_pi(), tol); } { // Integrate for function lambert_W0(1/z^2). @@ -178,15 +175,14 @@ void test_integrals() } }; Real z = es.integrate(f); - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, boost::math::constants::root_two_pi(), tol); } } // template void test_integrals() -BOOST_AUTO_TEST_CASE( integrals ) +void integrals() { std::cout << "Macro BOOST_MATH_LAMBERT_W0_INTEGRALS is defined." << std::endl; - BOOST_TEST_MESSAGE("\nTest Lambert W0 integrals."); try { // using statements needed to change precision policy. @@ -266,7 +262,7 @@ Real x; // Unexpected exception thrown in integration code at abscissa (x): 3.478765835953569e-23. x = es.integrate(f); std::cout << "es.integrate(f) = " << x << std::endl; - BOOST_CHECK_CLOSE_FRACTION(x, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(x, boost::math::constants::root_two_pi(), tol); // root_two_pi // for BOOST_MSVC versions. // Boost macros -#define BOOST_TEST_MAIN -#define BOOST_LIB_DIAGNOSTIC "on" // Report library file details. -#include // Boost.Test -// #include // Boost.Test -#include +#include "math_unit_test.hpp" #include #include @@ -134,7 +130,7 @@ void test_integrals() return lambert_w0(z); }; Real z = ts.integrate(f, a, b); // OK without any decltype(f) - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::e() - 1, tol); + CHECK_RELATIVE_ERROR(z, boost::math::constants::e() - 1, tol); } { // Integrate for function lambert_W0(z/(z sqrt(z)). @@ -144,7 +140,7 @@ void test_integrals() return lambert_w0(z)/(z * sqrt(z)); }; Real z = es.integrate(f); // OK - BOOST_CHECK_CLOSE_FRACTION(z, 2 * boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, 2 * boost::math::constants::root_two_pi(), tol); } { // Integrate for function lambert_W0(1/z^2). @@ -163,15 +159,14 @@ void test_integrals() } }; Real z = es.integrate(f); - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, boost::math::constants::root_two_pi(), tol); } } // template void test_integrals() -BOOST_AUTO_TEST_CASE( integrals ) +void integrals() { std::cout << "Macro BOOST_MATH_LAMBERT_W0_INTEGRALS is defined." << std::endl; - BOOST_TEST_MESSAGE("\nTest Lambert W0 integrals."); try { // using statements needed to change precision policy. @@ -250,7 +245,7 @@ Real x; // Unexpected exception thrown in integration code at abscissa (x): 3.478765835953569e-23. x = es.integrate(f); std::cout << "es.integrate(f) = " << x << std::endl; - BOOST_CHECK_CLOSE_FRACTION(x, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(x, boost::math::constants::root_two_pi(), tol); // root_two_pi // for BOOST_MSVC versions. // Boost macros -#define BOOST_TEST_MAIN -#define BOOST_LIB_DIAGNOSTIC "on" // Report library file details. -#include // Boost.Test -// #include // Boost.Test -#include +#include "math_unit_test.hpp" #include #include @@ -137,7 +133,7 @@ void test_integrals() return lambert_w0(z); }; Real z = ts.integrate(f, a, b); // OK without any decltype(f) - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::e() - 1, tol); + CHECK_RELATIVE_ERROR(z, boost::math::constants::e() - 1, tol); } { // Integrate for function lambert_W0(z/(z sqrt(z)). @@ -147,7 +143,7 @@ void test_integrals() return lambert_w0(z)/(z * sqrt(z)); }; Real z = es.integrate(f); // OK - BOOST_CHECK_CLOSE_FRACTION(z, 2 * boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, 2 * boost::math::constants::root_two_pi(), tol); } { // Integrate for function lambert_W0(1/z^2). @@ -166,15 +162,14 @@ void test_integrals() } }; Real z = es.integrate(f); - BOOST_CHECK_CLOSE_FRACTION(z, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(z, boost::math::constants::root_two_pi(), tol); } } // template void test_integrals() -BOOST_AUTO_TEST_CASE( integrals ) +void integrals() { std::cout << "Macro BOOST_MATH_LAMBERT_W0_INTEGRALS is defined." << std::endl; - BOOST_TEST_MESSAGE("\nTest Lambert W0 integrals."); try { // using statements needed to change precision policy. @@ -253,7 +248,7 @@ Real x; // Unexpected exception thrown in integration code at abscissa (x): 3.478765835953569e-23. x = es.integrate(f); std::cout << "es.integrate(f) = " << x << std::endl; - BOOST_CHECK_CLOSE_FRACTION(x, boost::math::constants::root_two_pi(), tol); + CHECK_RELATIVE_ERROR(x, boost::math::constants::root_two_pi(), tol); // root_two_pi +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#endif +#include "math_unit_test.hpp" + +template +void test_spots(T, const char* t) +{ + std::cout << "Testing lambert_w for type " << t << std::endl; + + using std::exp; + const T tolerance = 16; + + // W0 at 1 is the omega constant. + CHECK_ULP_CLOSE(::boost::math::lambert_w0(static_cast(1)), + static_cast(0.56714329040978387299996866221035554975381578718651L), tolerance); + + // W0 identity: w * e^w == z. Runtime indexing here reaches the w0 tables. + for (const T z : {static_cast(0.5), static_cast(2), static_cast(10), + static_cast(100), static_cast(1000)}) + { + const T w = ::boost::math::lambert_w0(z); + CHECK_ULP_CLOSE(w * exp(w), z, tolerance); + } + + // W-1 identity on its branch (z in [-1/e, 0)); reaches the wm1 tables. + for (const T z : {static_cast(-0.3), static_cast(-0.1), + static_cast(-0.01), static_cast(-0.001)}) + { + const T w = ::boost::math::lambert_wm1(z); + CHECK_ULP_CLOSE(w * exp(w), z, tolerance); + } +} + +int main() +{ + test_spots(0.0F, "float"); + test_spots(0.0, "double"); + + return boost::math::test::report_errors(); +} diff --git a/test/test_lambert_w_std_free_module.cpp b/test/test_lambert_w_std_free_module.cpp new file mode 100644 index 0000000000..0b8ccd5015 --- /dev/null +++ b/test/test_lambert_w_std_free_module.cpp @@ -0,0 +1,30 @@ +// (C) Copyright Matt Borland 2026. +// 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) +// +// A std-free module consumer: it names no standard library entity, so it builds +// on toolchains (GCC/libstdc++) that cannot yet mix textual std includes with +// import std in a consumer. Instantiating these functions makes the compiler +// resolve the namespace-scope tables/constants they use, which is where GCC +// enforces the module exposure rule that clang does not diagnose. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +int main() +{ + int status {0}; + + // lambert_w0/wm1 index the namespace-scope lookup tables at run time; that + // odr-use is what makes GCC reject the tables if they carry internal linkage. + const double w0 {boost::math::lambert_w0(1.0)}; + const double wm1 {boost::math::lambert_wm1(-0.1)}; + status += (w0 > 0.5 && w0 < 0.6) ? 0 : 1; + status += (wm1 < -3.0) ? 0 : 1; + + return status; +} diff --git a/test/test_lanczos_smoothing.cpp b/test/test_lanczos_smoothing.cpp new file mode 100644 index 0000000000..8e21fb7663 --- /dev/null +++ b/test/test_lanczos_smoothing.cpp @@ -0,0 +1,708 @@ +/* + * Copyright Nick Thompson, 2019 + * 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) + */ +#include +#include +#include +#include +#include +#include +#include +#include // for float_distance +#include +#include "math_unit_test.hpp" + +using std::abs; +using std::pow; +using std::sqrt; +using std::sin; +using boost::math::constants::two_pi; +using boost::multiprecision::cpp_bin_float_50; +using boost::multiprecision::cpp_bin_float_100; +using boost::math::differentiation::discrete_lanczos_derivative; +using boost::math::differentiation::detail::discrete_legendre; +using boost::math::differentiation::detail::interior_velocity_filter; +using boost::math::differentiation::detail::boundary_velocity_filter; +using boost::math::tools::summation_condition_number; + +template +void test_dlp_norms() +{ + std::cout << "Testing Discrete Legendre Polynomial norms on type " << typeid(Real).name() << "\n"; + auto dlp = discrete_legendre(1, Real(0)); + CHECK_ULP_CLOSE(3, dlp.norm_sq(0), 2); + CHECK_ULP_CLOSE(2, dlp.norm_sq(1), 2); + dlp = discrete_legendre(2, Real(0)); + CHECK_ULP_CLOSE(Real(5)/Real(2), dlp.norm_sq(0), 2); + CHECK_ULP_CLOSE(Real(5)/Real(4), dlp.norm_sq(1), 2); + CHECK_ULP_CLOSE(Real(3*3*7)/Real(pow(2,6)), dlp.norm_sq(2), 4); + dlp = discrete_legendre(200, Real(0)); + for(size_t r = 0; r < 10; ++r) + { + Real calc = dlp.norm_sq(r); + Real expected = Real(2)/Real(2*r+1); + // As long as r << n, ||q_r||^2 -> 2/(2r+1) as n->infty + CHECK_ABSOLUTE_ERROR(expected, calc, Real(0.05*abs(expected))); + } + +} + +template +void test_dlp_evaluation() +{ + std::cout << "Testing evaluation of Discrete Legendre polynomials on type " << typeid(Real).name() << "\n"; + size_t n = 25; + Real x = 0.72; + auto dlp = discrete_legendre(n, x); + Real q0 = dlp(x, 0); + CHECK_EQUAL(q0, Real(1)); + Real q1 = dlp(x, 1); + CHECK_EQUAL(q1, x); + Real q2 = dlp(x, 2); + int N = 2*n+1; + Real expected = 0.5*(3*x*x - Real(N*N - 1)/Real(4*n*n)); + CHECK_ULP_CLOSE(expected, q2, 2); + Real q3 = dlp(x, 3); + expected = (x/3)*(5*expected - (Real(N*N - 4))/(2*n*n)); + CHECK_ULP_CLOSE(expected, q3, 8); + + // q_r(x) is even for even r, and odd for odd r: + for (size_t n = 8; n < 22; ++n) + { + dlp = discrete_legendre(n, x); + for(size_t r = 2; r <= n; ++r) + { + if (r & 1) + { + Real q1 = dlp(x, r); + Real q2 = -dlp(-x, r); + CHECK_ULP_CLOSE(q2, q1, 2); + } + else + { + Real q1 = dlp(x, r); + Real q2 = dlp(-x, r); + CHECK_ULP_CLOSE(q2, q1, 2); + } + + Real l2_sq = 0; + for (int j = -(int)n; j <= (int) n; ++j) + { + Real y = Real(j)/Real(n); + Real term = dlp(y, r); + l2_sq += term*term; + } + l2_sq /= n; + Real l2_sq_expected = dlp.norm_sq(r); + CHECK_ULP_CLOSE(l2_sq_expected, l2_sq, 40); + } + } +} + +template +void test_dlp_next() +{ + std::cout << "Testing Discrete Legendre polynomial 'next' function on type " << typeid(Real).name() << "\n"; + + for(size_t n = 2; n < 20; ++n) + { + for(Real x = -1; x <= 1; x += 0.1) + { + auto dlp = discrete_legendre(n, x); + for (size_t k = 2; k < n; ++k) + { + CHECK_ULP_CLOSE(dlp(x, k), dlp.next(), 0); + } + + dlp = discrete_legendre(n, x); + for (size_t k = 2; k < n; ++k) + { + CHECK_ULP_CLOSE(dlp.prime(x, k), dlp.next_prime(), 0); + } + } + } +} + + +template +void test_dlp_derivatives() +{ + std::cout << "Testing Discrete Legendre polynomial derivatives on type " << typeid(Real).name() << "\n"; + int n = 25; + Real x = 0.72; + auto dlp = discrete_legendre(n, x); + Real q0p = dlp.prime(x, 0); + CHECK_EQUAL(q0p, Real(0)); + Real q1p = dlp.prime(x, 1); + CHECK_EQUAL(q1p, Real(1)); + Real q2p = dlp.prime(x, 2); + Real expected = 3*x; + CHECK_ULP_CLOSE(expected, q2p, 4); +} + +template +void test_dlp_second_derivative() +{ + std::cout << "Testing Discrete Legendre polynomial derivatives on type " << typeid(Real).name() << "\n"; + int n = 25; + Real x = Real(1)/Real(3); + auto dlp = discrete_legendre(n, x); + Real q2pp = dlp.next_dbl_prime(); + CHECK_EQUAL(q2pp, Real(3)); +} + + +template +void test_interior_velocity_filter() +{ + using boost::math::constants::half; + std::cout << "Testing interior filter on type " << typeid(Real).name() << "\n"; + Real tol = std::numeric_limits::epsilon(); + for(int n = 1; n < 10; ++n) + { + for (int p = 1; p < n; p += 2) + { + auto f = interior_velocity_filter(n,p); + // Since we only store half the filter coefficients, + // we need to reindex the moment sums: + auto cond = summation_condition_number(0); + for (size_t j = 0; j < f.size(); ++j) + { + cond += j*f[j]; + } + CHECK_ABSOLUTE_ERROR(half(), cond.sum(), Real(4*(cond()*tol)*abs(half()))); + + for (int l = 3; l <= p; l += 2) + { + cond = summation_condition_number(0); + for (size_t j = 0; j < f.size() - 1; ++j) + { + cond += pow(Real(j), l)*f[j]; + } + Real expected = -pow(Real(f.size() - 1), l)*f[f.size()-1]; + CHECK_ABSOLUTE_ERROR(expected, cond.sum(), Real(15*(cond()*tol)*abs(expected))); + } + //std::cout << "(n,p) = (" << n << "," << p << ") = {"; + //for (auto & x : f) + //{ + // std::cout << x << ", "; + //} + //std::cout << "}\n"; + } + } +} + +template +void test_interior_lanczos() +{ + std::cout << "Testing interior Lanczos on type " << typeid(Real).name() << "\n"; + Real tol = std::numeric_limits::epsilon(); + std::vector v(500); + std::fill(v.begin(), v.end(), 7); + + for (size_t n = 1; n < 10; ++n) + { + for (size_t p = 2; p < 2*n; p += 2) + { + auto dld = discrete_lanczos_derivative(Real(0.1), n, p); + for (size_t m = n; m < v.size() - n; ++m) + { + Real dvdt = dld(v, m); + CHECK_ABSOLUTE_ERROR(0, dvdt, tol); + } + auto dvdt = dld(v); + for (size_t m = n; m < v.size() - n; ++m) + { + CHECK_ABSOLUTE_ERROR(0, dvdt[m], tol); + } + } + } + + + for(size_t i = 0; i < v.size(); ++i) + { + v[i] = 7*i+8; + } + + for (size_t n = 1; n < 10; ++n) + { + for (size_t p = 2; p < 2*n; p += 2) + { + auto dld = discrete_lanczos_derivative(Real(1), n, p); + for (size_t m = n; m < v.size() - n; ++m) + { + Real dvdt = dld(v, m); + CHECK_ULP_CLOSE(7, dvdt, 4000); + } + auto dvdt = dld(v); + for (size_t m = n; m < v.size() - n; ++m) + { + CHECK_ULP_CLOSE(7, dvdt[m], 4000); + } + } + } + + //std::random_device rd{}; + //auto seed = rd(); + //std::cout << "Seed = " << seed << "\n"; + std::mt19937 gen(4172378669); + std::normal_distribution<> dis{0, 0.01}; + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = 7*i+8 + dis(gen); + } + + for (size_t n = 1; n < 10; ++n) + { + for (size_t p = 2; p < 2*n; p += 2) + { + auto dld = discrete_lanczos_derivative(Real(1), n, p); + for (size_t m = n; m < v.size() - n; ++m) + { + CHECK_ABSOLUTE_ERROR(Real(7), dld(v, m), Real(0.0042*abs(Real(7)))); + } + } + } + + + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = 15*i*i + 7*i+8 + dis(gen); + } + + for (size_t n = 1; n < 10; ++n) + { + for (size_t p = 2; p < 2*n; p += 2) + { + auto dld = discrete_lanczos_derivative(Real(1), n, p); + for (size_t m = n; m < v.size() - n; ++m) + { + CHECK_ABSOLUTE_ERROR(Real(30*m + 7), dld(v,m), Real(8e-05*abs(Real(30*m + 7)))); + } + } + } + + std::normal_distribution<> dis1{0, 0.0001}; + Real omega = Real(1)/Real(16); + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = sin(i*omega) + dis1(gen); + } + + for (size_t n = 10; n < 20; ++n) + { + for (size_t p = 3; p < 100 && p < n/2; p += 2) + { + auto dld = discrete_lanczos_derivative(Real(1), n, p); + + for (size_t m = n; m < v.size() - n && m < n + 10; ++m) + { + CHECK_ABSOLUTE_ERROR(omega*cos(omega*m), dld(v,m), Real(0.03*abs(omega*cos(omega*m)))); + } + } + } +} + +template +void test_boundary_velocity_filters() +{ + std::cout << "Testing boundary filters on type " << typeid(Real).name() << "\n"; + Real tol = std::numeric_limits::epsilon(); + for(int n = 1; n < 5; ++n) + { + for (int p = 1; p < 2*n+1; ++p) + { + for (int s = -n; s <= n; ++s) + { + auto f = boundary_velocity_filter(n, p, s); + // Sum is zero: + auto cond = summation_condition_number(0); + for (size_t i = 0; i < f.size() - 1; ++i) + { + cond += f[i]; + } + + CHECK_ABSOLUTE_ERROR(-f[f.size()-1], cond.sum(), Real(6*(cond()*tol)*abs(-f[f.size()-1]))); + + cond = summation_condition_number(0); + for (size_t k = 0; k < f.size(); ++k) + { + Real j = Real(k) - Real(n); + // note the shifted index here: + cond += (j-s)*f[k]; + } + CHECK_ABSOLUTE_ERROR(1, cond.sum(), Real(6*(cond()*tol)*Real(1))); + + + for (int l = 2; l <= p; ++l) + { + cond = summation_condition_number(0); + for (size_t k = 0; k < f.size() - 1; ++k) + { + Real j = Real(k) - Real(n); + // The condition number of this sum is infinite! + // No need to get to worked up about the tolerance. + cond += pow(j-s, l)*f[k]; + } + + Real expected = -pow(Real(f.size()-1) - Real(n) - Real(s), l)*f[f.size()-1]; + if (expected == 0) + { + CHECK_ABSOLUTE_ERROR(0, cond.sum(), cond()*tol); + } + else + { + CHECK_ABSOLUTE_ERROR(expected, cond.sum(), Real(200*(cond()*tol)*abs(expected))); + } + } + + //std::cout << "(n,p,s) = ("<< n << ", " << p << "," << s << ") = {"; + //for (auto & x : f) + //{ + // std::cout << x << ", "; + //} + //std::cout << "}\n";*/ + } + } + } +} + +template +void test_boundary_lanczos() +{ + std::cout << "Testing Lanczos boundary on type " << typeid(Real).name() << "\n"; + Real tol = std::numeric_limits::epsilon(); + std::vector v(500, 7); + + for (size_t n = 1; n < 10; ++n) + { + for (size_t p = 2; p < 2*n; ++p) + { + auto lsd = discrete_lanczos_derivative(Real(0.0125), n, p); + for (size_t m = 0; m < n; ++m) + { + Real dvdt = lsd(v,m); + CHECK_ABSOLUTE_ERROR(0, dvdt, 4*sqrt(tol)); + } + for (size_t m = v.size() - n; m < v.size(); ++m) + { + Real dvdt = lsd(v,m); + CHECK_ABSOLUTE_ERROR(0, dvdt, 4*sqrt(tol)); + } + } + } + + for(size_t i = 0; i < v.size(); ++i) + { + v[i] = 7*i+8; + } + + for (size_t n = 3; n < 10; ++n) + { + for (size_t p = 2; p < 2*n; ++p) + { + auto lsd = discrete_lanczos_derivative(Real(1), n, p); + for (size_t m = 0; m < n; ++m) + { + Real dvdt = lsd(v,m); + CHECK_ABSOLUTE_ERROR(7, dvdt, Real((sqrt(tol))*Real(7))); + } + + for (size_t m = v.size() - n; m < v.size(); ++m) + { + Real dvdt = lsd(v,m); + CHECK_ABSOLUTE_ERROR(7, dvdt, Real(4*(sqrt(tol))*Real(7))); + } + } + } + + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = 15*i*i + 7*i+8; + } + + for (size_t n = 1; n < 10; ++n) + { + for (size_t p = 2; p < 2*n; ++p) + { + auto lsd = discrete_lanczos_derivative(Real(1), n, p); + for (size_t m = 0; m < v.size(); ++m) + { + CHECK_ABSOLUTE_ERROR(Real(30*m+7), lsd(v,m), Real(30*sqrt(tol)*Real(30*m+7))); + } + } + } + + // Demonstrate that the boundary filters are also denoising: + //std::random_device rd{}; + //auto seed = rd(); + //std::cout << "seed = " << seed << "\n"; + std::mt19937 gen(311354333); + std::normal_distribution<> dis{0, 0.01}; + for (size_t i = 0; i < v.size(); ++i) + { + v[i] += dis(gen); + } + + for (size_t n = 1; n < 10; ++n) + { + for (size_t p = 2; p < n; ++p) + { + auto lsd = discrete_lanczos_derivative(Real(1), n, p); + for (size_t m = 0; m < v.size(); ++m) + { + CHECK_ABSOLUTE_ERROR(Real(30*m+7), lsd(v,m), Real(0.005*Real(30*m+7))); + } + auto dvdt = lsd(v); + for (size_t m = 0; m < v.size(); ++m) + { + CHECK_ABSOLUTE_ERROR(Real(30*m+7), dvdt[m], Real(0.005*Real(30*m+7))); + } + } + } +} + +template +void test_acceleration_filters() +{ + Real eps = std::numeric_limits::epsilon(); + for (size_t n = 1; n < 5; ++n) + { + for(size_t p = 3; p <= 2*n; ++p) + { + for(int64_t s = -int64_t(n); s <= 0; ++s) + { + auto g = boost::math::differentiation::detail::acceleration_filter(n,p,s); + + std::vector f(g.size()); + for (size_t i = 0; i < g.size(); ++i) + { + f[i] = static_cast(g[i]); + } + + auto cond = summation_condition_number(0); + + for (size_t i = 0; i < f.size() - 1; ++i) + { + cond += f[i]; + } + CHECK_ABSOLUTE_ERROR(-f[f.size()-1], cond.sum(), Real(10*(cond()*eps)*abs(-f[f.size()-1]))); + + + cond = summation_condition_number(0); + for (size_t k = 0; k < f.size() -1; ++k) + { + Real j = Real(k) - Real(n); + cond += (j-s)*f[k]; + } + Real expected = -(Real(f.size()-1)- Real(n) - s)*f[f.size()-1]; + CHECK_ABSOLUTE_ERROR(expected, cond.sum(), Real(10*(cond()*eps)*abs(expected))); + + cond = summation_condition_number(0); + for (size_t k = 0; k < f.size(); ++k) + { + Real j = Real(k) - Real(n); + cond += (j-s)*(j-s)*f[k]; + } + CHECK_ABSOLUTE_ERROR(2, cond.sum(), Real(100*(cond()*eps)*Real(2))); + // See unlabelled equation in McDevitt, 2012, just after equation 26: + // It appears that there is an off-by-one error in that equation, since p + 1 moments don't vanish, only p. + // This test is itself suspect; the condition number of the moment sum is infinite. + // So the *slightest* error in the filter gets amplified by the test; in terms of the + // behavior of the actual filter, it's not a big deal. + for (size_t l = 3; l <= p; ++l) + { + cond = summation_condition_number(0); + for (size_t k = 0; k < f.size() - 1; ++k) + { + Real j = Real(k) - Real(n); + cond += pow((j-s), l)*f[k]; + } + Real expected = -pow(Real(f.size()- 1 - n -s), l)*f[f.size()-1]; + CHECK_ABSOLUTE_ERROR(expected, cond.sum(), Real(1000*(cond()*eps)*abs(expected))); + } + } + } + } +} + +template +void test_lanczos_acceleration() +{ + Real eps = std::numeric_limits::epsilon(); + std::vector v(100, 7); + auto lanczos = discrete_lanczos_derivative(Real(1), 4, 3); + for (size_t i = 0; i < v.size(); ++i) + { + CHECK_ABSOLUTE_ERROR(0, lanczos(v, i), eps); + } + + for(size_t i = 0; i < v.size(); ++i) + { + v[i] = 7*i + 6; + } + for (size_t i = 0; i < v.size(); ++i) + { + CHECK_ABSOLUTE_ERROR(0, lanczos(v,i), 200*eps); + } + + for(size_t i = 0; i < v.size(); ++i) + { + v[i] = 7*i*i + 9*i + 6; + } + for (size_t i = 0; i < v.size(); ++i) + { + CHECK_ULP_CLOSE(14, lanczos(v, i), 3000); + } + + // Now add noise, and kick up the smoothing of the Lanzcos derivative (increase n): + //std::random_device rd{}; + //auto seed = rd(); + //std::cout << "seed = " << seed << "\n"; + size_t seed = 2507134629; + std::mt19937 gen(seed); + Real std_dev = 0.1; + std::normal_distribution dis{0, std_dev}; + for (size_t i = 0; i < v.size(); ++i) + { + v[i] += dis(gen); + } + lanczos = discrete_lanczos_derivative(Real(1), 18, 3); + auto w = lanczos(v); + for (size_t i = 0; i < v.size(); ++i) + { + CHECK_ABSOLUTE_ERROR(14, w[i], Real((std_dev/200)*Real(14))); + } +} + +template +void test_rescaling() +{ + std::cout << "Test rescaling on type " << typeid(Real).name() << "\n"; + std::vector v(500); + for(size_t i = 0; i < v.size(); ++i) + { + v[i] = 7*i*i + 9*i + 6; + } + std::vector dvdt1(500); + std::vector dvdt2(500); + auto lanczos1 = discrete_lanczos_derivative(Real(1)); + auto lanczos2 = discrete_lanczos_derivative(Real(2)); + + lanczos1(v, dvdt1); + lanczos2(v, dvdt2); + + for(size_t i = 0; i < v.size(); ++i) + { + CHECK_ULP_CLOSE(2*dvdt2[i], dvdt1[i], 2); + } + + auto lanczos3 = discrete_lanczos_derivative(Real(1)); + auto lanczos4 = discrete_lanczos_derivative(Real(2)); + + + std::vector dv2dt21(500); + std::vector dv2dt22(500); + lanczos3(v, dv2dt21); + lanczos4(v, dv2dt22); + + for(size_t i = 0; i < v.size(); ++i) + { + CHECK_ULP_CLOSE(4*dv2dt22[i], dv2dt21[i], 2); + } +} + +template +void test_data_representations() +{ + std::cout << "Test data representations on type " << typeid(Real).name() << "\n"; + Real tol = 150*std::numeric_limits::epsilon(); + std::array v; + for(size_t i = 0; i < v.size(); ++i) + { + v[i] = 9*i + 6; + } + std::array dvdt; + auto lanczos = discrete_lanczos_derivative(Real(1)); + + lanczos(v, dvdt); + + for(size_t i = 0; i < v.size(); ++i) + { + CHECK_ULP_CLOSE(9, dvdt[i], 300); + } + + boost::numeric::ublas::vector w(500); + boost::numeric::ublas::vector dwdt(500); + for(size_t i = 0; i < w.size(); ++i) + { + w[i] = 9*i + 6; + } + + lanczos(w, dwdt); + + for(size_t i = 0; i < v.size(); ++i) + { + CHECK_ULP_CLOSE(9, dwdt[i], 300); + } + + auto v1 = boost::make_iterator_range(v.begin(), v.end()); + auto v2 = boost::make_iterator_range(dvdt.begin(), dvdt.end()); + lanczos(v1, v2); + + for(size_t i = 0; i < v2.size(); ++i) + { + CHECK_ULP_CLOSE(9, v2[i], 300); + } + + auto lanczos2 = discrete_lanczos_derivative(Real(1)); + + lanczos2(v1, v2); + + for(size_t i = 0; i < v2.size(); ++i) + { + CHECK_ABSOLUTE_ERROR(0, v2[i], 10*tol); + } + +} + +void lanczos_smoothing_test() +{ + test_dlp_second_derivative(); + test_dlp_norms(); + test_dlp_evaluation(); + test_dlp_derivatives(); + test_dlp_next(); + + // Takes too long! + //test_dlp_norms(); + test_boundary_velocity_filters(); + test_boundary_velocity_filters(); + // Takes too long! + //test_boundary_velocity_filters(); + test_boundary_lanczos(); + test_boundary_lanczos(); + // Takes too long! + //test_boundary_lanczos(); + + test_interior_velocity_filter(); + test_interior_velocity_filter(); + test_interior_lanczos(); + + test_acceleration_filters(); + + test_lanczos_acceleration(); + test_lanczos_acceleration(); + + test_rescaling(); + test_data_representations(); +} + +int main() +{ + lanczos_smoothing_test(); + return boost::math::test::report_errors(); +} diff --git a/test/test_lanczos_smoothing_module.cpp b/test/test_lanczos_smoothing_module.cpp new file mode 100644 index 0000000000..e96fa29036 --- /dev/null +++ b/test/test_lanczos_smoothing_module.cpp @@ -0,0 +1,158 @@ +// (C) Copyright Nick Thompson 2019. +// (C) Copyright Matt Borland 2026. +// 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) +// +// Module build check for boost::math::differentiation::discrete_lanczos_derivative. +// The exported class template builds its interior and boundary filters by calling +// the namespace-scope templates in differentiation::detail (interior_velocity_filter, +// boundary_velocity_filter, acceleration_filter). Constructing and evaluating the +// derivative here forces those internal templates to be instantiated and resolved +// from a module consumer. Data and expected values are copied from +// test_lanczos_smoothing.cpp; only mathematically-certain results are checked. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif +#include "math_unit_test.hpp" + +// First derivative (order 1) on unit-spacing samples, double precision. +void test_velocity() +{ + using boost::math::differentiation::discrete_lanczos_derivative; + + // Default filter: n = 18, approximation_order = 3. + auto d = discrete_lanczos_derivative(1.0); + CHECK_EQUAL(1.0, d.get_spacing()); + + // Constant signal: the first derivative is identically zero. + std::vector constant(500, 7.0); + auto dc = d(constant); + for (std::size_t i = 0; i < dc.size(); ++i) + { + CHECK_ABSOLUTE_ERROR(0.0, dc[i], 1e-9); + } + + // Linear signal v = 9 i + 6: the derivative is the slope 9 everywhere + // (data and expected value from test_data_representations). A generous + // absolute tolerance keeps the check robust where the internal long double + // filter build is only 64-bit wide. + std::vector linear(500); + for (std::size_t i = 0; i < linear.size(); ++i) + { + linear[i] = 9.0 * static_cast(i) + 6.0; + } + auto dl = d(linear); + for (std::size_t i = 0; i < dl.size(); ++i) + { + CHECK_ABSOLUTE_ERROR(9.0, dl[i], 1e-6); + } + + // Quadratic signal v = 15 i^2 + 7 i + 8: the derivative is 30 i + 7 (test_boundary_lanczos). + // Checked on the well-conditioned interior where the symmetric filter applies. + std::vector quad(500); + for (std::size_t i = 0; i < quad.size(); ++i) + { + const double x = static_cast(i); + quad[i] = 15.0 * x * x + 7.0 * x + 8.0; + } + auto dq = d(quad); + const std::size_t interior[] = {std::size_t(50), std::size_t(100), std::size_t(250), std::size_t(400)}; + for (const std::size_t i : interior) + { + const double expected = 30.0 * static_cast(i) + 7.0; + CHECK_MOLLIFIED_CLOSE(expected, dq[i], 1e-9); + // The single-index operator() must agree with the whole-vector transform. + CHECK_MOLLIFIED_CLOSE(expected, d(quad, i), 1e-9); + } +} + +// Rescaling: halving the sample rate doubles the reported derivative (test_rescaling). +void test_rescaling() +{ + using boost::math::differentiation::discrete_lanczos_derivative; + + std::vector v(500); + for (std::size_t i = 0; i < v.size(); ++i) + { + const double x = static_cast(i); + v[i] = 7.0 * x * x + 9.0 * x + 6.0; + } + + auto lanczos1 = discrete_lanczos_derivative(1.0); + auto lanczos2 = discrete_lanczos_derivative(2.0); + auto d1 = lanczos1(v); + auto d2 = lanczos2(v); + for (std::size_t i = 0; i < v.size(); ++i) + { + CHECK_MOLLIFIED_CLOSE(d1[i], 2.0 * d2[i], 1e-12); + } +} + +// Second derivative (order 2, acceleration filter), double precision (test_lanczos_acceleration). +void test_acceleration() +{ + using boost::math::differentiation::discrete_lanczos_derivative; + + auto lanczos = discrete_lanczos_derivative(1.0, 4, 3); + CHECK_EQUAL(1.0, lanczos.get_spacing()); + + // Constant signal: the second derivative is zero. + std::vector constant(100, 7.0); + for (std::size_t i = 0; i < constant.size(); ++i) + { + CHECK_ABSOLUTE_ERROR(0.0, lanczos(constant, i), 1e-9); + } + + // Quadratic signal v = 7 i^2 + 9 i + 6: the second derivative is exactly 14. + std::vector quad(100); + for (std::size_t i = 0; i < quad.size(); ++i) + { + const double x = static_cast(i); + quad[i] = 7.0 * x * x + 9.0 * x + 6.0; + } + for (std::size_t i = 0; i < quad.size(); ++i) + { + CHECK_MOLLIFIED_CLOSE(14.0, lanczos(quad, i), 1e-8); + } +} + +// Exercise the float instantiation of the exported template through the module. +// The interior first derivative of a linear ramp reproduces the slope. +void test_velocity_float() +{ + using boost::math::differentiation::discrete_lanczos_derivative; + + auto d = discrete_lanczos_derivative(1.0f); + + std::vector linear(100); + for (std::size_t i = 0; i < linear.size(); ++i) + { + linear[i] = 9.0f * static_cast(i) + 6.0f; + } + + // Interior indices for the default n = 18 filter satisfy 18 <= i <= 81. + const std::size_t interior[] = {std::size_t(20), std::size_t(40), std::size_t(60), std::size_t(80)}; + for (const std::size_t i : interior) + { + CHECK_MOLLIFIED_CLOSE(9.0f, d(linear, i), 1e-3f); + } +} + +int main() +{ + test_velocity(); + test_rescaling(); + test_acceleration(); + test_velocity_float(); + + return boost::math::test::report_errors(); +} diff --git a/test/test_landau.cpp b/test/test_landau.cpp index 96e9f9c3a7..47b9805bc3 100644 --- a/test/test_landau.cpp +++ b/test/test_landau.cpp @@ -4,16 +4,13 @@ // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_TEST_MAIN -#define BOOST_TEST_MODULE StatsLandauTest #ifdef BOOST_MATH_ENABLE_SYCL #include "sycl/sycl.hpp" #endif #include -#include -#include +#include "math_unit_test.hpp" #include #if __has_include() @@ -49,191 +46,191 @@ void do_test_landau_pdf(){ landau_distribution dist(static_cast(0), static_cast(1)); // Left tail of Landau distribution inherently limits accuracy due to the rapid decay of the function value. - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.23085262843901249987787600097675204323741277288698e-2763), tolerance * 10000); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43092685592935588160074717060232841559786193515624e-1259), tolerance * 10000); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.07984079126853424748872672315932614660166330244758e-574), tolerance * 4000); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51902330649665702862232056199116883579782363388698e-261), tolerance * 1000); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.61740160083645125413680224234682096739098348513281e-119), tolerance * 400); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.40268429420551752841762522647338593851384890728514e-54), tolerance * 100); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.64264014182893964260735316412669280242258553581563e-37), tolerance * 100); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.96628298286997713279446280099737948363623849272499e-25), tolerance * 100); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.65014695258589331535696024118503069088391324558285e-17), tolerance * 100); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52577680004870416264378840612037346351517011876564e-11), tolerance * 40); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.96564073685328676511751663666044321538322085645615e-8), tolerance * 40); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.49195679110887105000100573294850045215882388658736e-5), tolerance * 10); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.83029281547111049679644135145824504175531296639784e-4), tolerance * 4); - - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.50763682207511020788551990942118742909694977020766e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55239934591810979484111502955882518822410677336301e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.11811339800999276275816189148400161297598608940370e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.43803188361205250108898134179433045737003842752098e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.44559645555354621908225839934967437642938589048641e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.19256762240252210606670736977933945194758525070962e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55747609478534232829752995639617852824070107389867e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90787204474682320276094536207112207798402106183626e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.21762208692280384264052188465103527015057255360522e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.35142856681038695962612277740850797545496160091346e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.46926317225475336949604234617889242016284403135263e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.57038182663311646092167022800387128596042855954974e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.65453539644067140109079490907422208395106068408806e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72189928839617935958276513066615896148477769341984e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.77299781354951097794140321722510611592577477809046e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.80862887196928314574763226767834515262714169253341e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.82979296472337068393182796635835781531645972141685e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83762914935252825962037404558307269544013453409236e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83335939453844198706047097920194738266342072083183e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.81824188244607845783889480215304948211453087161311e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.79353314321623987234651193548815637401927993615201e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.76045845604337224786926223067521339118457783620200e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72018967730828877761590993107231423707402335516208e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(-0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.67382951900254916684467526412940597211696659408252e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62240126375351657025589608183516471314881294729647e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56684293488331550048284390907274219670798777890274e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.50800501583089077855151395221936193088464543391697e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.44665091350810416315066697862911894015423062289459e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.38345947054726504652084392231776081590084152956389e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.31902894209756674501863785530002142859374765415539e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25388195748200100617512573536171938322886836672500e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18847108191054606649972320910802001046885937665349e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.12318467675064265241298421202132871385510191955048e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.05835282809935995378486652717710487064456876565464e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.99425317296731752992133425091298094257535743484505e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.93111650117890312500196499480137441707124661561802e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.86913205029713491869481191910148340512494429155677e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.80845244177744590342641324845464181512725512270901e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.74919823041494123736512984399481253444800810061398e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.69146205716679200390505774997534008647397580964682e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.63531240868022603475813051802104652763421266792797e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52794577355035866144175272867439043108097332289280e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.42728268648990888425150769069939371653574963683898e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.33330183140387812967271143318337448709293578674499e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.24583903791438503777896988292725453902854934482082e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.16463504238864475787300731138600083506835647657585e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08937118376337417303260299595016407050621597377842e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01969562586719050610986409853288944869103385155807e-1), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.55242261334771588093967856464157010583515904813711e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.40542106335080455284302185631726193959498759868958e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.42466467030240081155174776845818529710340047591917e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.58484837369864336802514847217316987349368653299870e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.86394883380361824062302169684513676586056038951383e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.24319810137134739489567689474925534356381531907667e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.70679858898932226345344507218372775665959269901845e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.24154519527191616123631238437619039275267092832219e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.83643820409470770350079809236512802617514831283958e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.17158939997042257734107084716347218188987519860810e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.65588931293442756274955123891841674957134577995432e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.24999943998132461512162382109845468953569057653206e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.92615450486233381461674333853015589016995103903169e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.66449631910567440889641030798080985765446733145615e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.45062281189987454243698017666196791149621836621069e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(7.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.27394302531621603387264220385271200998719076373774e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(8)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12656323880287532946687856443190592954884366662750e-2), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(9)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.97272209098442387115881795542777687494895710641442e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(10)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.29822142754406367527698808542596968321101482611499e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(11)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04211802337476854086853204096220197132228559528499e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(12)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.07803739765703855539464392586871287241424478552475e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(13)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.32333875346680119671101261202737313738117089411627e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(14)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.72232982334134875374745579629692504175963269123550e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(15)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.23647379895109194018623503694593516089449736564227e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(16)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83847488747490686627461184914507143000166295798209e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(18)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.23229209720541068914767304360845920096605060550204e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(20)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.79947182256974676114073539538738666749318597550126e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(22)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.48016777321149926163568000853843271440982208135806e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(24)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.23815521917416110142990010737370397993296057042020e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(26)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05051356188948975788809310742705170449199446295996e-3), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(28)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.02189494175551818802120780043908400302499693753383e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(30)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.82977743390109357722237932712596740553146168838163e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(32)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.85767880395157523314894776472286059373130513345678e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(36)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.38436988071020010518465973524617926941561115862543e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(40)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.33733686912592492663864652100824543220296291087705e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(44)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.56719760886187032655497099894304037738414747694058e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(48)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.98455504950479524812911915761096343833926775180855e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(52)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.53330379508737569512814290970113441709685617438320e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(56)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.17681386666988585981678825113751906947724221061916e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(60)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.89036019000414403525553377301848537121144402020797e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(64)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65677119200426097313111689557286038389044055520291e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(72)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.30262785101049126879812527584486523431435416855092e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(80)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05075497824543686508583330151701088746046662556142e-4), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(88)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.65309719784826735811404845249006631571011107397937e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(96)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.24862987881373408810690419771199915049078409763957e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(104)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.15969937273460908511004283053502890256890552857434e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(112)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.29851658065131948803621145305770537695198696080417e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(120)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.60580149897015438520712002341005415255634795262650e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.04036158768936643116910162586744782570492472991852e-5), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(256)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.94016243990046849166189460556288227597025594512208e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(512)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.46086028677885635430916943188657821915692719236659e-6), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, static_cast(1024)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.11684517285572531637079275580373275248746393740505e-7), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 11)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52416040197318095218142515144159361915369773070323e-7), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 12)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.80328507092562833387828627033077037362079287147494e-8), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 13)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.49830894979328205589801770626380874036837651152185e-9), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 14)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.37321260457507890170942420030228551149027146711858e-9), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 15)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.93116689130330056188281287044879751157310863062584e-10), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 16)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.48253875064413349633513149673423379659751420343007e-10), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 17)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.70600576035028939688935887999924497768090063213495e-11), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 18)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.26455685393631638684357809746815117207931914505548e-12), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 19)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.31607812424720075650435345952742430841572532807506e-12), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 20)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.79011407780867471284567547634162699267979186606188e-13), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 21)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.44751775633854916204285667335984781835956253195982e-13), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 22)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.61878017561309094548695350627490496501579775589554e-14), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 23)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.04693171826032841875566733962302122545285900020005e-15), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 24)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26173047049833308211942124367857471386868403241961e-15), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.65432295369693602811408648241147072923809751085578e-16), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 26)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41358031701599971473805281134574751063094181933632e-16), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 27)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.53395024254254681824332124678431347548990493315457e-17), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 28)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.83487488981301080647710951024578189621167614209000e-18), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 29)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.20871862925450931967259224559170596670053211110073e-18), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 30)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.52179645209930996243372289840247886946662593536877e-19), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 31)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38044909732789001695763980339161333087125784369381e-19), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 32)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.45112272298940668060590155421055597940788628104792e-20), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 34)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15695169189532579197171519055168026495351913764385e-21), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 36)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.34809480577241011630081955001585893790541249979882e-22), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 38)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.42559253331811413189334788330851699569177453819777e-24), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 40)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.26599533286729634727335420905860617977183492898697e-25), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 42)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.29124708296676552183969416435576047604811850887072e-26), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 44)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.05702942684184448841776719264034349959339461930208e-27), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 46)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28564339177412106630199552439532586497065103592483e-28), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 48)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.03527119858493090854162194048072858076706076597819e-30), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 50)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.02204449911503854915599875932648541933495423396290e-31), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 52)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13877781194681051697029360385733987849026091896815e-32), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 54)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.96173613246674215642318845771797429014235991071697e-33), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 56)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.22608508279171150505713607335390403334626262247470e-34), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 58)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.66303176744819310534466860343470655112837733629379e-36), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 60)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.78939485465512007489594618239133015330653514470962e-37), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 62)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.99337178415944994713157754959412500112801769504923e-38), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 64)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.87085736509965620084544629248142254049400680133870e-39), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 68)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.30803658242053201409813080005840450554429514097447e-42), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 72)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85470179000802031747569733233640023770585023325816e-44), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 76)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.11511788672188293650018950543585978468059122696737e-46), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 80)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.35592924500735522070031636324180548468184125270321e-49), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 84)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.70153486133099813308596977841944913997064236009234e-51), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 88)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.64662055207421145736704601944518511418678161667227e-54), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 92)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.59633615315398885053400175162079403845778513781261e-56), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 96)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01419380982577689473984441890730791873276374028644e-58), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 100)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.96169456963194099507751725745105477863201113021124e-61), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 104)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.54753694126247695120215517859242605013890436588657e-63), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 108)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04506617680655059063341866635141218965712131228669e-66), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 112)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.36135397531505882446617916654287979923104956976029e-68), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 116)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.22403896607444853307101236930796194301091622511538e-71), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 120)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.60314022112283145823086420676091852871339922342198e-73), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 124)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40747664887610603837143133076598369654786648237564e-75), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.49795565967228921238840363580462378845964351238859e-78), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.49795565967228921238840363580462378845964351238859e-78), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 136)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.38921456859174989683289128998508268228293005240118e-83), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 144)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28009255502193449353529225005875895420403010118164e-87), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 152)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.95326622775563734975477943429376061127322830738396e-92), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 160)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.98044773522283531151547154891015718272892496044375e-97), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 168)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.54780233035710954515910575700402402149799340844629e-102), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 176)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.93939564568650748467881127472537845077208466864701e-107), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 184)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05886774378761405711041431804281287395814280222275e-111), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 192)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61570395475404976976076403509950694878867004733696e-116), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 200)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.46536858330390895044061895004197227293193061422265e-121), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 208)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.76185391739488060064791709906306804341420076633095e-126), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 216)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.74013354094677826026598678445902716585418818104698e-131), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 224)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.75874868918880960123594174874729486977262600867765e-136), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 232)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.33647898699780419940733974437672346035348907603114e-140), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 240)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.03930509490631744294332846737170938164289714970571e-145), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 248)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.11173262772570410605366282252763272345412773087419e-150), tolerance); - BOOST_CHECK_CLOSE(pdf(dist, ldexp(static_cast(1), 256)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.74812717853653580635629703144475208046589314403411e-155), tolerance); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.23085262843901249987787600097675204323741277288698e-2763), (tolerance * 10000) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.43092685592935588160074717060232841559786193515624e-1259), (tolerance * 10000) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.07984079126853424748872672315932614660166330244758e-574), (tolerance * 4000) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51902330649665702862232056199116883579782363388698e-261), (tolerance * 1000) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.61740160083645125413680224234682096739098348513281e-119), (tolerance * 400) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.40268429420551752841762522647338593851384890728514e-54), (tolerance * 100) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.64264014182893964260735316412669280242258553581563e-37), (tolerance * 100) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.96628298286997713279446280099737948363623849272499e-25), (tolerance * 100) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.65014695258589331535696024118503069088391324558285e-17), (tolerance * 100) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52577680004870416264378840612037346351517011876564e-11), (tolerance * 40) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.96564073685328676511751663666044321538322085645615e-8), (tolerance * 40) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.49195679110887105000100573294850045215882388658736e-5), (tolerance * 10) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.83029281547111049679644135145824504175531296639784e-4), (tolerance * 4) / 100); + + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.50763682207511020788551990942118742909694977020766e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55239934591810979484111502955882518822410677336301e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.11811339800999276275816189148400161297598608940370e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.43803188361205250108898134179433045737003842752098e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.44559645555354621908225839934967437642938589048641e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.19256762240252210606670736977933945194758525070962e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55747609478534232829752995639617852824070107389867e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.90787204474682320276094536207112207798402106183626e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.21762208692280384264052188465103527015057255360522e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.35142856681038695962612277740850797545496160091346e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.46926317225475336949604234617889242016284403135263e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.57038182663311646092167022800387128596042855954974e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.65453539644067140109079490907422208395106068408806e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72189928839617935958276513066615896148477769341984e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.77299781354951097794140321722510611592577477809046e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.80862887196928314574763226767834515262714169253341e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.82979296472337068393182796635835781531645972141685e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83762914935252825962037404558307269544013453409236e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83335939453844198706047097920194738266342072083183e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.81824188244607845783889480215304948211453087161311e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.79353314321623987234651193548815637401927993615201e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.76045845604337224786926223067521339118457783620200e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.72018967730828877761590993107231423707402335516208e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(-0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.67382951900254916684467526412940597211696659408252e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62240126375351657025589608183516471314881294729647e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.56684293488331550048284390907274219670798777890274e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.50800501583089077855151395221936193088464543391697e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.44665091350810416315066697862911894015423062289459e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.38345947054726504652084392231776081590084152956389e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.31902894209756674501863785530002142859374765415539e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25388195748200100617512573536171938322886836672500e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.18847108191054606649972320910802001046885937665349e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.12318467675064265241298421202132871385510191955048e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.05835282809935995378486652717710487064456876565464e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.99425317296731752992133425091298094257535743484505e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.93111650117890312500196499480137441707124661561802e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.86913205029713491869481191910148340512494429155677e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.80845244177744590342641324845464181512725512270901e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.74919823041494123736512984399481253444800810061398e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.69146205716679200390505774997534008647397580964682e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.63531240868022603475813051802104652763421266792797e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52794577355035866144175272867439043108097332289280e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.42728268648990888425150769069939371653574963683898e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.33330183140387812967271143318337448709293578674499e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.24583903791438503777896988292725453902854934482082e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.16463504238864475787300731138600083506835647657585e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08937118376337417303260299595016407050621597377842e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01969562586719050610986409853288944869103385155807e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.55242261334771588093967856464157010583515904813711e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.40542106335080455284302185631726193959498759868958e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.42466467030240081155174776845818529710340047591917e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.58484837369864336802514847217316987349368653299870e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.86394883380361824062302169684513676586056038951383e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.24319810137134739489567689474925534356381531907667e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.70679858898932226345344507218372775665959269901845e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.24154519527191616123631238437619039275267092832219e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.83643820409470770350079809236512802617514831283958e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.17158939997042257734107084716347218188987519860810e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.65588931293442756274955123891841674957134577995432e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.24999943998132461512162382109845468953569057653206e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.92615450486233381461674333853015589016995103903169e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.66449631910567440889641030798080985765446733145615e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.45062281189987454243698017666196791149621836621069e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(7.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.27394302531621603387264220385271200998719076373774e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(8)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12656323880287532946687856443190592954884366662750e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(9)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.97272209098442387115881795542777687494895710641442e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(10)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.29822142754406367527698808542596968321101482611499e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(11)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04211802337476854086853204096220197132228559528499e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(12)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.07803739765703855539464392586871287241424478552475e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(13)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.32333875346680119671101261202737313738117089411627e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(14)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.72232982334134875374745579629692504175963269123550e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(15)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.23647379895109194018623503694593516089449736564227e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(16)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.83847488747490686627461184914507143000166295798209e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(18)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.23229209720541068914767304360845920096605060550204e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(20)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.79947182256974676114073539538738666749318597550126e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(22)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.48016777321149926163568000853843271440982208135806e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(24)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.23815521917416110142990010737370397993296057042020e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(26)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05051356188948975788809310742705170449199446295996e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(28)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.02189494175551818802120780043908400302499693753383e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(30)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.82977743390109357722237932712596740553146168838163e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(32)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.85767880395157523314894776472286059373130513345678e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(36)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.38436988071020010518465973524617926941561115862543e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(40)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.33733686912592492663864652100824543220296291087705e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(44)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.56719760886187032655497099894304037738414747694058e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(48)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.98455504950479524812911915761096343833926775180855e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(52)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.53330379508737569512814290970113441709685617438320e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(56)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.17681386666988585981678825113751906947724221061916e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(60)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.89036019000414403525553377301848537121144402020797e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(64)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65677119200426097313111689557286038389044055520291e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(72)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.30262785101049126879812527584486523431435416855092e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(80)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05075497824543686508583330151701088746046662556142e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(88)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.65309719784826735811404845249006631571011107397937e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(96)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.24862987881373408810690419771199915049078409763957e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(104)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.15969937273460908511004283053502890256890552857434e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(112)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.29851658065131948803621145305770537695198696080417e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(120)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.60580149897015438520712002341005415255634795262650e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.04036158768936643116910162586744782570492472991852e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(256)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.94016243990046849166189460556288227597025594512208e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(512)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.46086028677885635430916943188657821915692719236659e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, static_cast(1024)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.11684517285572531637079275580373275248746393740505e-7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 11)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.52416040197318095218142515144159361915369773070323e-7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 12)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.80328507092562833387828627033077037362079287147494e-8), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 13)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.49830894979328205589801770626380874036837651152185e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 14)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.37321260457507890170942420030228551149027146711858e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 15)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.93116689130330056188281287044879751157310863062584e-10), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 16)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.48253875064413349633513149673423379659751420343007e-10), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 17)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.70600576035028939688935887999924497768090063213495e-11), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 18)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.26455685393631638684357809746815117207931914505548e-12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 19)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.31607812424720075650435345952742430841572532807506e-12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 20)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.79011407780867471284567547634162699267979186606188e-13), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 21)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.44751775633854916204285667335984781835956253195982e-13), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 22)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.61878017561309094548695350627490496501579775589554e-14), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 23)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.04693171826032841875566733962302122545285900020005e-15), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 24)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26173047049833308211942124367857471386868403241961e-15), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.65432295369693602811408648241147072923809751085578e-16), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 26)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41358031701599971473805281134574751063094181933632e-16), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 27)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.53395024254254681824332124678431347548990493315457e-17), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 28)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.83487488981301080647710951024578189621167614209000e-18), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 29)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.20871862925450931967259224559170596670053211110073e-18), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 30)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.52179645209930996243372289840247886946662593536877e-19), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 31)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38044909732789001695763980339161333087125784369381e-19), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 32)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.45112272298940668060590155421055597940788628104792e-20), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 34)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15695169189532579197171519055168026495351913764385e-21), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 36)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.34809480577241011630081955001585893790541249979882e-22), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 38)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.42559253331811413189334788330851699569177453819777e-24), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 40)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.26599533286729634727335420905860617977183492898697e-25), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 42)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.29124708296676552183969416435576047604811850887072e-26), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 44)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.05702942684184448841776719264034349959339461930208e-27), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 46)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28564339177412106630199552439532586497065103592483e-28), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 48)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.03527119858493090854162194048072858076706076597819e-30), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 50)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.02204449911503854915599875932648541933495423396290e-31), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 52)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13877781194681051697029360385733987849026091896815e-32), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 54)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.96173613246674215642318845771797429014235991071697e-33), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 56)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.22608508279171150505713607335390403334626262247470e-34), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 58)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.66303176744819310534466860343470655112837733629379e-36), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 60)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.78939485465512007489594618239133015330653514470962e-37), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 62)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.99337178415944994713157754959412500112801769504923e-38), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 64)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.87085736509965620084544629248142254049400680133870e-39), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 68)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.30803658242053201409813080005840450554429514097447e-42), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 72)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85470179000802031747569733233640023770585023325816e-44), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 76)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.11511788672188293650018950543585978468059122696737e-46), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 80)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.35592924500735522070031636324180548468184125270321e-49), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 84)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.70153486133099813308596977841944913997064236009234e-51), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 88)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.64662055207421145736704601944518511418678161667227e-54), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 92)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.59633615315398885053400175162079403845778513781261e-56), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 96)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01419380982577689473984441890730791873276374028644e-58), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 100)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.96169456963194099507751725745105477863201113021124e-61), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 104)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.54753694126247695120215517859242605013890436588657e-63), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 108)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04506617680655059063341866635141218965712131228669e-66), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 112)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.36135397531505882446617916654287979923104956976029e-68), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 116)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.22403896607444853307101236930796194301091622511538e-71), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 120)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.60314022112283145823086420676091852871339922342198e-73), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 124)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40747664887610603837143133076598369654786648237564e-75), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.49795565967228921238840363580462378845964351238859e-78), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 128)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.49795565967228921238840363580462378845964351238859e-78), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 136)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.38921456859174989683289128998508268228293005240118e-83), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 144)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28009255502193449353529225005875895420403010118164e-87), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 152)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.95326622775563734975477943429376061127322830738396e-92), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 160)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.98044773522283531151547154891015718272892496044375e-97), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 168)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.54780233035710954515910575700402402149799340844629e-102), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 176)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.93939564568650748467881127472537845077208466864701e-107), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 184)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.05886774378761405711041431804281287395814280222275e-111), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 192)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.61570395475404976976076403509950694878867004733696e-116), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 200)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.46536858330390895044061895004197227293193061422265e-121), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 208)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.76185391739488060064791709906306804341420076633095e-126), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 216)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.74013354094677826026598678445902716585418818104698e-131), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 224)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.75874868918880960123594174874729486977262600867765e-136), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 232)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.33647898699780419940733974437672346035348907603114e-140), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 240)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.03930509490631744294332846737170938164289714970571e-145), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 248)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.11173262772570410605366282252763272345412773087419e-150), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist, ldexp(static_cast(1), 256)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.74812717853653580635629703144475208046589314403411e-155), (tolerance) / 100); } template @@ -250,85 +247,85 @@ void do_test_landau_cdf() { landau_distribution dist(static_cast(0), static_cast(1)); // Left tail of Landau distribution inherently limits accuracy due to the rapid decay of the function value. - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.23104384186197610398535377648417544130503923472088e-2767), tolerance * 10000); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13839831060468958638389597955042905895011279005609e-1263), tolerance * 10000); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.44312475898376675389279659203392726913179988221856e-577), tolerance * 4000); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.60161744250590449897633679409320688863793657438650e-264), tolerance * 1000); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.35715172357835600843326068305277508896293574359993e-122), tolerance * 400); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21485044777822987831938208827397125595048645106450e-56), tolerance * 100); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.20700596052912975894895710721207297741913643002012e-39), tolerance * 100); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.68977785355043338853968150291349097131276031028880e-27), tolerance * 100); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08280503661515358192902976596786876511904900370188e-18), tolerance * 100); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.65792002575428625860974216754165889856915439054540e-13), tolerance * 40); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.10050102765608360408879765554028186586411956977646e-9), tolerance * 40); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.68815894016077213783105942021589578300879813020189e-7), tolerance * 10); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.37625644367407768681214121219960213300943983402353e-5), tolerance * 4); - - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.07114056489178077422539043012078031612755414599729e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02378089289225642153717146519785629105551593533471e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.86628849116890981757518380028315283124563329691336e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01356086445894450901462536543096095003540865562528e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.87500433294484935737405475465845379363381335629325e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.14477362642888337899595114315256777323730741351157e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.86347714259952478386139532766899266845283140865196e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.03233833485353985646171581359634291113172343250638e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.61609610406317335842332400044553397267403259400925e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10447280320452875363390566033897366825208362273976e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.25520504813750944299743577454809066282274647597463e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41278210604233003854999957016294448201095585229262e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.57614904197281705412681135912362432813551089393050e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.74424900339390561779123457277662541525802871208804e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.91604740159711318114657552509684829710278507526176e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.09055135109096066379824832581601920047332653592899e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26682451996131584587603100587452166035163093744954e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.44399775009966844789856291613140149240683895719411e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62127593214618528740100724985588598153581542828585e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.79794168130771479096847395825066083537476191027208e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.97335637253762835584202042505471763077481208909960e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.14695907126043189562824247063432944143645211079990e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.31826385110143246791390839018674857130873325623297e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(-0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.48685593270949525320895832911820568633181874504622e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.65238701512374797371944390202236332910560491002867e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.81457010849525523978613828303353744448250289768502e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.97317411782647886281236276761522493696113175680302e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.12801837383425412356107316013533713934091886254748e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.27896726012877622151287254340779424837571495657384e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.42592504593813016256394437035333320729928769135529e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.56883100040026405468976154826963286030986607276898e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.70765483748602800807348700535078666283426208025338e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.84239251923251354944511010208659148773285992261636e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.97306242841106189982720542754596269997825882200963e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.09970190928358551894563742001208165448751595738393e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.22236416601074576846725329522076603667792610069772e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.34111550192882688466795267571966376590108144590146e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.45603287874932276581779533145259002587664864932810e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.56720177227709322443036736236667681466823855576748e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.67471430008752600464561254217339060305933972234066e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.77866759641952347636729485475686950346612605081233e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.97630190201768046886571833364686445094779890812683e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.16093363694296970300414411298982724729800950998126e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.33340119589825831941744118804669746898228023705595e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.49453081078357569536385447775302397639174227456126e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.64512181956668895495628599815612188484872430606076e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.78593712196194817010501161391740217697424135219932e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.91769748027973587988050487247823119315646010788285e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.04107862044208783622223577234526499721208130809085e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.26517695571963502030771662018373539384937999898516e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.46273425405663094259919090350425049446731674380517e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.63758376080325935199241149369372014196158210794207e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.79296673358868394263845167623854238605663977145579e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.93161494811251760796024569455411548871678150466575e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.05582884526567009703468807923041602465523081207835e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.16754715036218405381848078882559199991501527210887e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.26840681332434061224397365001110201431714574161004e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.44288421192372625436336887550283154670590764164969e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.58804227080862094903927728732613232538756639404536e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.71029700052871041881284261613115047981162112317573e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.81440531622793612780308998937907666985394243647458e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.90394591759649482553720310181182407678855125658003e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.98164927634689821536641290454567745500263396394663e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(7.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.04962661826577677675750333226666504803112871241155e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(dist, static_cast(8)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.10953085258825170758957718650744990707007748273190e-1), tolerance); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.23104384186197610398535377648417544130503923472088e-2767), (tolerance * 10000) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13839831060468958638389597955042905895011279005609e-1263), (tolerance * 10000) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.44312475898376675389279659203392726913179988221856e-577), (tolerance * 4000) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.60161744250590449897633679409320688863793657438650e-264), (tolerance * 1000) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.35715172357835600843326068305277508896293574359993e-122), (tolerance * 400) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21485044777822987831938208827397125595048645106450e-56), (tolerance * 100) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.20700596052912975894895710721207297741913643002012e-39), (tolerance * 100) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.68977785355043338853968150291349097131276031028880e-27), (tolerance * 100) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.08280503661515358192902976596786876511904900370188e-18), (tolerance * 100) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.65792002575428625860974216754165889856915439054540e-13), (tolerance * 40) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.10050102765608360408879765554028186586411956977646e-9), (tolerance * 40) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.68815894016077213783105942021589578300879813020189e-7), (tolerance * 10) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.37625644367407768681214121219960213300943983402353e-5), (tolerance * 4) / 100); + + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.07114056489178077422539043012078031612755414599729e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.02378089289225642153717146519785629105551593533471e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.86628849116890981757518380028315283124563329691336e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01356086445894450901462536543096095003540865562528e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.87500433294484935737405475465845379363381335629325e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.14477362642888337899595114315256777323730741351157e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.86347714259952478386139532766899266845283140865196e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.03233833485353985646171581359634291113172343250638e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.61609610406317335842332400044553397267403259400925e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10447280320452875363390566033897366825208362273976e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.25520504813750944299743577454809066282274647597463e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41278210604233003854999957016294448201095585229262e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.57614904197281705412681135912362432813551089393050e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.74424900339390561779123457277662541525802871208804e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.91604740159711318114657552509684829710278507526176e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.09055135109096066379824832581601920047332653592899e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26682451996131584587603100587452166035163093744954e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.44399775009966844789856291613140149240683895719411e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62127593214618528740100724985588598153581542828585e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.79794168130771479096847395825066083537476191027208e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.97335637253762835584202042505471763077481208909960e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.14695907126043189562824247063432944143645211079990e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.31826385110143246791390839018674857130873325623297e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(-0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.48685593270949525320895832911820568633181874504622e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.65238701512374797371944390202236332910560491002867e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.81457010849525523978613828303353744448250289768502e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.97317411782647886281236276761522493696113175680302e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.12801837383425412356107316013533713934091886254748e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.27896726012877622151287254340779424837571495657384e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.42592504593813016256394437035333320729928769135529e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.56883100040026405468976154826963286030986607276898e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.70765483748602800807348700535078666283426208025338e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.84239251923251354944511010208659148773285992261636e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.97306242841106189982720542754596269997825882200963e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.09970190928358551894563742001208165448751595738393e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.22236416601074576846725329522076603667792610069772e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.34111550192882688466795267571966376590108144590146e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.45603287874932276581779533145259002587664864932810e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.56720177227709322443036736236667681466823855576748e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.67471430008752600464561254217339060305933972234066e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.77866759641952347636729485475686950346612605081233e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.97630190201768046886571833364686445094779890812683e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.16093363694296970300414411298982724729800950998126e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.33340119589825831941744118804669746898228023705595e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.49453081078357569536385447775302397639174227456126e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.64512181956668895495628599815612188484872430606076e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.78593712196194817010501161391740217697424135219932e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(1.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.91769748027973587988050487247823119315646010788285e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(2)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.04107862044208783622223577234526499721208130809085e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(2.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.26517695571963502030771662018373539384937999898516e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(2.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.46273425405663094259919090350425049446731674380517e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(2.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.63758376080325935199241149369372014196158210794207e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(3)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.79296673358868394263845167623854238605663977145579e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(3.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.93161494811251760796024569455411548871678150466575e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(3.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.05582884526567009703468807923041602465523081207835e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(3.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.16754715036218405381848078882559199991501527210887e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(4)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.26840681332434061224397365001110201431714574161004e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(4.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.44288421192372625436336887550283154670590764164969e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.58804227080862094903927728732613232538756639404536e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(5.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.71029700052871041881284261613115047981162112317573e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(6)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.81440531622793612780308998937907666985394243647458e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(6.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.90394591759649482553720310181182407678855125658003e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(7)), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.98164927634689821536641290454567745500263396394663e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(7.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.04962661826577677675750333226666504803112871241155e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist, static_cast(8)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.10953085258825170758957718650744990707007748273190e-1), (tolerance) / 100); } template @@ -344,177 +341,177 @@ void do_test_landau_ccdf() { landau_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-2))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.99292885943510821922577460956987921968387244585400e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.97976219107107743578462828534802143708944484064665e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.95133711508831090182424816199716847168754366703087e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.89864391355410554909853746345690390499645913443747e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.81249956670551506426259452453415462063661866437068e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.68552263735711166210040488568474322267626925864884e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.51365228574004752161386046723310073315471685913480e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.29676616651464601435382841864036570888682765674936e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-1))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.03839038959368266415766759995544660273259674059908e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.9375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.89552719679547124636609433966102633174791637726024e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.74479495186249055700256422545190933717725352402537e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.8125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.58721789395766996145000042983705551798904414770738e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.42385095802718294587318864087637567186448910606950e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.6875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.25575099660609438220876542722337458474197128791196e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.08395259840288681885342447490315170289721492473824e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.5625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.90944864890903933620175167418398079952667346407101e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.73317548003868415412396899412547833964836906255046e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.55600224990033155210143708386859850759316104280589e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.37872406785381471259899275014411401846418457171415e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.20205831869228520903152604174933916462523808972792e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.02664362746237164415797957494528236922518791090040e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.85304092873956810437175752936567055856354788920010e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.68173614889856753208609160981325142869126674376703e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(-0.0625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.51314406729050474679104167088179431366818125495378e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.34761298487625202628055609797763667089439508997133e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.0625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.18542989150474476021386171696646255551749710231498e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.02682588217352113718763723238477506303886824319698e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.87198162616574587643892683986466286065908113745252e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.72103273987122377848712745659220575162428504342616e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.57407495406186983743605562964666679270071230864471e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.43116899959973594531023845173036713969013392723102e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.29234516251397199192651299464921333716573791974662e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.15760748076748645055488989791340851226714007738364e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.5625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.02693757158893810017279457245403730002174117799037e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.90029809071641448105436257998791834551248404261607e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.6875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.77763583398925423153274670477923396332207389930228e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.65888449807117311533204732428033623409891855409854e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.8125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.54396712125067723418220466854740997412335135067190e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.43279822772290677556963263763332318533176144423252e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(0.9375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.32528569991247399535438745782660939694066027765934e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.22133240358047652363270514524313049653387394918767e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.02369809798231953113428166635313554905220109187317e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.83906636305703029699585588701017275270199049001874e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.66659880410174168058255881195330253101771976294405e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.50546918921642430463614552224697602360825772543874e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.35487818043331104504371400184387811515127569393924e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.21406287803805182989498838608259782302575864780068e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.08230251972026412011949512752176880684353989211715e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(2))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.95892137955791216377776422765473500278791869190915e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(2.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.73482304428036497969228337981626460615062000101484e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(2.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.53726574594336905740080909649574950553268325619483e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(2.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.36241623919674064800758850630627985803841789205793e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(3))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.20703326641131605736154832376145761394336022854421e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(3.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.06838505188748239203975430544588451128321849533425e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(3.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.94417115473432990296531192076958397534476918792165e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(3.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.83245284963781594618151921117440800008498472789113e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(4))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.73159318667565938775602634998889798568285425838996e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(4.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55711578807627374563663112449716845329409235835031e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41195772919137905096072271267386767461243360595464e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(5.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28970299947128958118715738386884952018837887682427e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(6))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.18559468377206387219691001062092333014605756352542e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(6.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.09605408240350517446279689818817592321144874341997e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(7))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01835072365310178463358709545432254499736603605337e-1), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(7.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.50373381734223223242496667733334951968871287588448e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(8))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.90469147411748292410422813492550092929922517268105e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(9))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.89904178519375419646729692713027452766956304810423e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(10))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.08967063825624536726393015854367927398248532043928e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(11))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.42552960269528172637745151674852945361026757129572e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.87155991603325430279966781361705985837149401924358e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(13))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.40297179699419503759356245733027728020687579530781e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.00178775061898975362196226343808042189550214610720e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(15))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.65467961100606469227978737829290437667112287748795e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.35157264931262089761621934621402648953813567255367e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(18))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.84807181681993477724365847791930879377149510380933e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.44719141256297825765636022076703604777398281522436e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(22))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.12076533048217442252783357779404422496811288961954e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.84999992100002427148546326508663805148388380497970e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(26))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62189540632143171631461472152513248987041904718627e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42718378313424593748302632910098340183096121887744e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(30))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25908549106503559691958010353777133320615316433912e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.11253031965493064317003259449214452744697000964364e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(36))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.86945568960396455137037115431688883900622129241921e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.67614509428664592918239573763993132586708338097148e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(44))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51880213758692367036733937634308433186738240289411e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38828350661980875444222979837389265249992909781147e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(52))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.27829420024685114258602774435891775801837844690349e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.18436085060190590919501220038943005140750783789755e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(60))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10321854418155548568175979136702978995567636390268e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.03242932255189471157625857327944947615628400066886e-2), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(72))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.14901073563432515854150573798153430678589620957278e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.21304799594562916903235283213953478595851140543801e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(88))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.45021033455396813779806884621309261695988381836678e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.81662081970375351344432645398857600988792278643367e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(104))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.28205524656921301117582740567146809114392866561466e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.82502022536734166688286248837161828142031676980706e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(120))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.42981578145699797251974720633677573816663490439276e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.08470827750959570805565668839133674990776529552199e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.51875926400324844459822808369891291211052352126700e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(512))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.25243798184186193073508388843632555296804735961418e-3), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, static_cast(1024))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.24222666597149382309278694960823422316591681354937e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 11))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.11546656864925721385400506911714668228522959074988e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55615661646764419866569094853675423840407090817980e-4), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 13))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.77642694561457848096607089076550607777923417509897e-5), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.88702045347145575328162812652239839108265167027629e-5), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 15))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.94318591305792177162247519775866592794374293269769e-5), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.71505353250968890581644704744607604904036466331858e-6), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 17))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.85729142998688039060495209150963975787147384530557e-6), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 18))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42858279647060361837158514176420066606677711840386e-6), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 19))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21427464712490151175367196840586966659512986509712e-6), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.07132880360935675845351982773327267915998066915668e-7), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 21))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.03565265516245957916479321487698564090018898313690e-7), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 22))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51782323124974173858669998521646771346131838415381e-7), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 23))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.58910801622650317351735034158503382297981706223572e-8), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.79455187330704471571840926063516392410676855026673e-8), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.89727537800148613712401816975344760624742045931026e-8), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 26))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.48637543100068173667331269634864926724205314304352e-9), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 27))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.74318733515442703770226252397963326193722512832281e-9), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.37159356859216986241429458639296184020669300874754e-9), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 29))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.18579675857518154364748998529259019922036982534955e-9), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 30))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.92898372613704146131858586390099325449659727514527e-10), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 31))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.96449184577465200097456706940455493448424599625049e-10), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.48224591841157074706460083370955443589105978681308e-10), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 34))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.70561478725616554450782995120929832467409189826579e-11), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 36))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.26403696230051280181276990208319690098486010067856e-12), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 38))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.31600924018782655652761250713319794226217154394605e-12), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.79002310021356047142575775154740548981748412961642e-13), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 42))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.44750577503651834833347404492486283164453776697661e-13), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 44))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.61876443758020639017543150875739203546579850550506e-14), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 46))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.04691109394324465958560412889011979187196424398413e-15), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26172777348533543325299108739056247374472601114618e-15), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 50))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.65431943371302795435372191153510741742082062236667e-16), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 52))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41357985842823674325840669958475387008031322630868e-16), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 54))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.53394964607057868542015717421467433254478008250729e-17), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.83487411517643815597510900540151314745726776276537e-18), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 58))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.20871852879410898385647064972035961074675685323943e-18), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 60))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.52179632198527209999982790078399565586115610945978e-19), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 62))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38044908049631800172983942388255378445601347506470e-19), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.45112270124079498928544180507695627740193986743475e-20), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 68))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15695168827549686524997208584894563633442321098092e-21), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 72))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.34809480517218554065439979557746061380338130338956e-22), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 76))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.42559253232615962903750225978472507493251963237152e-24), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.26599533270384976814627294052855716278192786930198e-25), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 84))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.29124708293990610509133147452548575130220036516594e-26), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 88))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.05702942683744131568207851461222366485608388136168e-27), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 92))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28564339177340082230129892190826718627845694793237e-28), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.03527119858375513938311820075537974687844953537787e-30), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 100))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.02204449911484696211444887297771791655738720297691e-31), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 104))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13877781194677935132153054550953911471083914854259e-32), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 108))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.96173613246673709457595659093933570122399892106597e-33), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.22608508279171068410997286933691737981629848926873e-34), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 116))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.66303176744819177568733043335566577797931906017599e-36), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 120))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.78939485465511985980458152084728836560995745045025e-37), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 124))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.99337178415944991237786345052955511752869068868957e-38), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.87085736509965619523616465658097194397480643905015e-39), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.87085736509965619523616465658097194397480643905015e-39), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 136))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.30803658242053201264126818976942165494933536744296e-42), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 144))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85470179000802031743799538662868033396263440343802e-44), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 152))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.11511788672188293649921694790182825545415091296783e-46), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 160))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.35592924500735522070006620274151662286777695301906e-49), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 168))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.70153486133099813308596336044590493080772537219152e-51), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 176))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.64662055207421145736704437674181613596767723512183e-54), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 184))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.59633615315398885053400170966477192811237391996946e-56), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 192))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01419380982577689473984441783780153441889606248807e-58), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 200))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.96169456963194099507751725717891224382381274409403e-61), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 208))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.54753694126247695120215517858551259524367685316173e-63), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 216))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04506617680655059063341866634965857517061270766301e-66), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 224))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.36135397531505882446617916654283538092602058893086e-68), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 232))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.22403896607444853307101236930795070674226792551118e-71), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 240))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.60314022112283145823086420676091824482119840840280e-73), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 248))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40747664887610603837143133076598368938328062828235e-75), tolerance); - BOOST_CHECK_CLOSE(cdf(complement(dist, ldexp(static_cast(1), 256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.49795565967228921238840363580462378665343995422791e-78), tolerance); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-2))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.99292885943510821922577460956987921968387244585400e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.97976219107107743578462828534802143708944484064665e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.95133711508831090182424816199716847168754366703087e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.89864391355410554909853746345690390499645913443747e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.81249956670551506426259452453415462063661866437068e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.68552263735711166210040488568474322267626925864884e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.51365228574004752161386046723310073315471685913480e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.29676616651464601435382841864036570888682765674936e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-1))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.03839038959368266415766759995544660273259674059908e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.9375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.89552719679547124636609433966102633174791637726024e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.74479495186249055700256422545190933717725352402537e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.8125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.58721789395766996145000042983705551798904414770738e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.42385095802718294587318864087637567186448910606950e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.6875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.25575099660609438220876542722337458474197128791196e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.08395259840288681885342447490315170289721492473824e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.5625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.90944864890903933620175167418398079952667346407101e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.73317548003868415412396899412547833964836906255046e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.55600224990033155210143708386859850759316104280589e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.37872406785381471259899275014411401846418457171415e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.20205831869228520903152604174933916462523808972792e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.02664362746237164415797957494528236922518791090040e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.85304092873956810437175752936567055856354788920010e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.68173614889856753208609160981325142869126674376703e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(-0.0625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.51314406729050474679104167088179431366818125495378e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.34761298487625202628055609797763667089439508997133e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.0625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.18542989150474476021386171696646255551749710231498e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.02682588217352113718763723238477506303886824319698e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.87198162616574587643892683986466286065908113745252e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.72103273987122377848712745659220575162428504342616e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.57407495406186983743605562964666679270071230864471e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.43116899959973594531023845173036713969013392723102e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.29234516251397199192651299464921333716573791974662e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.15760748076748645055488989791340851226714007738364e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.5625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.02693757158893810017279457245403730002174117799037e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.90029809071641448105436257998791834551248404261607e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.6875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.77763583398925423153274670477923396332207389930228e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.65888449807117311533204732428033623409891855409854e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.8125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.54396712125067723418220466854740997412335135067190e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.43279822772290677556963263763332318533176144423252e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(0.9375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.32528569991247399535438745782660939694066027765934e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.22133240358047652363270514524313049653387394918767e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.02369809798231953113428166635313554905220109187317e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.83906636305703029699585588701017275270199049001874e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.66659880410174168058255881195330253101771976294405e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.50546918921642430463614552224697602360825772543874e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.35487818043331104504371400184387811515127569393924e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.21406287803805182989498838608259782302575864780068e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1.875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.08230251972026412011949512752176880684353989211715e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(2))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.95892137955791216377776422765473500278791869190915e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(2.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.73482304428036497969228337981626460615062000101484e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(2.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.53726574594336905740080909649574950553268325619483e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(2.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.36241623919674064800758850630627985803841789205793e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(3))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.20703326641131605736154832376145761394336022854421e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(3.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.06838505188748239203975430544588451128321849533425e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(3.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.94417115473432990296531192076958397534476918792165e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(3.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.83245284963781594618151921117440800008498472789113e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(4))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.73159318667565938775602634998889798568285425838996e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(4.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55711578807627374563663112449716845329409235835031e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41195772919137905096072271267386767461243360595464e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(5.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28970299947128958118715738386884952018837887682427e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(6))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.18559468377206387219691001062092333014605756352542e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(6.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.09605408240350517446279689818817592321144874341997e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(7))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01835072365310178463358709545432254499736603605337e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(7.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.50373381734223223242496667733334951968871287588448e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(8))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.90469147411748292410422813492550092929922517268105e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(9))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.89904178519375419646729692713027452766956304810423e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(10))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.08967063825624536726393015854367927398248532043928e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(11))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.42552960269528172637745151674852945361026757129572e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.87155991603325430279966781361705985837149401924358e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(13))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.40297179699419503759356245733027728020687579530781e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.00178775061898975362196226343808042189550214610720e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(15))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.65467961100606469227978737829290437667112287748795e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.35157264931262089761621934621402648953813567255367e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(18))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.84807181681993477724365847791930879377149510380933e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.44719141256297825765636022076703604777398281522436e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(22))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.12076533048217442252783357779404422496811288961954e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.84999992100002427148546326508663805148388380497970e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(26))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.62189540632143171631461472152513248987041904718627e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42718378313424593748302632910098340183096121887744e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(30))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.25908549106503559691958010353777133320615316433912e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.11253031965493064317003259449214452744697000964364e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(36))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.86945568960396455137037115431688883900622129241921e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.67614509428664592918239573763993132586708338097148e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(44))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51880213758692367036733937634308433186738240289411e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38828350661980875444222979837389265249992909781147e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(52))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.27829420024685114258602774435891775801837844690349e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.18436085060190590919501220038943005140750783789755e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(60))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.10321854418155548568175979136702978995567636390268e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.03242932255189471157625857327944947615628400066886e-2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(72))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.14901073563432515854150573798153430678589620957278e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.21304799594562916903235283213953478595851140543801e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(88))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.45021033455396813779806884621309261695988381836678e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.81662081970375351344432645398857600988792278643367e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(104))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.28205524656921301117582740567146809114392866561466e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.82502022536734166688286248837161828142031676980706e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(120))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.42981578145699797251974720633677573816663490439276e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.08470827750959570805565668839133674990776529552199e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.51875926400324844459822808369891291211052352126700e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(512))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.25243798184186193073508388843632555296804735961418e-3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, static_cast(1024))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.24222666597149382309278694960823422316591681354937e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 11))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.11546656864925721385400506911714668228522959074988e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55615661646764419866569094853675423840407090817980e-4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 13))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.77642694561457848096607089076550607777923417509897e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.88702045347145575328162812652239839108265167027629e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 15))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.94318591305792177162247519775866592794374293269769e-5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.71505353250968890581644704744607604904036466331858e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 17))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.85729142998688039060495209150963975787147384530557e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 18))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.42858279647060361837158514176420066606677711840386e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 19))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.21427464712490151175367196840586966659512986509712e-6), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.07132880360935675845351982773327267915998066915668e-7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 21))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.03565265516245957916479321487698564090018898313690e-7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 22))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.51782323124974173858669998521646771346131838415381e-7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 23))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.58910801622650317351735034158503382297981706223572e-8), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.79455187330704471571840926063516392410676855026673e-8), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.89727537800148613712401816975344760624742045931026e-8), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 26))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.48637543100068173667331269634864926724205314304352e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 27))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.74318733515442703770226252397963326193722512832281e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.37159356859216986241429458639296184020669300874754e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 29))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.18579675857518154364748998529259019922036982534955e-9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 30))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.92898372613704146131858586390099325449659727514527e-10), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 31))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.96449184577465200097456706940455493448424599625049e-10), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.48224591841157074706460083370955443589105978681308e-10), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 34))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.70561478725616554450782995120929832467409189826579e-11), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 36))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.26403696230051280181276990208319690098486010067856e-12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 38))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.31600924018782655652761250713319794226217154394605e-12), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.79002310021356047142575775154740548981748412961642e-13), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 42))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.44750577503651834833347404492486283164453776697661e-13), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 44))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.61876443758020639017543150875739203546579850550506e-14), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 46))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.04691109394324465958560412889011979187196424398413e-15), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.26172777348533543325299108739056247374472601114618e-15), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 50))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.65431943371302795435372191153510741742082062236667e-16), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 52))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.41357985842823674325840669958475387008031322630868e-16), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 54))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.53394964607057868542015717421467433254478008250729e-17), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.83487411517643815597510900540151314745726776276537e-18), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 58))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.20871852879410898385647064972035961074675685323943e-18), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 60))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.52179632198527209999982790078399565586115610945978e-19), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 62))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.38044908049631800172983942388255378445601347506470e-19), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.45112270124079498928544180507695627740193986743475e-20), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 68))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15695168827549686524997208584894563633442321098092e-21), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 72))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.34809480517218554065439979557746061380338130338956e-22), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 76))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.42559253232615962903750225978472507493251963237152e-24), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.26599533270384976814627294052855716278192786930198e-25), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 84))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.29124708293990610509133147452548575130220036516594e-26), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 88))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.05702942683744131568207851461222366485608388136168e-27), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 92))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.28564339177340082230129892190826718627845694793237e-28), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.03527119858375513938311820075537974687844953537787e-30), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 100))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.02204449911484696211444887297771791655738720297691e-31), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 104))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.13877781194677935132153054550953911471083914854259e-32), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 108))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.96173613246673709457595659093933570122399892106597e-33), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.22608508279171068410997286933691737981629848926873e-34), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 116))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.66303176744819177568733043335566577797931906017599e-36), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 120))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.78939485465511985980458152084728836560995745045025e-37), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 124))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.99337178415944991237786345052955511752869068868957e-38), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.87085736509965619523616465658097194397480643905015e-39), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.87085736509965619523616465658097194397480643905015e-39), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 136))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.30803658242053201264126818976942165494933536744296e-42), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 144))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.85470179000802031743799538662868033396263440343802e-44), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 152))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.11511788672188293649921694790182825545415091296783e-46), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 160))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.35592924500735522070006620274151662286777695301906e-49), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 168))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.70153486133099813308596336044590493080772537219152e-51), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 176))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.64662055207421145736704437674181613596767723512183e-54), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 184))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.59633615315398885053400170966477192811237391996946e-56), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 192))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.01419380982577689473984441783780153441889606248807e-58), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 200))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.96169456963194099507751725717891224382381274409403e-61), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 208))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.54753694126247695120215517858551259524367685316173e-63), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 216))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.04506617680655059063341866634965857517061270766301e-66), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 224))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.36135397531505882446617916654283538092602058893086e-68), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 232))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.22403896607444853307101236930795070674226792551118e-71), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 240))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.60314022112283145823086420676091824482119840840280e-73), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 248))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.40747664887610603837143133076598368938328062828235e-75), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(complement(dist, ldexp(static_cast(1), 256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.49795565967228921238840363580462378665343995422791e-78), (tolerance) / 100); } template @@ -530,40 +527,40 @@ void do_test_landau_quantile_nearzero() { landau_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.03125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.37666142124664870427736212608782014348092232942703e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.16727296241754547290632950718657110865371011883488e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.09375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.01093317611810417245689707499918702758654056685650e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.77109518013577849065583862782160134594408514905936e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.15625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -7.55147864363163697663604936395052484592948168261254e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.39830737061008092918841929339491480637487863539219e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.21875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.28068260002115642528019835718799250663117082682413e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.17764764050720242897742634974454174978089714315837e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.28125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.07332710058680816601395586920882835843791948709923e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.95448171270527198765810574858446724358448730774699e-1), tolerance); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.03125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.37666142124664870427736212608782014348092232942703e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.0625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.16727296241754547290632950718657110865371011883488e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.09375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.01093317611810417245689707499918702758654056685650e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.77109518013577849065583862782160134594408514905936e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.15625)), BOOST_MATH_BIG_CONSTANT(RealType, N, -7.55147864363163697663604936395052484592948168261254e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.1875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.39830737061008092918841929339491480637487863539219e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.21875)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.28068260002115642528019835718799250663117082682413e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.25)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.17764764050720242897742634974454174978089714315837e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.28125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.07332710058680816601395586920882835843791948709923e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.3125)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.95448171270527198765810574858446724358448730774699e-1), (tolerance) / 100); // Relative error decreases near the root. - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.34375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.09096582988749397639311472333288802663134525410086e-2), tolerance * 10); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.74557416577759248536854968412795127813716796439183e-2), tolerance * 10); - - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.40625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.60865269786540938863996714417993425933643390360701e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.90647080532071673100911236876323489196027799942628e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.46875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.28310640852292004320545764804480585932279888826464e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.75630143945078214396279308922575172688187402052064e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.53125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.34751649957416497391423738312790099231331963193670e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.08338732735341567163440035550389980881822036530441e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.59375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.09977916217503813825408682237719484284367467701518e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.31348919222343858173602105619413807214737739605647e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.65625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55537778016228176635489075791437025790508273018206e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.83358201486120130332744845371832465533289389791770e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.71875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15968268411007811908706240304578653239207877720217e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.55081568282045925871949387822806899205587760602861e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.78125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.03356573722052416577951184486453626014326770622663e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.65170109428623528831428068089551728119930570543517e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.84375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.48307637103506875745328267812359172615004959210209e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.68160868054034088524891526884683024288168516466432e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.90625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.60235856635301171960591513042024596858455255485505e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12983583770683756688253603663598582344177172936943e1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, static_cast(0.96875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19714287107110229779819680655029619622254635434578e1), tolerance); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.34375)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.09096582988749397639311472333288802663134525410086e-2), (tolerance * 10) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.74557416577759248536854968412795127813716796439183e-2), (tolerance * 10) / 100); + + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.40625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.60865269786540938863996714417993425933643390360701e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.4375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.90647080532071673100911236876323489196027799942628e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.46875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.28310640852292004320545764804480585932279888826464e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.5)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.75630143945078214396279308922575172688187402052064e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.53125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.34751649957416497391423738312790099231331963193670e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.5625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.08338732735341567163440035550389980881822036530441e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.59375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.09977916217503813825408682237719484284367467701518e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.31348919222343858173602105619413807214737739605647e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.65625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55537778016228176635489075791437025790508273018206e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.6875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.83358201486120130332744845371832465533289389791770e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.71875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15968268411007811908706240304578653239207877720217e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.75)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.55081568282045925871949387822806899205587760602861e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.78125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.03356573722052416577951184486453626014326770622663e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.8125)), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.65170109428623528831428068089551728119930570543517e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.84375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.48307637103506875745328267812359172615004959210209e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.68160868054034088524891526884683024288168516466432e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.90625)), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.60235856635301171960591513042024596858455255485505e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.9375)), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12983583770683756688253603663598582344177172936943e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, static_cast(0.96875)), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19714287107110229779819680655029619622254635434578e1), (tolerance) / 100); } template @@ -579,61 +576,61 @@ void do_test_landau_quantile_lower() { landau_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -3)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.77109518013577849065583862782160134594408514905936e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -4)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.16727296241754547290632950718657110865371011883488e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -5)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.37666142124664870427736212608782014348092232942703e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -6)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.53937945687640569563878953898367418895418286968892e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -7)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.67193057806636817209385515556513905369159305215132e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -8)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.78348038398799867332294266481364804262899249535026e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -10)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.96398712546539547900868300204740158406402253850740e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -12)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.10672834330580928387396530276881975373360375562766e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -14)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.22455234225296140347183338705883529117630663916504e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -16)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.32474749499506228416012679106564721359216355271060e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -20)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.48880222197195858123676152921728490355916489072920e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -24)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.62012266244208104039475013076613716084830146896364e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -28)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.72950770317262402197221324973838006547359087175177e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -32)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.82318656228158372073367735499500997206084370651970e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -40)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.97778747939490003780916437343292886429806927997697e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -48)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.10253941103391799610961378724535481625827036745191e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -56)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.20706965504048009454149883353144814083641366738928e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -64)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.29700011190686230364493911161520662289614047608888e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -80)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.44616534249558131319374859709618689440842790052762e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -96)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.56714397893479094507321490741760621098238204564655e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -112)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.66888826418737343076580628480419340009764391741662e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -128)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.75666995985336007747791649448887717847452667971341e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -160)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.90272386559500090814947503869007637264448398505091e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -192)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.02154690255519314578158695811138813197102888432118e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -224)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.12170243205222902851790251956181678240666087312573e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -256)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.20826069989721596260510558511263030379850705902299e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -320)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.35254674338923723387138280464388000015841039600555e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -384)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.47014796872616976009165833857464389146621180677518e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -448)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.56940486432189047495132801898571896454756873328884e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -512)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.65527239540648657446629479052874024150007745617425e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -640)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.79856256497052731627737920479094219620428520302497e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -768)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.91547732272180866354170476973276286391282782030491e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -896)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.01423042502756027207185677104980034013809957436307e0), tolerance); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -3)), BOOST_MATH_BIG_CONSTANT(RealType, N, -8.77109518013577849065583862782160134594408514905936e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -4)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.16727296241754547290632950718657110865371011883488e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -5)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.37666142124664870427736212608782014348092232942703e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -6)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.53937945687640569563878953898367418895418286968892e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -7)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.67193057806636817209385515556513905369159305215132e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -8)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.78348038398799867332294266481364804262899249535026e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -10)), BOOST_MATH_BIG_CONSTANT(RealType, N, -1.96398712546539547900868300204740158406402253850740e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -12)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.10672834330580928387396530276881975373360375562766e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -14)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.22455234225296140347183338705883529117630663916504e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -16)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.32474749499506228416012679106564721359216355271060e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -20)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.48880222197195858123676152921728490355916489072920e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -24)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.62012266244208104039475013076613716084830146896364e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -28)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.72950770317262402197221324973838006547359087175177e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -32)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.82318656228158372073367735499500997206084370651970e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -40)), BOOST_MATH_BIG_CONSTANT(RealType, N, -2.97778747939490003780916437343292886429806927997697e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -48)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.10253941103391799610961378724535481625827036745191e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -56)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.20706965504048009454149883353144814083641366738928e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -64)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.29700011190686230364493911161520662289614047608888e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -80)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.44616534249558131319374859709618689440842790052762e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -96)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.56714397893479094507321490741760621098238204564655e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -112)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.66888826418737343076580628480419340009764391741662e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -128)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.75666995985336007747791649448887717847452667971341e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -160)), BOOST_MATH_BIG_CONSTANT(RealType, N, -3.90272386559500090814947503869007637264448398505091e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -192)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.02154690255519314578158695811138813197102888432118e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -224)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.12170243205222902851790251956181678240666087312573e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -256)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.20826069989721596260510558511263030379850705902299e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -320)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.35254674338923723387138280464388000015841039600555e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -384)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.47014796872616976009165833857464389146621180677518e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -448)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.56940486432189047495132801898571896454756873328884e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -512)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.65527239540648657446629479052874024150007745617425e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -640)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.79856256497052731627737920479094219620428520302497e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -768)), BOOST_MATH_BIG_CONSTANT(RealType, N, -4.91547732272180866354170476973276286391282782030491e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -896)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.01423042502756027207185677104980034013809957436307e0), (tolerance) / 100); // The test is terminated because p = 0 after this in fp64. if(N <= 53){ return; } - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -1024)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.09971143249822249471944441552701750744803726485204e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -1280)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.24244558247619917128857214117595378487244291900164e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -1536)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.35897805692044314674029465486888992071638929853610e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -1792)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.45745119510512195777968048015384189694395480185084e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -2048)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.54271778755494231572464179212263712867955955556373e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -2560)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.68514415447058604503373799640504720298538164608415e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -3072)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.80146552760710346457341432134646648154958472048223e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -3584)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.89978436824284434538360953970051552537044157804319e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -4096)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.98493298246627952401490656857159297529934857258768e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -5120)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.12719032649420608124001447392893816734788637468278e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -6144)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.24339602515596353391422898038238569270302761832424e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -7168)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.34163046670299704746360546090336718985578875063595e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -8192)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.42671464308364892089984144203590287404801291341155e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -10240)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.56887983067842563164669431493815471028291272019257e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -12288)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.68502258391108555173104319503169367212234002338911e0), tolerance); - BOOST_CHECK_CLOSE(quantile(dist, ldexp(static_cast(1), -14336)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.78321117119788305968192558554365316820805283962570e0), tolerance); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -1024)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.09971143249822249471944441552701750744803726485204e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -1280)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.24244558247619917128857214117595378487244291900164e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -1536)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.35897805692044314674029465486888992071638929853610e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -1792)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.45745119510512195777968048015384189694395480185084e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -2048)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.54271778755494231572464179212263712867955955556373e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -2560)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.68514415447058604503373799640504720298538164608415e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -3072)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.80146552760710346457341432134646648154958472048223e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -3584)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.89978436824284434538360953970051552537044157804319e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -4096)), BOOST_MATH_BIG_CONSTANT(RealType, N, -5.98493298246627952401490656857159297529934857258768e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -5120)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.12719032649420608124001447392893816734788637468278e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -6144)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.24339602515596353391422898038238569270302761832424e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -7168)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.34163046670299704746360546090336718985578875063595e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -8192)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.42671464308364892089984144203590287404801291341155e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -10240)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.56887983067842563164669431493815471028291272019257e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -12288)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.68502258391108555173104319503169367212234002338911e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(dist, ldexp(static_cast(1), -14336)), BOOST_MATH_BIG_CONSTANT(RealType, N, -6.78321117119788305968192558554365316820805283962570e0), (tolerance) / 100); } template @@ -649,45 +646,45 @@ void do_test_landau_quantile_upper() { landau_distribution dist(static_cast(0), static_cast(1)); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.75630143945078214396279308922575172688187402052064e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.46875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.34751649957416497391423738312790099231331963193670e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.08338732735341567163440035550389980881822036530441e-1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.40625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.09977916217503813825408682237719484284367467701518e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.31348919222343858173602105619413807214737739605647e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.34375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55537778016228176635489075791437025790508273018206e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.83358201486120130332744845371832465533289389791770e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.28125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15968268411007811908706240304578653239207877720217e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.55081568282045925871949387822806899205587760602861e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.21875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.03356573722052416577951184486453626014326770622663e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.65170109428623528831428068089551728119930570543517e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, static_cast(0.15625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.48307637103506875745328267812359172615004959210209e0), tolerance); - - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -3))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.68160868054034088524891526884683024288168516466432e0), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -4))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12983583770683756688253603663598582344177172936943e1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19714287107110229779819680655029619622254635434578e1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -6))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.28089946846201448479186405990829330152038273940336e1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -7))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.40066013407733304728124190173163568113870838023174e1), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -8))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65941656579816517264930679482280545790703168918131e2), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -10))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55753077855274500558851746639632584040672341383365e2), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.61233279175261252785344820794971528959731572291875e3), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.04359994051668217545134727183452999841836322543240e4), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.17280170760481128545941744972976378785527707571987e4), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.67552483213163052181906697701099131817014739251016e5), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.06807174647511043368265795578221114430723661526053e7), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.70891330693062153503879914631960898643362032945242e8), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.73426111586976542228936210986127280848086481329720e9), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.99970842207360156603062974124919047698394307869345e11), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.79192535600728707050158319385235151176991681631485e14), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.58732891137812933185516807516215074813520642490265e16), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.17435620131280049336696928005840807489266101470318e19), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.69626080092356929518666088104130567689669972090860e23), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.04382147849327037329330237397632338076523897478536e28), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.30551884414534967184149864106941373195910184715021e33), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.16630482969909636093804454941121895928783047320959e38), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -160))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.30420839672446839098151322191224148323438073311282e47), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -192))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.99612707791001852622513406287046677525461975485236e57), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -224))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.71632351102835736008910691332442626839731739200064e67), tolerance); - BOOST_CHECK_CLOSE(quantile(complement(dist, ldexp(static_cast(1), -256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.37155334922269019018360983857591746072979653277477e76), tolerance); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.75630143945078214396279308922575172688187402052064e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.46875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.34751649957416497391423738312790099231331963193670e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.4375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.08338732735341567163440035550389980881822036530441e-1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.40625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.09977916217503813825408682237719484284367467701518e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.31348919222343858173602105619413807214737739605647e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.34375))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.55537778016228176635489075791437025790508273018206e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.3125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.83358201486120130332744845371832465533289389791770e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.28125))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.15968268411007811908706240304578653239207877720217e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.55081568282045925871949387822806899205587760602861e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.21875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.03356573722052416577951184486453626014326770622663e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.1875))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.65170109428623528831428068089551728119930570543517e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, static_cast(0.15625))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.48307637103506875745328267812359172615004959210209e0), (tolerance) / 100); + + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -3))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.68160868054034088524891526884683024288168516466432e0), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -4))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.12983583770683756688253603663598582344177172936943e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -5))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.19714287107110229779819680655029619622254635434578e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -6))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.28089946846201448479186405990829330152038273940336e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -7))), BOOST_MATH_BIG_CONSTANT(RealType, N, 8.40066013407733304728124190173163568113870838023174e1), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -8))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.65941656579816517264930679482280545790703168918131e2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -10))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.55753077855274500558851746639632584040672341383365e2), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -12))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.61233279175261252785344820794971528959731572291875e3), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -14))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.04359994051668217545134727183452999841836322543240e4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -16))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.17280170760481128545941744972976378785527707571987e4), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -20))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.67552483213163052181906697701099131817014739251016e5), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -24))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.06807174647511043368265795578221114430723661526053e7), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -28))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.70891330693062153503879914631960898643362032945242e8), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -32))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.73426111586976542228936210986127280848086481329720e9), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -40))), BOOST_MATH_BIG_CONSTANT(RealType, N, 6.99970842207360156603062974124919047698394307869345e11), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -48))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.79192535600728707050158319385235151176991681631485e14), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -56))), BOOST_MATH_BIG_CONSTANT(RealType, N, 4.58732891137812933185516807516215074813520642490265e16), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -64))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.17435620131280049336696928005840807489266101470318e19), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -80))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.69626080092356929518666088104130567689669972090860e23), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -96))), BOOST_MATH_BIG_CONSTANT(RealType, N, 5.04382147849327037329330237397632338076523897478536e28), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -112))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.30551884414534967184149864106941373195910184715021e33), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -128))), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.16630482969909636093804454941121895928783047320959e38), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -160))), BOOST_MATH_BIG_CONSTANT(RealType, N, 9.30420839672446839098151322191224148323438073311282e47), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -192))), BOOST_MATH_BIG_CONSTANT(RealType, N, 3.99612707791001852622513406287046677525461975485236e57), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -224))), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.71632351102835736008910691332442626839731739200064e67), (tolerance) / 100); + CHECK_RELATIVE_ERROR(quantile(complement(dist, ldexp(static_cast(1), -256))), BOOST_MATH_BIG_CONSTANT(RealType, N, 7.37155334922269019018360983857591746072979653277477e76), (tolerance) / 100); } template @@ -706,173 +703,222 @@ void do_test_landau_locscale_param() { landau_distribution dist_1_3(static_cast(1), static_cast(3)); landau_distribution dist_0_pihalf(static_cast(0), boost::math::constants::pi() / 2); - BOOST_CHECK_CLOSE(entropy(dist_0_1), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.3726364400044818244844049010588577710), tolerance); - BOOST_CHECK_CLOSE(entropy(dist_1_3), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.3726364400044818244844049010588577710) + log(static_cast(3)), tolerance); - BOOST_CHECK_CLOSE(entropy(dist_0_pihalf), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.8242191452939366892106001309537399145), tolerance); + CHECK_RELATIVE_ERROR(entropy(dist_0_1), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.3726364400044818244844049010588577710), (tolerance) / 100); + CHECK_RELATIVE_ERROR(entropy(dist_1_3), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.3726364400044818244844049010588577710) + log(static_cast(3)), (tolerance) / 100); + CHECK_RELATIVE_ERROR(entropy(dist_0_pihalf), BOOST_MATH_BIG_CONSTANT(RealType, N, 2.8242191452939366892106001309537399145), (tolerance) / 100); - BOOST_CHECK_CLOSE(median(dist_0_1), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.57563014394507821439627930892257517269), tolerance); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR(median(dist_0_1), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.57563014394507821439627930892257517269), (tolerance) / 100); + CHECK_RELATIVE_ERROR( median(dist_1_3), - (1 + 3 * (BOOST_MATH_BIG_CONSTANT(RealType, N, 0.57563014394507821439627930892257517269) + 2 / boost::math::constants::pi() * log(static_cast(3)))), - tolerance - ); - BOOST_CHECK_CLOSE(median(dist_0_pihalf), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.3557804209908013250320928093906509105), tolerance); + (1 + 3 * (BOOST_MATH_BIG_CONSTANT(RealType, N, 0.57563014394507821439627930892257517269) + 2 / boost::math::constants::pi() * log(static_cast(3)))), (tolerance) / 100); + CHECK_RELATIVE_ERROR(median(dist_0_pihalf), BOOST_MATH_BIG_CONSTANT(RealType, N, 1.3557804209908013250320928093906509105), (tolerance) / 100); - BOOST_CHECK_CLOSE(mode(dist_0_1), BOOST_MATH_BIG_CONSTANT(RealType, N, -0.42931452986133525016556463510885028346), tolerance); - BOOST_CHECK_CLOSE( + CHECK_RELATIVE_ERROR(mode(dist_0_1), BOOST_MATH_BIG_CONSTANT(RealType, N, -0.42931452986133525016556463510885028346), (tolerance) / 100); + CHECK_RELATIVE_ERROR( mode(dist_1_3), - (1 + 3 * (BOOST_MATH_BIG_CONSTANT(RealType, N, -0.42931452986133525016556463510885028346) + 2 / boost::math::constants::pi() * log(static_cast(3)))), - tolerance - ); - BOOST_CHECK_CLOSE(mode(dist_0_pihalf), BOOST_MATH_BIG_CONSTANT(RealType, N, -0.222782981256408504061824283124805665631673572953417648794046), tolerance); - - BOOST_CHECK_CLOSE(pdf(dist_0_1, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.16353124086802260347581305180210465276342), tolerance); - BOOST_CHECK_CLOSE(pdf(dist_1_3, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.09034495984298569669047391552324642172044), tolerance); - BOOST_CHECK_CLOSE(pdf(dist_0_pihalf, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.14520663709640194253543670745173917702186), tolerance); - - BOOST_CHECK_CLOSE(cdf(dist_0_1, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.57786675964195234763672948547568695034661), tolerance); - BOOST_CHECK_CLOSE(cdf(dist_1_3, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.17119311431882309272302517476020685228892), tolerance); - BOOST_CHECK_CLOSE(cdf(dist_0_pihalf, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.45101809281952585982591839302215356640746), tolerance); - - BOOST_CHECK_CLOSE(cdf(dist_0_1, quantile(dist_0_1, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), tolerance); - BOOST_CHECK_CLOSE(cdf(dist_1_3, quantile(dist_1_3, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), tolerance); - BOOST_CHECK_CLOSE(cdf(dist_0_pihalf, quantile(dist_0_pihalf, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), tolerance); - - BOOST_CHECK_CLOSE(cdf(dist_0_1, quantile(dist_0_1, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), tolerance); - BOOST_CHECK_CLOSE(cdf(dist_1_3, quantile(dist_1_3, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), tolerance); - BOOST_CHECK_CLOSE(cdf(dist_0_pihalf, quantile(dist_0_pihalf, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), tolerance); + (1 + 3 * (BOOST_MATH_BIG_CONSTANT(RealType, N, -0.42931452986133525016556463510885028346) + 2 / boost::math::constants::pi() * log(static_cast(3)))), (tolerance) / 100); + CHECK_RELATIVE_ERROR(mode(dist_0_pihalf), BOOST_MATH_BIG_CONSTANT(RealType, N, -0.222782981256408504061824283124805665631673572953417648794046), (tolerance) / 100); + + CHECK_RELATIVE_ERROR(pdf(dist_0_1, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.16353124086802260347581305180210465276342), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist_1_3, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.09034495984298569669047391552324642172044), (tolerance) / 100); + CHECK_RELATIVE_ERROR(pdf(dist_0_pihalf, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.14520663709640194253543670745173917702186), (tolerance) / 100); + + CHECK_RELATIVE_ERROR(cdf(dist_0_1, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.57786675964195234763672948547568695034661), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist_1_3, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.17119311431882309272302517476020685228892), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist_0_pihalf, static_cast(1)), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.45101809281952585982591839302215356640746), (tolerance) / 100); + + CHECK_RELATIVE_ERROR(cdf(dist_0_1, quantile(dist_0_1, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist_1_3, quantile(dist_1_3, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist_0_pihalf, quantile(dist_0_pihalf, static_cast(0.25))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.25), (tolerance) / 100); + + CHECK_RELATIVE_ERROR(cdf(dist_0_1, quantile(dist_0_1, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist_1_3, quantile(dist_1_3, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), (tolerance) / 100); + CHECK_RELATIVE_ERROR(cdf(dist_0_pihalf, quantile(dist_0_pihalf, static_cast(0.75))), BOOST_MATH_BIG_CONSTANT(RealType, N, 0.75), (tolerance) / 100); } -BOOST_AUTO_TEST_CASE(landau_pdf_fp64) +void landau_pdf_fp64() { do_test_landau_pdf(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(landau_pdf_fp64_std) +void landau_pdf_fp64_std() { do_test_landau_pdf(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(landau_pdf_fp128) +void landau_pdf_fp128() { do_test_landau_pdf(); } #endif -BOOST_AUTO_TEST_CASE(landau_cdf_fp64) +void landau_cdf_fp64() { do_test_landau_cdf(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(landau_cdf_fp64_std) +void landau_cdf_fp64_std() { do_test_landau_cdf(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(landau_cdf_fp128) +void landau_cdf_fp128() { do_test_landau_cdf(); } #endif -BOOST_AUTO_TEST_CASE(landau_ccdf_fp64) +void landau_ccdf_fp64() { do_test_landau_ccdf(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(landau_ccdf_fp64_std) +void landau_ccdf_fp64_std() { do_test_landau_ccdf(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(landau_ccdf_fp128) +void landau_ccdf_fp128() { do_test_landau_ccdf(); } #endif -BOOST_AUTO_TEST_CASE(landau_quantile_nearzero_fp64) +void landau_quantile_nearzero_fp64() { do_test_landau_quantile_nearzero(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(landau_quantile_nearzero_fp64_std) +void landau_quantile_nearzero_fp64_std() { do_test_landau_quantile_nearzero(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(landau_quantile_nearzero_fp128) +void landau_quantile_nearzero_fp128() { do_test_landau_quantile_nearzero(); } #endif -BOOST_AUTO_TEST_CASE(landau_quantile_lower_fp64) +void landau_quantile_lower_fp64() { do_test_landau_quantile_lower(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(landau_quantile_lower_fp64_std) +void landau_quantile_lower_fp64_std() { do_test_landau_quantile_lower(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(landau_quantile_lower_fp128) +void landau_quantile_lower_fp128() { do_test_landau_quantile_lower(); } #endif -BOOST_AUTO_TEST_CASE(landau_quantile_upper_fp64) +void landau_quantile_upper_fp64() { do_test_landau_quantile_upper(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(landau_quantile_upper_fp64_std) +void landau_quantile_upper_fp64_std() { do_test_landau_quantile_upper(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(landau_quantile_upper_fp128) +void landau_quantile_upper_fp128() { do_test_landau_quantile_upper(); } #endif -BOOST_AUTO_TEST_CASE(landau_locscale_fp64) +void landau_locscale_fp64() { do_test_landau_locscale_param(); } #ifdef __STDCPP_FLOAT64_T__ -BOOST_AUTO_TEST_CASE(landau_locscale_fp64_std) +void landau_locscale_fp64_std() { do_test_landau_locscale_param(); } #endif #ifndef BOOST_MATH_HAS_GPU_SUPPORT -BOOST_AUTO_TEST_CASE(landau_locscale_fp128) +void landau_locscale_fp128() { do_test_landau_locscale_param(); } #endif +int main() +{ + landau_pdf_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + landau_pdf_fp64_std(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + landau_pdf_fp128(); +#endif + landau_cdf_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + landau_cdf_fp64_std(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + landau_cdf_fp128(); +#endif + landau_ccdf_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + landau_ccdf_fp64_std(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + landau_ccdf_fp128(); +#endif + landau_quantile_nearzero_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + landau_quantile_nearzero_fp64_std(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + landau_quantile_nearzero_fp128(); +#endif + landau_quantile_lower_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + landau_quantile_lower_fp64_std(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + landau_quantile_lower_fp128(); +#endif + landau_quantile_upper_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + landau_quantile_upper_fp64_std(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + landau_quantile_upper_fp128(); +#endif + landau_locscale_fp64(); +#ifdef __STDCPP_FLOAT64_T__ + landau_locscale_fp64_std(); +#endif +#ifndef BOOST_MATH_HAS_GPU_SUPPORT + landau_locscale_fp128(); +#endif + return boost::math::test::report_errors(); +} diff --git a/test/test_laplace.cpp b/test/test_laplace.cpp index 954b94dc97..089aef6caf 100644 --- a/test/test_laplace.cpp +++ b/test/test_laplace.cpp @@ -491,6 +491,31 @@ void test_location_scale_symmetry() } } +template +void test_logpdf_location_scale_symmetry() +{ + RealType tolerance(boost::math::tools::epsilon() * 500); // 5 eps as a percentage + + const float xtest[7] = { -2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0 }; + const float ltest[7] = { -2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0 }; + const float stest[3] = { 0.5, 1.0, 2.0 }; + + for (int xi=0; xi<7; ++xi) + for (int li=0; li<7; ++li) + for (int si=0; si<3; ++si) + { + RealType x( static_cast(xtest[xi]) ); + RealType l( static_cast(ltest[li]) ); + RealType s( static_cast(stest[si]) ); + RealType x0( (x-l)/s ); + + BOOST_CHECK_CLOSE( + logpdf(laplace_distribution(l,s), x) + log(s), + logpdf(laplace_distribution(), x0), + tolerance); + } +} + template void test_mmm_moments() { @@ -686,6 +711,12 @@ BOOST_AUTO_TEST_CASE( location_scale_symmetry ) test_location_scale_symmetry(); } +BOOST_AUTO_TEST_CASE( logpdf_location_scale_symmetry ) +{ + test_logpdf_location_scale_symmetry(); + test_logpdf_location_scale_symmetry(); +} + BOOST_AUTO_TEST_CASE( mmm_moments ) { test_mmm_moments(); diff --git a/test/test_lbeta.cpp b/test/test_lbeta.cpp new file mode 100644 index 0000000000..55a06f3f36 --- /dev/null +++ b/test/test_lbeta.cpp @@ -0,0 +1,147 @@ +// Copyright Nick Thompson, 2026 +// 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) + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include + +using boost::math::lbeta; +using boost::multiprecision::cpp_bin_float_100; + +// a = am * 2^ae and b = bm * 2^be are exact in every type whose exponent range holds them. +// The values of log(beta(a, b)) were computed as lgamma(a) + lgamma(b) - lgamma(a + b) with +// 800-digit cpp_bin_float, enough to absorb the cancellation when an argument is 2^1000. +struct lbeta_case +{ + double am; + int ae; + double bm; + int be; + const char* value; +}; + +const lbeta_case cases[] = { + { 1, -60, 1, -50, "4.15898069195697740239298881123986100039915095416801455108115264409117033485238337627682905027475554197949082691e+01" }, + { 1, -100, 3, 0, "6.93147180559945309417232121458164735161921819183174078192200771589333072536381647225831806423195466923922439014e+01" }, + { 0.5, 0, 0.5, 0, "1.14472988584940017414342735135305871164729481291531157151362307147213776988482607978362327027548970770200981223e+00" }, + { 0.25, 0, 0.75, 0, "1.49130347612937282885204341208214699568504488009543919857396307621883458086967343758655493377369905147301055274e+00" }, + { 1.5, 0, 2.5, 0, "-1.62785883639038106352550113447964756065470572452570944496909696650143671799395278263983003771018504246599611185e+00" }, + { 2, 0, 0.75, 0, "-2.71933715483641758831669494532999161982574749963589623711364445601499668091899372237820945415928865613025799190e-01" }, + { 2.5, 0, 2.5, 0, "-2.60868808940210730038195226193165156023371556978372575559644266134412329068442796258380426388570901630403052585e+00" }, + { 2.5, 0, 7.25, 0, "-4.90533661883930395460834936695643873217655041103926652565285221548103484033393583597181887094577679099681463945e+00" }, + { 7.25, 0, 10, 0, "-1.15206093828576774238792925676023403474351969826024007014606103008266556359021233866230652434846476474713883000e+01" }, + { 33, 0, 70, 0, "-6.52309611058463901652530664244886314226939493764776246951104105272718684570163848327941904447963477233497622302e+01" }, + { 1000, 0, 2.5, 0, "-1.69865790781530187420413395240576683950617459492281475607293952992950240177344530711756692292901949091581441171e+01" }, + { 1, 20, 2.5, 0, "-3.43726779456625527055870837198099350327971371888199561621811864168868157894165670678814799899328577816876559438e+01" }, + { 1, 40, 0.125, 0, "-1.44631754524588046377436687345621730310702661961084719229448263705785310178427063985532264153346167268065642354e+00" }, + { 1, 60, 3, 0, "-1.24073345320230210388286634954978816325251619811257890584231209580161422603673162680077814295275683492847917281e+02" }, + { 7.25, 100, 1, -3, "-6.89254658305384294843871197074079636920399542538686737751765487854131887259626569180127928805023089821623285643e+00" }, + { 1, 20, 1, 20, "-1.45364066196521333105311408462318440517413066016099383479834829660518401041863896220590715872159106794242688144e+06" }, + { 1, 60, 1.5, 60, "-1.93982405936568553724082316071548785790406066925570806020585049192655840461166500901608060631298307929683783052e+18" }, + { 1, 100, 1, 90, "-9.81929078485523071471385110686110593997035850585013134716105089872660111623496248017922967392287894559854586350e+27" }, + { 2.5, 200, 2.5, 0, "-3.48579634239185123211942384088825609792055182534338388500569779067988144304556260885743443173501924555859593246e+02" }, + { 1, -1000, 1, 1000, "6.93147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687542001481021e+02" }, + { 1, 1000, 1, 1000, "-1.48542634003375029367139526623878447128207418381951509618626907063551595543031141778517375655554942542595596811e+301" }, + { 1, -1000, 1, -1000, "6.93840327740505254726649353579634744643575634494615509374800689502887015591664410321469190323415106229543482502e+02" }, + { 1.5, 500, 7.25, 3, "-1.99483893641016901555392148959348216596399017908133451106724466122953422408704368366657864286454193673764307194e+04" }, + { 1, 996, 1, -53, "3.67368005696770246880527428609492912902170429819419624345920988651297592807040422075224154620060976686905127353e+01" } +}; + +template +Real from_reference(const cpp_bin_float_100& x) +{ + return static_cast(x); +} + +#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS +template <> +boost::math::concepts::real_concept from_reference(const cpp_bin_float_100& x) +{ + return boost::math::concepts::real_concept(static_cast(x)); +} +#endif + +// Where |log(beta)| < 1, it passes through zero and relative error is meaningless, so check the absolute error. +template +void test_spots(std::size_t ulps, Real absolute_tolerance) +{ + using std::abs; + using std::ldexp; + const int max_exponent = boost::math::itrunc(boost::math::tools::log_max_value() / boost::math::constants::ln_two()) - 2; + for (const lbeta_case& c : cases) + { + if ((abs(c.ae) > max_exponent) || (abs(c.be) > max_exponent)) + continue; + Real a = ldexp(Real(c.am), c.ae); + Real b = ldexp(Real(c.bm), c.be); + Real expected = from_reference(cpp_bin_float_100(c.value)); + Real computed = lbeta(a, b); + if (abs(expected) >= 1) + CHECK_ULP_CLOSE(expected, computed, ulps); + else + CHECK_LE(Real(abs(expected - computed)), absolute_tolerance); + CHECK_EQUAL(computed, Real(lbeta(b, a))); + } + // With one argument equal to 1, log(beta) is -log of the other. Compare with a high-precision + // reference rather than Real's own log, which real_concept evaluates only in double precision: + CHECK_ULP_CLOSE(from_reference(cpp_bin_float_100(-log(cpp_bin_float_100(3)))), Real(lbeta(Real(1), Real(3))), 1); + CHECK_ULP_CLOSE(from_reference(cpp_bin_float_100(-log(cpp_bin_float_100(0.25)))), Real(lbeta(Real(0.25), Real(1))), 1); +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(lbeta(Real(0), Real(1)), std::domain_error); + CHECK_THROW(lbeta(Real(1), Real(-2)), std::domain_error); +#endif + // NaN arguments are domain errors; ignoring the error gives NaN: + if (std::numeric_limits::has_quiet_NaN) + { + using ignore_domain = boost::math::policies::policy>; + const Real nan = std::numeric_limits::quiet_NaN(); + CHECK_TRUE((boost::math::isnan)(Real(lbeta(nan, Real(2), ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(lbeta(Real(2), nan, ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(lbeta(nan, Real(0.5), ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(lbeta(Real(0.5), nan, ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(lbeta(nan, Real(50), ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(lbeta(nan, nan, ignore_domain())))); +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(lbeta(nan, Real(2)), std::domain_error); + CHECK_THROW(lbeta(Real(2), nan), std::domain_error); +#endif + } + // log(beta) is exactly -infinity when either argument is infinite. That's an overflow, as for every + // exact infinity; ignoring it gives -infinity: + if (std::numeric_limits::has_infinity) + { + using ignore_overflow = boost::math::policies::policy>; + const Real infinity = std::numeric_limits::infinity(); + CHECK_EQUAL(Real(lbeta(infinity, Real(2.5), ignore_overflow())), Real(-infinity)); + CHECK_EQUAL(Real(lbeta(Real(1e-30), infinity, ignore_overflow())), Real(-infinity)); + CHECK_EQUAL(Real(lbeta(infinity, infinity, ignore_overflow())), Real(-infinity)); +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(lbeta(infinity, Real(2.5)), std::overflow_error); +#endif + } +} + +int main() +{ + test_spots(2, 2 * std::numeric_limits::epsilon()); + test_spots(4, 2 * std::numeric_limits::epsilon()); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_spots(8, 4 * std::numeric_limits::epsilon()); +#endif +#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS + test_spots(8, boost::math::concepts::real_concept(16 * std::numeric_limits::epsilon())); +#endif + using boost::multiprecision::cpp_bin_float_50; + test_spots(8, 8 * std::numeric_limits::epsilon()); + // No Lanczos approximation at this precision, so this exercises the generic code path, whose + // errors come from beta, lgamma and tgamma_delta_ratio at this precision: + test_spots(64, 64 * std::numeric_limits::epsilon()); + return boost::math::test::report_errors(); +} diff --git a/test/test_lbeta_double.cu b/test/test_lbeta_double.cu new file mode 100644 index 0000000000..c6f84fb717 --- /dev/null +++ b/test/test_lbeta_double.cu @@ -0,0 +1,139 @@ +// Copyright John Maddock 2016. +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef double float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type * in2, float_type *out, int numElements) +{ + using std::cos; + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::lbeta(in1[i], in2[i]); + } +} + +template struct table_type { typedef T type; }; +typedef float_type T; +#define SC_(x) static_cast(x) + +#include "beta_med_data.ipp" +#include "beta_small_data.ipp" + +/** + * Host main routine + */ +int main(void) +{ + try{ + // Consolidate the test data: + std::vector v1, v2; + + for(unsigned i = 0; i < beta_med_data.size(); ++i) + { + v1.push_back(beta_med_data[i][0]); + v2.push_back(beta_med_data[i][1]); + } + for(unsigned i = 0; i < beta_small_data.size(); ++i) + { + v1.push_back(beta_small_data[i][0]); + v2.push_back(beta_small_data[i][1]); + } + + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vector A + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + + // Allocate the managed output vector C + cuda_managed_ptr output_vector(numElements); + + // Initialize the input vectors + for (int i = 0; i < numElements; ++i) + { + int table_id = i % v1.size(); + input_vector1[i] = v1[table_id]; + input_vector2[i] = v2[table_id]; + } + + // Launch the Vector Add CUDA Kernel + int threadsPerBlock = 1024; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + cuda_test<<>>(input_vector1.get(), input_vector2.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + std::cout << "CUDA kernal done in " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::lbeta(input_vector1[i], input_vector2[i])); + double t = w.elapsed(); + // check the results + for(int i = 0; i < numElements; ++i) + { + // log(beta) passes through zero, where relative error is meaningless, so compare absolutely there: + float_type error = std::fabs(results[i]) < 1 + ? std::fabs(output_vector[i] - results[i]) / std::numeric_limits::epsilon() + : boost::math::epsilon_difference(output_vector[i], results[i]); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + return EXIT_FAILURE; + } + } + + std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + } + catch(const std::exception& e) + { + std::cerr << "Stopped with exception: " << e.what() << std::endl; + } + return 0; +} + + diff --git a/test/test_lbeta_float.cu b/test/test_lbeta_float.cu new file mode 100644 index 0000000000..6fc05fa05c --- /dev/null +++ b/test/test_lbeta_float.cu @@ -0,0 +1,137 @@ +// Copyright John Maddock 2016. +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef float float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type * in2, float_type *out, int numElements) +{ + using std::cos; + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::lbeta(in1[i], in2[i]); + } +} + +template struct table_type { typedef T type; }; +typedef float_type T; +#define SC_(x) static_cast(x) + +#include "beta_med_data.ipp" +#include "beta_small_data.ipp" + +/** + * Host main routine + */ +int main(void) +{ + try{ + // Consolidate the test data: + std::vector v1, v2; + + for(unsigned i = 0; i < beta_med_data.size(); ++i) + { + v1.push_back(beta_med_data[i][0]); + v2.push_back(beta_med_data[i][1]); + } + for(unsigned i = 0; i < beta_small_data.size(); ++i) + { + v1.push_back(beta_small_data[i][0]); + v2.push_back(beta_small_data[i][1]); + } + + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vector A + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + + // Allocate the managed output vector C + cuda_managed_ptr output_vector(numElements); + + // Initialize the input vectors + for (int i = 0; i < numElements; ++i) + { + int table_id = i % v1.size(); + input_vector1[i] = v1[table_id]; + input_vector2[i] = v2[table_id]; + } + + // Launch the Vector Add CUDA Kernel + int threadsPerBlock = 1024; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + cuda_test<<>>(input_vector1.get(), input_vector2.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + std::cout << "CUDA kernal done in " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::lbeta(input_vector1[i], input_vector2[i])); + double t = w.elapsed(); + // check the results + for(int i = 0; i < numElements; ++i) + { + // log(beta) passes through zero, where relative error is meaningless, so compare absolutely there: + float_type error = std::fabs(results[i]) < 1 + ? std::fabs(output_vector[i] - results[i]) / std::numeric_limits::epsilon() + : boost::math::epsilon_difference(output_vector[i], results[i]); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + return EXIT_FAILURE; + } + } + + std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + } + catch(const std::exception& e) + { + std::cerr << "Stopped with exception: " << e.what() << std::endl; + } + return 0; +} + diff --git a/test/test_lbfgs.cpp b/test/test_lbfgs.cpp index f89940ddcc..8f00dc66c5 100644 --- a/test/test_lbfgs.cpp +++ b/test/test_lbfgs.cpp @@ -12,9 +12,8 @@ namespace rdiff = boost::math::differentiation::reverse_mode; namespace bopt = boost::math::optimization; -BOOST_AUTO_TEST_SUITE(basic_lbfgs) -BOOST_AUTO_TEST_CASE(default_lbfgs_test) //, T, all_float_types) +void default_lbfgs_test() //, T, all_float_types) { using T = double; constexpr size_t NITER = 10; @@ -32,7 +31,7 @@ BOOST_AUTO_TEST_CASE(default_lbfgs_test) //, T, all_float_types) auto result = bopt::minimize(opt, constraint, convergence_policy); for (auto& xi : x) { - BOOST_REQUIRE_CLOSE(xi, T{1.0}, eps); + if (!CHECK_RELATIVE_ERROR(xi, T{1.0}, (eps) / 100)) { return; } } } @@ -74,7 +73,8 @@ struct analytic_gradient_eval_pol } }; -BOOST_AUTO_TEST_CASE_TEMPLATE(custom_init_lbfgs_test, T, all_float_types) +template +void custom_init_lbfgs_test() { constexpr size_t M = 8; const T eps = T{1e-6}; @@ -93,11 +93,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(custom_init_lbfgs_test, T, all_float_types) auto result = minimize(opt, constraint, convergence_policy); for (auto& xi : x) { - BOOST_REQUIRE_CLOSE(xi, T{1.0}, eps); + if (!CHECK_RELATIVE_ERROR(xi, T{1.0}, (eps) / 100)) { return; } } } -BOOST_AUTO_TEST_CASE_TEMPLATE(analytic_lbfgs_test, T, all_float_types) +template +void analytic_lbfgs_test() { constexpr size_t M = 10; const T eps = T{1e-3}; @@ -118,7 +119,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(analytic_lbfgs_test, T, all_float_types) auto result = minimize(opt); for (auto& xi : x) { - BOOST_REQUIRE_SMALL(xi, eps); + if (!CHECK_ABSOLUTE_ERROR(0,xi, eps)) { return; } } } -BOOST_AUTO_TEST_SUITE_END() + +int main() +{ + default_lbfgs_test(); + boost::mp11::mp_for_each>([](auto t) { custom_init_lbfgs_test(); }); + boost::mp11::mp_for_each>([](auto t) { analytic_lbfgs_test(); }); + return boost::math::test::report_errors(); +} diff --git a/test/test_lbfgs_module.cpp b/test/test_lbfgs_module.cpp new file mode 100644 index 0000000000..7079fb9a4a --- /dev/null +++ b/test/test_lbfgs_module.cpp @@ -0,0 +1,158 @@ +// Copyright Maksym Zhelyenzyakov 2025-2026. +// Copyright Matt Borland 2026. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) +// +// Module build check for boost::math::optimization L-BFGS. It exercises the +// exported make_lbfgs / minimize entry points when built against the boost.math +// module. The reverse-mode-autodiff paths of test_lbfgs.cpp are not usable here +// (autodiff_reverse is not part of the module export surface), so this test +// drives the fully analytic path: minimizing the isotropic quadratic +// f(x) = sum x_i^2 whose minimizer is the origin with value 0. + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#endif +#include "math_unit_test.hpp" + +namespace bopt = boost::math::optimization; + +// Objective: isotropic quadratic, minimum 0 at the origin. +template +Real quadratic(std::vector& x) +{ + Real res{ 0 }; + for (auto& item : x) + { + res += item * item; + } + return res; +} + +// No-op initializer: keep the caller-supplied starting point. +template +struct identity_init_policy +{ + void operator()(std::vector&) const noexcept {} +}; + +// Objective evaluation policy: just call the objective. +template +struct analytic_objective_eval_policy +{ + template + Real operator()(Objective&& objective, ArgumentContainer& x) + { + return objective(x); + } +}; + +// Gradient evaluation policy: analytic gradient of sum x_i^2 is 2*x. +template +struct analytic_gradient_eval_policy +{ + template + void operator()(Objective&& obj_f, + ArgumentContainer& x, + FunctionEvaluationPolicy&& f_eval_pol, + Real& obj_v, + std::vector& grad_container) + { + obj_v = f_eval_pol(obj_f, x); + grad_container.resize(x.size()); + for (std::size_t i{ 0 }; i < x.size(); ++i) + { + grad_container[i] = 2 * x[i]; + } + } +}; + +// Self-contained backtracking Armijo line search. The library's own +// armijo_line_search_policy and its dot/axpy helpers are not exported by the +// module, so the search is reimplemented here with plain loops. +template +struct armijo_line_search_policy +{ + template + Real operator()(Objective& objective, + ObjectiveEvalPolicy& obj_eval, + GradientEvalPolicy& /*grad_eval*/, + ArgumentContainer& x, + const std::vector& g, + const std::vector& p, + Real f_x) const + { + const Real c{ static_cast(1e-4) }; + const Real rho{ static_cast(0.5) }; + + Real gTp{ 0 }; + for (std::size_t i{ 0 }; i < g.size(); ++i) + { + gTp += g[i] * p[i]; + } + + Real alpha{ 1 }; + for (int iter{ 0 }; iter < 20; ++iter) + { + ArgumentContainer x_trial{ x }; + for (std::size_t i{ 0 }; i < x_trial.size(); ++i) + { + x_trial[i] += alpha * p[i]; + } + const Real f_trial{ obj_eval(objective, x_trial) }; + if (f_trial <= f_x + c * alpha * gTp) + { + return alpha; + } + alpha *= rho; + } + return alpha; + } +}; + +template +void test_quadratic_minimization() +{ + constexpr std::size_t M{ 10 }; + const Real tol{ static_cast(1e-3) }; + + // Non-trivial, distinct starting coordinates. + std::vector x{ static_cast(2), static_cast(-1.5), static_cast(3) }; + + auto opt = bopt::make_lbfgs(&quadratic, // Objective + x, // Arguments + M, // History size + identity_init_policy{}, // Initialization + analytic_objective_eval_policy{}, // Function eval + analytic_gradient_eval_policy{}, // Gradient eval + armijo_line_search_policy{}); // Line search + + auto result = bopt::minimize(opt); + + // The minimizer of sum x_i^2 is the origin; each coordinate converges to 0. + for (auto& xi : x) + { + CHECK_ABSOLUTE_ERROR(static_cast(0), xi, tol); + } + + // Objective value at the minimum is 0, and the run reports convergence. + CHECK_ABSOLUTE_ERROR(static_cast(0), result.objective_value, tol); + CHECK_EQUAL(true, result.converged); +} + +int main() +{ + test_quadratic_minimization(); + test_quadratic_minimization(); + + return boost::math::test::report_errors(); +} diff --git a/test/test_legendre.cpp b/test/test_legendre.cpp index bc32892577..8dfc5db67d 100644 --- a/test/test_legendre.cpp +++ b/test/test_legendre.cpp @@ -38,7 +38,7 @@ void expected_results() // const char* largest_type; #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - if(boost::math::policies::digits >() == boost::math::policies::digits >()) + if(!boost::math::policies::promote_double<>() || boost::math::policies::digits >() == boost::math::policies::digits >()) { largest_type = "(long\\s+)?double"; } @@ -52,7 +52,7 @@ void expected_results() // // Linux: // - BOOST_MATH_IF_CONSTEXPR((std::numeric_limits::digits <= 64) + BOOST_MATH_IF_CONSTEXPR(boost::math::policies::promote_double<>() && (std::numeric_limits::digits <= 64) && (std::numeric_limits::digits != std::numeric_limits::digits)) { #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS diff --git a/test/test_legendre.hpp b/test/test_legendre.hpp index 885dae91e8..252d6e9b9d 100644 --- a/test/test_legendre.hpp +++ b/test/test_legendre.hpp @@ -284,7 +284,9 @@ void test_legendre_p_prime() BOOST_CHECK_CLOSE_FRACTION(::boost::math::legendre_p_prime(n, (T) -1), -expected, tolerance); BOOST_CHECK_CLOSE_FRACTION(::boost::math::legendre_p_prime(-n - 1, (T) -1), -expected, tolerance); } - ++n; + // Each evaluation is O(n), so test every n at first and then a sparse set up to 5000 + // (odd stride, so both parities are still covered): + n += (n < 200) ? 1 : 101; } // // Coverage: diff --git a/test/test_legendre_stieltjes.cpp b/test/test_legendre_stieltjes.cpp new file mode 100644 index 0000000000..20e570246a --- /dev/null +++ b/test/test_legendre_stieltjes.cpp @@ -0,0 +1,150 @@ +// Copyright Nick Thompson 2017. +// 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) + +#include +#include +#include +#include +#include "math_unit_test.hpp" +#include +#include +#include +#include + + +using boost::math::legendre_stieltjes; +using boost::math::legendre_p; +using boost::multiprecision::cpp_bin_float_quad; + + +template +void test_legendre_stieltjes() +{ + std::cout << std::setprecision(std::numeric_limits::digits10); + using std::sqrt; + using std::abs; + using boost::math::constants::third; + using boost::math::constants::half; + + Real tol = std::numeric_limits::epsilon(); + legendre_stieltjes ls1(1); + legendre_stieltjes ls2(2); + legendre_stieltjes ls3(3); + legendre_stieltjes ls4(4); + legendre_stieltjes ls5(5); + legendre_stieltjes ls8(8); + Real x = -1; + while(x <= 1) + { + CHECK_ULP_CLOSE(x, ls1(x), 2); + CHECK_ULP_CLOSE(1, ls1.prime(x), 2); + + Real p2 = legendre_p(2, x); + CHECK_ULP_CLOSE(p2 - 2/static_cast(5), ls2(x), 2); + CHECK_ULP_CLOSE(3*x, ls2.prime(x), 2); + + Real p3 = legendre_p(3, x); + CHECK_ULP_CLOSE(p3 - 9*x/static_cast(14), ls3(x), 256); + CHECK_ULP_CLOSE(15*x*x*half() -3*half()-9/static_cast(14), ls3.prime(x), 4); + + Real p4 = legendre_p(4, x); + //-20P_2(x)/27 + 14P_0(x)/891 + Real E4 = p4 - 20*p2/static_cast(27) + 14/static_cast(891); + CHECK_ULP_CLOSE(E4, ls4(x), 500); + CHECK_ULP_CLOSE(35*x*(9*x*x -5)/static_cast(18), ls4.prime(x), 400); + + Real p5 = legendre_p(5, x); + Real E5 = p5 - 35*p3/static_cast(44) + 135*x/static_cast(12584); + CHECK_ULP_CLOSE(E5, ls5(x), 58000); + Real E5prime = (315*(123 + 143*x*x*(11*x*x-9)))/static_cast(12584); + CHECK_ULP_CLOSE(E5prime, ls5.prime(x), 316); + x += 1/static_cast(1 << 9); + } + + // Test norm: + // E_1 = x + Real expected_norm_sq = 2*third(); + CHECK_ULP_CLOSE(expected_norm_sq, ls1.norm_sq(), 2); + + // E_2 = P[sub 2](x) - 2P[sup 0](x)/5 + expected_norm_sq = 2/static_cast(5) + 8/static_cast(25); + CHECK_ULP_CLOSE(expected_norm_sq, ls2.norm_sq(), 2); + + // E_3 = P[sub 3](x) - 9P[sub 1]/14 + expected_norm_sq = 2/static_cast(7) + 9*9*2*third()/static_cast(14*14); + CHECK_ULP_CLOSE(expected_norm_sq, ls3.norm_sq(), 2); + + // E_4 = P[sub 4](x) -20P[sub 2](x)/27 + 14P[sub 0](x)/891 + expected_norm_sq = static_cast(2)/static_cast(9) + static_cast(20*20*2)/static_cast(27*27*5) + 14*14*2/static_cast(891*891); + CHECK_ULP_CLOSE(expected_norm_sq, ls4.norm_sq(), 2); + + // E_5 = P[sub 5](x) - 35P[sub 3](x)/44 + 135P[sub 1](x)/12584 + expected_norm_sq = 2/static_cast(11) + (35*35/static_cast(44*44))*(2/static_cast(7)) + (135*135/static_cast(12584*12584))*2*third(); + CHECK_ULP_CLOSE(expected_norm_sq, ls5.norm_sq(), 2); + + // Only zero of E1 is 0: + std::vector zeros = ls1.zeros(); + CHECK_EQUAL(zeros.size(), static_cast(1)); + CHECK_ABSOLUTE_ERROR(0, zeros[0], tol); + CHECK_ABSOLUTE_ERROR(0, ls1(zeros[0]), tol); + + zeros = ls2.zeros(); + CHECK_EQUAL(zeros.size(), static_cast(1)); + CHECK_ULP_CLOSE(sqrt(3/static_cast(5)), zeros[0], 2); + CHECK_ABSOLUTE_ERROR(0, ls2(zeros[0]), tol); + + zeros = ls3.zeros(); + CHECK_EQUAL(zeros.size(), static_cast(2)); + CHECK_ABSOLUTE_ERROR(0, zeros[0], tol); + CHECK_ULP_CLOSE(sqrt(6/static_cast(7)), zeros[1], 2); + + + zeros = ls4.zeros(); + CHECK_EQUAL(zeros.size(), static_cast(2)); + Real expected = sqrt( (55 - 2*sqrt(static_cast(330)))/static_cast(11) )/static_cast(3); + CHECK_ULP_CLOSE(expected, zeros[0], 2); + + expected = sqrt( (55 + 2*sqrt(static_cast(330)))/static_cast(11) )/static_cast(3); + CHECK_ULP_CLOSE(expected, zeros[1], 4); + + + zeros = ls5.zeros(); + CHECK_EQUAL(zeros.size(), static_cast(3)); + CHECK_ABSOLUTE_ERROR(0, zeros[0], tol); + + expected = sqrt( ( 195 - sqrt(static_cast(6045)) )/static_cast(286)); + CHECK_ULP_CLOSE(expected, zeros[1], 2); + + expected = sqrt( ( 195 + sqrt(static_cast(6045)) )/static_cast(286)); + CHECK_ULP_CLOSE(expected, zeros[2], 2); + + + for (size_t i = 6; i < 50; ++i) + { + legendre_stieltjes En(i); + zeros = En.zeros(); + for(auto const & zero : zeros) + { + CHECK_ABSOLUTE_ERROR(0, En(zero), 50*tol); + } + } + +#ifndef BOOST_MATH_NO_EXCEPTIONS + CHECK_THROW(legendre_stieltjes(0), std::domain_error); +#endif +} + + +int main() +{ + test_legendre_stieltjes(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_legendre_stieltjes(); +#endif + test_legendre_stieltjes(); + //test_legendre_stieltjes(); + return boost::math::test::report_errors(); +} diff --git a/test/test_libeta.cpp b/test/test_libeta.cpp new file mode 100644 index 0000000000..c5d6397e63 --- /dev/null +++ b/test/test_libeta.cpp @@ -0,0 +1,188 @@ +// Copyright Nick Thompson, 2026 +// 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) + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include + +using boost::math::libeta; +using boost::math::libetac; +using boost::multiprecision::cpp_bin_float_100; + +// log(ibeta(a, b, x)) and log(ibetac(a, b, x)) from Arb's arb_hypgeom_beta_lower, with the precision +// doubled until each logarithm's ball had relative radius below 1e-115. The inputs are dyadic, so exact +// in every type. Several targets underflow double: there log(ibeta) is -infinity, but libeta is not. +struct libeta_case +{ + double a; + double b; + double x; + const char* log_p; + const char* log_q; +}; + +const libeta_case cases[] = { + { 2.5, 7.25, 0.3125, "-3.7167156277665188049290840111055425693593488651567342000012502851004994412078034526975515049850137362945980883e-01", "-1.1698312803088233349651352879295389693292834586979826954540514935872825554887239020131638530480843027129424824e+00" }, + { 2.5, 7.25, 0.875, "-4.4345947122224081046530969749310990093659919691233663114625273621430941801405299283156934670374411191393943876e-06", "-1.2326076547615867168151504108295024750650355692244371499856114021272344401647386276346484452551499377402488966e+01" }, + { 0.5, 0.5, 0.5, "-6.9314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102e-01", "-6.9314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102e-01" }, + { 1.0, 1.0, 0.1875, "-1.6739764335716715462736832489101805676545099796182715647480257043360801946601698955498375531719426613800358950e+00", "-2.0763936477824450161544104426738766749673259268081390006367452731010982055436868302387864454518526139874773199e-01" }, + { 0.5, 0.5, 9.094947017729282e-13, "-1.4314526316488209470620542120468834675861013543469559344594411813858688169108548092137802186276440566259295234e+01", "-6.0712811052568164727952258383323139837273179818800005468192845698497291569843003152216679057253352649397217909e-07" }, + { 9.5367431640625e-7, 3.0, 0.5, "-6.4990279784362527021851305783498086889378815860578000369818737418560387836805289126143048273527262421196071331e-08", "-1.6549028152507438492978740557867797551584908242395123816839275331964007995320601266648979794701183754577299207e+01" }, + { 3.0, 9.5367431640625e-7, 0.5, "-1.6549028152507438492978740557867797551584908242395123816839275331964007995320601266648979794701183754577299207e+01", "-6.4990279784362527021851305783498086889378815860578000369818737418560387836805289126143048273527262421196071331e-08" }, + { 0.0009765625, 0.0009765625, 0.125, "-6.9504617998484206497446276820368611445317909319707817733433332393193935558041868358136995705973397981340663124e-01", "-6.9125178049975242775597449072452416228716139105677147030161509217245257586337866435580760659714648626361431213e-01" }, + { 50.0, 2.5, 0.0625, "-1.3310392296311938936477859354681779646430842972669870304195913133829620589539560964307738984041510250414505628e+02", "-1.5620708837902603944950917943401674846306871183800437733485803592936921101711474787720997003896385889333011021e-58" }, + { 1000.0, 1000.0, 0.375, "-6.7879098782070203571535741057973743782955536957303318080122891535681449203670406857800476852551450175275314762e+01", "-3.3149880133573969922824995974224965637056758043476670891119727642919243631695704636348416155978166270733913420e-30" }, + { 1000.0, 1000.0, 0.625, "-3.3149880133573969922824995974224965637056758043476670891119727642919243631695704636348416155978166270733913420e-30", "-6.7879098782070203571535741057973743782955536957303318080122891535681449203670406857800476852551450175275314762e+01" }, + { 10000.0, 10000.0, 0.25, "-2.8819984220755331098839194770117315448486264030839286705152670660549762353701257939070968841957833171644866865e+03", "-1.3633688684767639881765687928093097744250603074917173616473757806904196132829559298164511082526880657885781775e-613" }, + { 10000.0, 10000.0, 0.75, "-1.3633688684767639881765687928093097744250603074917173616473757806904196132829559298164511082526880657885781775e-613", "-2.8819984220755331098839194770117315448486264030839286705152670660549762353701257939070968841957833171644866865e+03" }, + { 10000.0, 0.5, 0.875, "-1.3394521027626777099748952446997573462746702885509053896612331431976821464436216161037222597806676708845142582e+03", "-1.9201846626087125029027612859359907113707395383457549239532866991395985295359825524988696116301598187398883665e-582" }, + { 1.048576e6, 1024.0, 0.5, "-7.1941557634186688357844532955373761625884349655139799481873092808405534876172700544822832792998463119052012317e+05", "-3.1661843852186122127237313070884491832685258910359624873249688080229877326939015766751471565635099226598406911e-611" }, + { 100.0, 1.048576e6, 0.0009765625, "-1.4486608968995453830084851361306300995014059641294937436625787355612796662632052991551882269877592472658236946e-303", "-6.9731264356684974023614850681051528231841414568944325979176586916712546741354321795568654597356458739661894994e+02" }, + { 37.5, 40.25, 0.5, "-4.7307555088411157725979633902922107691136049613019416337906660727145158645379390792662893477597617498250318147e-01", "-9.7573026146792365826661180434525064594695070782057324369556972488301090797505588648171444949724195815954006735e-01" }, + { 4.0, 3.0, 0.0078125, "-1.6712608432463251991856384283020918341020810329590680592279080948835199946873096273593449850993901626536894712e+01", "-5.5183137805310855384254552540924836333280609811359952446688756907101759825770857836273702787048662110831118110e-08" } +}; + +template +Real from_reference(const cpp_bin_float_100& x) +{ + return static_cast(x); +} + +#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS +template <> +boost::math::concepts::real_concept from_reference(const cpp_bin_float_100& x) +{ + return boost::math::concepts::real_concept(static_cast(x)); +} +#endif + +// Where |log| < 1 it passes through zero, so relative error is meaningless: check the absolute error. +template +void check(const Real& expected, const Real& computed, std::size_t ulps, const Real& absolute_tolerance) +{ + using std::abs; + if (abs(expected) >= 1) + CHECK_ULP_CLOSE(expected, computed, ulps); + else + CHECK_LE(Real(abs(expected - computed)), absolute_tolerance); +} + +template +void test_spots(std::size_t ulps, Real absolute_tolerance) +{ + for (const libeta_case& c : cases) + { + Real a(c.a), b(c.b), x(c.x); + check(from_reference(cpp_bin_float_100(c.log_p)), Real(libeta(a, b, x)), ulps, absolute_tolerance); + check(from_reference(cpp_bin_float_100(c.log_q)), Real(libetac(a, b, x)), ulps, absolute_tolerance); + } + + // The boundaries, which follow ibeta: a == 0 gives P = 1 and b == 0 gives P = 0 whatever x is. + CHECK_EQUAL(Real(libeta(Real(2), Real(3), Real(1))), Real(0)); + CHECK_EQUAL(Real(libetac(Real(2), Real(3), Real(0))), Real(0)); + CHECK_EQUAL(Real(libeta(Real(0), Real(3), Real(0))), Real(0)); + CHECK_EQUAL(Real(libetac(Real(3), Real(0), Real(1))), Real(0)); + // The log of an exact zero is an overflow, as for every exact infinity; ignoring it gives -infinity: + if (std::numeric_limits::has_infinity) + { + using ignore_overflow = boost::math::policies::policy>; + const Real minus_infinity = -std::numeric_limits::infinity(); + CHECK_EQUAL(Real(libeta(Real(2), Real(3), Real(0), ignore_overflow())), minus_infinity); + CHECK_EQUAL(Real(libetac(Real(2), Real(3), Real(1), ignore_overflow())), minus_infinity); + CHECK_EQUAL(Real(libeta(Real(2), Real(0), Real(0.5), ignore_overflow())), minus_infinity); + CHECK_EQUAL(Real(libetac(Real(0), Real(2), Real(0.5), ignore_overflow())), minus_infinity); + } +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(libeta(Real(2), Real(3), Real(0)), std::overflow_error); + CHECK_THROW(libetac(Real(2), Real(3), Real(1)), std::overflow_error); +#endif + // NaN arguments are domain errors; ignoring the error gives NaN: + if (std::numeric_limits::has_quiet_NaN) + { + using ignore_domain = boost::math::policies::policy>; + const Real nan = std::numeric_limits::quiet_NaN(); + CHECK_TRUE((boost::math::isnan)(Real(libeta(nan, Real(2), Real(0.5), ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(libeta(Real(2), nan, Real(0.5), ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(libeta(Real(2), Real(3), nan, ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(libetac(nan, Real(2), Real(0.5), ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(libetac(Real(2), nan, Real(0.5), ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(libetac(Real(2), Real(3), nan, ignore_domain())))); +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(libeta(nan, Real(2), Real(0.5)), std::domain_error); + CHECK_THROW(libetac(Real(2), Real(3), nan), std::domain_error); +#endif + } +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(libeta(Real(2), Real(3), Real(-0.5)), std::domain_error); + CHECK_THROW(libeta(Real(2), Real(3), Real(1.5)), std::domain_error); + CHECK_THROW(libetac(Real(-2), Real(3), Real(0.5)), std::domain_error); + CHECK_THROW(libetac(Real(0), Real(0), Real(0.5)), std::domain_error); +#endif +} + +// With a = 1, the continued fraction for an underflowing target starts with 0/0, so libeta must use +// P = 1 - (1 - x)^b instead. In double these targets are subnormal; to full precision, +// log(P) = log(b) + log(x) when b x is far below epsilon. +void test_a_equal_to_one_underflow() +{ + using std::log; + const double ln_two = boost::math::constants::ln_two(); + // P = 1 - (1 - 2^-1070)^(2^17), so log(P) = (17 - 1070) log(2): + CHECK_ULP_CLOSE(-1053 * ln_two, libeta(1.0, std::ldexp(1.0, 17), std::ldexp(1.0, -1070)), 1); + // Q = 1 - (1/2)^(2^-1040) after swapping a and b, so log(Q) = -1040 log(2) + log(log(2)): + CHECK_ULP_CLOSE(-1040 * ln_two + log(ln_two), libetac(std::ldexp(1.0, -1040), 1.0, 0.5), 1); +} + +// There is no Lanczos approximation at 100 digits, so libeta takes its generic code path. With the exponent range +// narrowed to about double's, the table's targets below exp(-800) underflow, so only the generic log-space power +// terms produce them. (Elsewhere ibeta itself currently loses digits at this precision, which libeta would inherit.) +void test_generic_underflow() +{ + using narrow_100 = boost::multiprecision::number>; + static_assert(std::is_same>::type, boost::math::lanczos::undefined_lanczos>::value, + "This test needs a type without a Lanczos approximation."); + int checked = 0; + for (const libeta_case& c : cases) + { + narrow_100 a(c.a), b(c.b), x(c.x); + narrow_100 log_p = from_reference(cpp_bin_float_100(c.log_p)); + narrow_100 log_q = from_reference(cpp_bin_float_100(c.log_q)); + if (log_p < -800) + { + CHECK_ULP_CLOSE(log_p, narrow_100(libeta(a, b, x)), 8); + ++checked; + } + if (log_q < -800) + { + CHECK_ULP_CLOSE(log_q, narrow_100(libetac(a, b, x)), 8); + ++checked; + } + } + CHECK_LE(4, checked); +} + +int main() +{ + test_a_equal_to_one_underflow(); + // Near the mean, libeta is log(ibeta), so it inherits ibeta's error: 18.5 epsilon at (37.5, 40.25, 0.5) in double. + test_spots(2, 2 * std::numeric_limits::epsilon()); + test_spots(8, 32 * std::numeric_limits::epsilon()); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_spots(16, 64 * std::numeric_limits::epsilon()); +#endif +#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS + test_spots(16, boost::math::concepts::real_concept(64 * std::numeric_limits::epsilon())); +#endif + using boost::multiprecision::cpp_bin_float_50; + // At 50 digits the Lanczos g is about 30, and ibeta near the mean scatters by up to about 60 epsilon: + test_spots(16, 64 * std::numeric_limits::epsilon()); + test_generic_underflow(); + return boost::math::test::report_errors(); +} diff --git a/test/test_libeta_double.cu b/test/test_libeta_double.cu new file mode 100644 index 0000000000..d6c892e6f4 --- /dev/null +++ b/test/test_libeta_double.cu @@ -0,0 +1,156 @@ +// Copyright John Maddock 2016. +// Copyright Matt Borland 2024. +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +// floating-point value does not fit in required floating-point type +#pragma nv_diag_suppress 221 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef double float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type *in2, const float_type *in3, float_type *out, int numElements) +{ + using std::cos; + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::libeta(in1[i], in2[i], in3[i]); + } +} + +template struct table_type { typedef T type; }; +typedef float_type T; +#define SC_(x) static_cast(x) + +#include "ibeta_data.ipp" +#include "ibeta_small_data.ipp" + +/** + * Host main routine + */ +int main(void) +{ + try{ + // Consolidate the test data: + std::vector v1, v2, v3; + + for(unsigned i = 0; i < ibeta_data.size(); ++i) + { + v1.push_back(ibeta_data[i][0]); + v2.push_back(ibeta_data[i][1]); + v3.push_back(ibeta_data[i][2]); + } + for(unsigned i = 0; i < ibeta_small_data.size(); ++i) + { + v1.push_back(ibeta_small_data[i][0]); + v2.push_back(ibeta_small_data[i][1]); + v3.push_back(ibeta_small_data[i][2]); + } + + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vector A + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + cuda_managed_ptr input_vector3(numElements); + + // Allocate the managed output vector C + cuda_managed_ptr output_vector(numElements); + + // Initialize the input vectors + for (int i = 0; i < numElements; ++i) + { + int table_id = i % v1.size(); + input_vector1[i] = v1[table_id]; + input_vector2[i] = v2[table_id]; + input_vector3[i] = v3[table_id]; + } + + // Launch the Vector Add CUDA Kernel + int threadsPerBlock = 256; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + cuda_test<<>>(input_vector1.get(), input_vector2.get(), input_vector3.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + std::cout << "CUDA kernal done in " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::libeta(input_vector1[i], input_vector2[i], input_vector3[i])); + double t = w.elapsed(); + bool failed = false; + // check the results + for(int i = 0; i < numElements; ++i) + { + if (boost::math::isfinite(output_vector[i])) + { + // The logarithm passes through zero, where relative error is meaningless, so compare absolutely there: + float_type error = std::fabs(results[i]) < 1 + ? std::fabs(output_vector[i] - results[i]) / std::numeric_limits::epsilon() + : boost::math::epsilon_difference(output_vector[i], results[i]); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + failed = true; + } + } + } + + if (failed) + { + return EXIT_FAILURE; + } + + std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + } + catch(const std::exception& e) + { + std::cerr << "Stopped with exception: " << e.what() << std::endl; + } + return 0; +} + + diff --git a/test/test_libeta_float.cu b/test/test_libeta_float.cu new file mode 100644 index 0000000000..2eae8e3819 --- /dev/null +++ b/test/test_libeta_float.cu @@ -0,0 +1,156 @@ +// Copyright John Maddock 2016. +// Copyright Matt Borland 2024. +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +// floating-point value does not fit in required floating-point type +#pragma nv_diag_suppress 221 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef float float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type *in2, const float_type *in3, float_type *out, int numElements) +{ + using std::cos; + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::libeta(in1[i], in2[i], in3[i]); + } +} + +template struct table_type { typedef T type; }; +typedef float_type T; +#define SC_(x) static_cast(x) + +#include "ibeta_data.ipp" +#include "ibeta_small_data.ipp" + +/** + * Host main routine + */ +int main(void) +{ + try{ + // Consolidate the test data: + std::vector v1, v2, v3; + + for(unsigned i = 0; i < ibeta_data.size(); ++i) + { + v1.push_back(ibeta_data[i][0]); + v2.push_back(ibeta_data[i][1]); + v3.push_back(ibeta_data[i][2]); + } + for(unsigned i = 0; i < ibeta_small_data.size(); ++i) + { + v1.push_back(ibeta_small_data[i][0]); + v2.push_back(ibeta_small_data[i][1]); + v3.push_back(ibeta_small_data[i][2]); + } + + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vector A + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + cuda_managed_ptr input_vector3(numElements); + + // Allocate the managed output vector C + cuda_managed_ptr output_vector(numElements); + + // Initialize the input vectors + for (int i = 0; i < numElements; ++i) + { + int table_id = i % v1.size(); + input_vector1[i] = v1[table_id]; + input_vector2[i] = v2[table_id]; + input_vector3[i] = v3[table_id]; + } + + // Launch the Vector Add CUDA Kernel + int threadsPerBlock = 256; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + cuda_test<<>>(input_vector1.get(), input_vector2.get(), input_vector3.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + std::cout << "CUDA kernal done in " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::libeta(input_vector1[i], input_vector2[i], input_vector3[i])); + double t = w.elapsed(); + bool failed = false; + // check the results + for(int i = 0; i < numElements; ++i) + { + if (boost::math::isfinite(output_vector[i])) + { + // The logarithm passes through zero, where relative error is meaningless, so compare absolutely there: + float_type error = std::fabs(results[i]) < 1 + ? std::fabs(output_vector[i] - results[i]) / std::numeric_limits::epsilon() + : boost::math::epsilon_difference(output_vector[i], results[i]); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + failed = true; + } + } + } + + if (failed) + { + return EXIT_FAILURE; + } + + std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + } + catch(const std::exception& e) + { + std::cerr << "Stopped with exception: " << e.what() << std::endl; + } + return 0; +} + + diff --git a/test/test_libetac_double.cu b/test/test_libetac_double.cu new file mode 100644 index 0000000000..0cd9826c04 --- /dev/null +++ b/test/test_libetac_double.cu @@ -0,0 +1,156 @@ +// Copyright John Maddock 2016. +// Copyright Matt Borland 2024. +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +// floating-point value does not fit in required floating-point type +#pragma nv_diag_suppress 221 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef double float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type *in2, const float_type *in3, float_type *out, int numElements) +{ + using std::cos; + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::libetac(in1[i], in2[i], in3[i]); + } +} + +template struct table_type { typedef T type; }; +typedef float_type T; +#define SC_(x) static_cast(x) + +#include "ibeta_data.ipp" +#include "ibeta_small_data.ipp" + +/** + * Host main routine + */ +int main(void) +{ + try{ + // Consolidate the test data: + std::vector v1, v2, v3; + + for(unsigned i = 0; i < ibeta_data.size(); ++i) + { + v1.push_back(ibeta_data[i][0]); + v2.push_back(ibeta_data[i][1]); + v3.push_back(ibeta_data[i][2]); + } + for(unsigned i = 0; i < ibeta_small_data.size(); ++i) + { + v1.push_back(ibeta_small_data[i][0]); + v2.push_back(ibeta_small_data[i][1]); + v3.push_back(ibeta_small_data[i][2]); + } + + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vector A + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + cuda_managed_ptr input_vector3(numElements); + + // Allocate the managed output vector C + cuda_managed_ptr output_vector(numElements); + + // Initialize the input vectors + for (int i = 0; i < numElements; ++i) + { + int table_id = i % v1.size(); + input_vector1[i] = v1[table_id]; + input_vector2[i] = v2[table_id]; + input_vector3[i] = v3[table_id]; + } + + // Launch the Vector Add CUDA Kernel + int threadsPerBlock = 256; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + cuda_test<<>>(input_vector1.get(), input_vector2.get(), input_vector3.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + std::cout << "CUDA kernal done in " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::libetac(input_vector1[i], input_vector2[i], input_vector3[i])); + double t = w.elapsed(); + bool failed = false; + // check the results + for(int i = 0; i < numElements; ++i) + { + if (boost::math::isfinite(output_vector[i])) + { + // The logarithm passes through zero, where relative error is meaningless, so compare absolutely there: + float_type error = std::fabs(results[i]) < 1 + ? std::fabs(output_vector[i] - results[i]) / std::numeric_limits::epsilon() + : boost::math::epsilon_difference(output_vector[i], results[i]); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + failed = true; + } + } + } + + if (failed) + { + return EXIT_FAILURE; + } + + std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + } + catch(const std::exception& e) + { + std::cerr << "Stopped with exception: " << e.what() << std::endl; + } + return 0; +} + + diff --git a/test/test_libetac_float.cu b/test/test_libetac_float.cu new file mode 100644 index 0000000000..19dec1f688 --- /dev/null +++ b/test/test_libetac_float.cu @@ -0,0 +1,156 @@ +// Copyright John Maddock 2016. +// Copyright Matt Borland 2024. +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +// floating-point value does not fit in required floating-point type +#pragma nv_diag_suppress 221 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef float float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type *in2, const float_type *in3, float_type *out, int numElements) +{ + using std::cos; + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::libetac(in1[i], in2[i], in3[i]); + } +} + +template struct table_type { typedef T type; }; +typedef float_type T; +#define SC_(x) static_cast(x) + +#include "ibeta_data.ipp" +#include "ibeta_small_data.ipp" + +/** + * Host main routine + */ +int main(void) +{ + try{ + // Consolidate the test data: + std::vector v1, v2, v3; + + for(unsigned i = 0; i < ibeta_data.size(); ++i) + { + v1.push_back(ibeta_data[i][0]); + v2.push_back(ibeta_data[i][1]); + v3.push_back(ibeta_data[i][2]); + } + for(unsigned i = 0; i < ibeta_small_data.size(); ++i) + { + v1.push_back(ibeta_small_data[i][0]); + v2.push_back(ibeta_small_data[i][1]); + v3.push_back(ibeta_small_data[i][2]); + } + + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vector A + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + cuda_managed_ptr input_vector3(numElements); + + // Allocate the managed output vector C + cuda_managed_ptr output_vector(numElements); + + // Initialize the input vectors + for (int i = 0; i < numElements; ++i) + { + int table_id = i % v1.size(); + input_vector1[i] = v1[table_id]; + input_vector2[i] = v2[table_id]; + input_vector3[i] = v3[table_id]; + } + + // Launch the Vector Add CUDA Kernel + int threadsPerBlock = 256; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + cuda_test<<>>(input_vector1.get(), input_vector2.get(), input_vector3.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + std::cout << "CUDA kernal done in " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::libetac(input_vector1[i], input_vector2[i], input_vector3[i])); + double t = w.elapsed(); + bool failed = false; + // check the results + for(int i = 0; i < numElements; ++i) + { + if (boost::math::isfinite(output_vector[i])) + { + // The logarithm passes through zero, where relative error is meaningless, so compare absolutely there: + float_type error = std::fabs(results[i]) < 1 + ? std::fabs(output_vector[i] - results[i]) / std::numeric_limits::epsilon() + : boost::math::epsilon_difference(output_vector[i], results[i]); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + failed = true; + } + } + } + + if (failed) + { + return EXIT_FAILURE; + } + + std::cout << "Test PASSED with calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + } + catch(const std::exception& e) + { + std::cerr << "Stopped with exception: " << e.what() << std::endl; + } + return 0; +} + + diff --git a/test/test_ligamma.cpp b/test/test_ligamma.cpp new file mode 100644 index 0000000000..b3dfe530dd --- /dev/null +++ b/test/test_ligamma.cpp @@ -0,0 +1,184 @@ +// Copyright Nick Thompson, 2026 +// 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) + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include + +using boost::math::ligamma; +using boost::math::ligamma_lower; +using boost::multiprecision::cpp_bin_float_100; + +// log(tgamma(a, x)) and log(tgamma_lower(a, x)), computed with Arb: arb_hypgeom_gamma_upper for x >= a, and for x < a +// the series for the lower function, each with the other as gamma(a) minus the first. The precision was doubled until +// each logarithm's ball had relative radius below 1e-115. The inputs are dyadic, so exact in every type. Several values +// overflow or underflow double, where log(tgamma(a, x)) is infinite but ligamma is not. +struct ligamma_case +{ + double a; + double x; + const char* log_upper; + const char* log_lower; +}; + +const ligamma_case cases[] = { + { 2.5, 1.0, "1.2115759487826881505275305651186870694041754810602241686386550907439660274410122689632242508378186319701322744e-01", "-1.6067535371453137835485637734565884075661272599144183153328939345813381648202869722143154438944755967497311409e+00" }, + { 2.5, 30.0, "-2.4848633033033568585775606150217063231776860531174716723611152050121158069210433588962288107825722546981486249e+01", "2.8468287046076458985523776395111859010124529460512663635052087420960128616776934174356639565068600583951170758e-01" }, + { 0.5, 0.5, "-5.7550952152461810928183727609782309764852436800536248513008065098880573654672044680219886267372404171768343111e-01", "1.9064979662257401479753066816587055020203900191383989139279624179991169101923287236368302011386826091354535869e-01" }, + { 9.5367431640625e-7, 0.25, "4.3329681976764116812962168205761668110531802122293663061271899236280959010116297976855105750784261579707721890e-02", "1.3862942064817819371597083203484523981378986248191528178643086339948011084679626489495691758190580840604079834e+01" }, + { 9.5367431640625e-7, 9.313225746154785e-10, "3.0065235630469892943086953167194409014444406877094897610620142931242359707297922698528910680764788181213409437e+00", "1.3862923780098997617405608217022900716380592969540924868089321252596890761811200226264389634053398086943925588e+01" }, + { 1.0, 0.125, "-1.2500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-01", "-2.1412905847632012003460915474560573950973053346029827451505631309617872378509999247775869790609354267681006076e+00" }, + { 100.0, 7.62939453125e-6, "3.5913420536957539877604401046028690961262171808562972877561279307484079922862431495362900583179335272293183799e+02", "-1.1829553846917510861148888194102544355366943034135567498326091371553742251900583033628108371168959536911942860e+03" }, + { 0.5, 800.0, "-8.0334292989026914277011788712147523027625048445796001213977030571616076706566234902264761738165995628239877020e+02", "5.7236494292470008707171367567652935582364740645765578575681153573606888494241303989181163513774485385100490611e-01" }, + { 37.5, 37.5, "9.6784219013624273538564367039851830199348647345043818460498983911692030778614396820970016069787243324610329474e+01", "9.6871148482431460918087441810862444588322980641847852624659906118444232717140238995838074935912952693191695927e+01" }, + { 150.0, 160.0, "5.9842166600398933896473633740479780587741555270045023808144087418030819202526400004141534851719087907025996299e+02", "5.9978084473911611070673933986747762225349459031614663814392284583053929946405261709380560441291096424584533341e+02" }, + { 1000.0, 1000.0, "5.9045188299725352393303969775776785919325346037738600473424508213569779194944742662149261807627638282089426729e+03", "5.9045356513458909016799290303089150623692120881673413020117569273880583353428974787238677453871076071638650619e+03" }, + { 1000.0, 500.0, "5.9052204232091812118260769123614407898489424097154325900233875198883841333644788925921620543460926574075386671e+03", "5.7083915041483186807926091879564531470086287259517343889685970127418854617508689583124643132768875701028822116e+03" }, + { 1000.0, 4000.0, "4.2860428284350736577552641746493656020777712625262765706663139050781686399320799273897846364221909714378263326e+03", "5.9052204232091812118260769123614407898489424097154325900233875198883841333644788925921620873288206280785351523e+03" }, + { 1.0e6, 1.5e6, "1.2720962543703061159755127230382120390711888790333146381432032604790510263473733787158079665363156769867669015e+07", "1.2815504569147611659976971785017113153687975196214851361632706092068992333829159968797138805737861576248904294e+07" }, + { 1.0e6, 500000.0, "1.2815504569147611659976971785017113153687975196214851361632706092068992333829159968797138805737861576248904294e+07", "1.2622350255038951404361743252556656958733649336038873758330500797737834380859841254882259339362580687585976636e+07" }, + { 1.048576e6, 1.0496e6, "1.3487766106501424078633459785724088776137287211137638456602466106862593851691460461761679317593366554025664762e+07", "1.3487767774769577991040370044266971477801670978480955073684733273999936390880788611365025536637318183046721133e+07" }, + { 3.0, 9.332636185032189e-302, "6.9314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102e-01", "-2.0805401539685040379430916096114522299311478936385885118137747228138183602023027557844635967440697947147924131e+03" }, + { 4.0, 712.0, "-6.9229154983203152364214453894071131752969051036854104094512292173514623019574780148370046658687497631154999836e+02", "1.7917594692280550008124773583807022727229906921830047058553743431308879151883036824794790818101507763299715101e+00" } +}; + +// Where tgamma(a, x) is near 1, log(tgamma(a, x)) magnified tgamma's relative error, by up to 13 ulps at these +// points in double (https://github.com/boostorg/math/issues/1514). The logarithms are between 0.1 and 0.9 in +// magnitude, well away from zero, so their relative error is checked. Computed in cpp_bin_float_100, which agrees +// with cpp_bin_float<80> to 1e-78: +struct near_one_case +{ + double a; + double x; + const char* log_upper; +}; + +const near_one_case near_one_cases[] = { + { 1.390625, 0.001953125, "-1.1913041184082416179216001200942763032633867183697e-01" }, + { 1.25, 0.0078125, "-1.0031506095522183340374220415887316547470731629977e-01" }, + { 0.1875, 0.09375, "4.3359308784299207346300520698158223193093290652088e-01" }, + { 0.75, 0.5, "-5.4736210896550123271278938139978866325343747684934e-01" } +}; + +template +Real from_reference(const cpp_bin_float_100& x) +{ + return static_cast(x); +} + +#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS +template <> +boost::math::concepts::real_concept from_reference(const cpp_bin_float_100& x) +{ + return boost::math::concepts::real_concept(static_cast(x)); +} +#endif + +// Where |log| < 1 it passes through zero, so relative error is meaningless: check the absolute error. +template +void check(const Real& expected, const Real& computed, std::size_t ulps, const Real& absolute_tolerance) +{ + using std::abs; + if (abs(expected) >= 1) + CHECK_ULP_CLOSE(expected, computed, ulps); + else + CHECK_LE(Real(abs(expected - computed)), absolute_tolerance); +} + +template +void test_spots(std::size_t ulps, Real absolute_tolerance) +{ + using std::ldexp; + const int max_exponent = boost::math::itrunc(boost::math::tools::log_max_value() / boost::math::constants::ln_two()) - 2; + const int min_exponent = boost::math::itrunc(boost::math::tools::log_min_value() / boost::math::constants::ln_two()) + 2; + for (const ligamma_case& c : cases) + { + int ea, ex; + std::frexp(c.a, &ea); + std::frexp(c.x, &ex); + if ((ea > max_exponent) || (ex > max_exponent) || (ex < min_exponent)) + continue; + Real a(c.a), x(c.x); + check(from_reference(cpp_bin_float_100(c.log_upper)), Real(ligamma(a, x)), ulps, absolute_tolerance); + check(from_reference(cpp_bin_float_100(c.log_lower)), Real(ligamma_lower(a, x)), ulps, absolute_tolerance); + } + // In real_concept and cpp_bin_float_50, tgamma1pm1 and lgamma are themselves off by tens to hundreds of + // epsilon at these points, so only the built-in types are held to this: + if (std::is_floating_point::value) + { + // Where double is not evaluated in a wider type (MSVC, or promote_double), the 1/a in + // tgamma_small_upper_part magnifies the rounding of its terms: 6 ulps at a = 0.1875 there (cond < 1). + const bool wider = (std::numeric_limits::digits < std::numeric_limits::digits) + && (!std::is_same::value || boost::math::policies::promote_double<>()); + const std::size_t near_one_ulps = wider ? ulps : 2 * ulps; + for (const near_one_case& c : near_one_cases) + { + CHECK_ULP_CLOSE(from_reference(cpp_bin_float_100(c.log_upper)), Real(ligamma(Real(c.a), Real(c.x))), near_one_ulps); + } + } + + // At the ends of the range the functions are lgamma(a) or exactly -infinity. The latter is an overflow, + // as for every exact infinity, and so are lgamma_p and lgamma_q there; ignoring it gives -infinity: + CHECK_EQUAL(Real(ligamma(Real(2.5), Real(0))), Real(boost::math::lgamma(Real(2.5)))); +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(ligamma_lower(Real(2.5), Real(0)), std::overflow_error); + CHECK_THROW(boost::math::lgamma_p(Real(2.5), Real(0)), std::overflow_error); +#endif + if (std::numeric_limits::has_infinity) + { + using ignore_overflow = boost::math::policies::policy>; + const Real infinity = std::numeric_limits::infinity(); + CHECK_EQUAL(Real(ligamma_lower(Real(2.5), infinity)), Real(boost::math::lgamma(Real(2.5)))); + CHECK_EQUAL(Real(ligamma(Real(2.5), infinity, ignore_overflow())), Real(-infinity)); + CHECK_EQUAL(Real(ligamma_lower(Real(2.5), Real(0), ignore_overflow())), Real(-infinity)); + CHECK_EQUAL(Real(boost::math::lgamma_p(Real(2.5), Real(0), ignore_overflow())), Real(-infinity)); + CHECK_EQUAL(Real(boost::math::lgamma_q(Real(2.5), infinity, ignore_overflow())), Real(-infinity)); +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(ligamma(Real(2.5), infinity), std::overflow_error); + CHECK_THROW(boost::math::lgamma_q(Real(2.5), infinity), std::overflow_error); +#endif + } + // NaN arguments are domain errors; ignoring the error gives NaN: + if (std::numeric_limits::has_quiet_NaN) + { + using ignore_domain = boost::math::policies::policy>; + const Real nan = std::numeric_limits::quiet_NaN(); + CHECK_TRUE((boost::math::isnan)(Real(ligamma(nan, Real(2), ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(ligamma(Real(2), nan, ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(ligamma_lower(nan, Real(2), ignore_domain())))); + CHECK_TRUE((boost::math::isnan)(Real(ligamma_lower(Real(2), nan, ignore_domain())))); +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(ligamma(nan, Real(2)), std::domain_error); + CHECK_THROW(ligamma_lower(Real(2), nan), std::domain_error); +#endif + } +#ifndef BOOST_NO_EXCEPTIONS + CHECK_THROW(ligamma(Real(0), Real(1)), std::domain_error); + CHECK_THROW(ligamma(Real(-1), Real(1)), std::domain_error); + CHECK_THROW(ligamma_lower(Real(2), Real(-1)), std::domain_error); +#endif +} + +int main() +{ + test_spots(2, 2 * std::numeric_limits::epsilon()); + test_spots(4, 8 * std::numeric_limits::epsilon()); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_spots(8, 16 * std::numeric_limits::epsilon()); +#endif +#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS + test_spots(8, boost::math::concepts::real_concept(16 * std::numeric_limits::epsilon())); +#endif + // At 50 digits ligamma inherits tgamma's errors of up to about 20 epsilon where it is log(tgamma): + using boost::multiprecision::cpp_bin_float_50; + test_spots(16, 64 * std::numeric_limits::epsilon()); + return boost::math::test::report_errors(); +} diff --git a/test/test_ligamma_double.cu b/test/test_ligamma_double.cu new file mode 100644 index 0000000000..5dff5ab11e --- /dev/null +++ b/test/test_ligamma_double.cu @@ -0,0 +1,118 @@ +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef double float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type *in2, float_type *out, int numElements) +{ + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::ligamma(in1[i], in2[i]); + } +} + +/** + * Host main routine + */ +int main(void) +{ + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vectors + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + + // Allocate the managed output vector + cuda_managed_ptr output_vector(numElements); + + // a log-uniform in [1e-2, 1e3], and x / a log-uniform in [10^-1.5, 10^1.5]: this reaches every method, + // including the tails where the non-normalised function under- or overflows. + std::mt19937_64 gen(42); + std::uniform_real_distribution log_a(-2, 3); + std::uniform_real_distribution log_ratio(-1.5, 1.5); + for (int i = 0; i < numElements; ++i) + { + double a = std::pow(10.0, log_a(gen)); + input_vector1[i] = static_cast(a); + input_vector2[i] = static_cast(a * std::pow(10.0, log_ratio(gen))); + } + + // Launch the CUDA Kernel + int threadsPerBlock = 1024; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + + cuda_test<<>>(input_vector1.get(), input_vector2.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + + std::cout << "CUDA kernal done in: " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::ligamma(input_vector1[i], input_vector2[i])); + double t = w.elapsed(); + // check the results + for(int i = 0; i < numElements; ++i) + { + // The logarithm is a difference of terms as large as a log(x) and x, so it carries an absolute error of + // a few eps times their size, on the host and the device alike: measure the difference against that size. + float_type a = input_vector1[i]; + float_type x = input_vector2[i]; + float_type scale = std::fmax(std::fmax(float_type(1), std::fabs(results[i])), std::fmax(x, std::fabs(a * std::log(x)))); + float_type error = std::fabs(output_vector[i] - results[i]) / (std::numeric_limits::epsilon() * scale); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + return EXIT_FAILURE; + } + } + + std::cout << "Test PASSED, normal calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + + return 0; +} diff --git a/test/test_ligamma_float.cu b/test/test_ligamma_float.cu new file mode 100644 index 0000000000..fe91a0c769 --- /dev/null +++ b/test/test_ligamma_float.cu @@ -0,0 +1,118 @@ +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef float float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type *in2, float_type *out, int numElements) +{ + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::ligamma(in1[i], in2[i]); + } +} + +/** + * Host main routine + */ +int main(void) +{ + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vectors + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + + // Allocate the managed output vector + cuda_managed_ptr output_vector(numElements); + + // a log-uniform in [1e-2, 1e3], and x / a log-uniform in [10^-1.5, 10^1.5]: this reaches every method, + // including the tails where the non-normalised function under- or overflows. + std::mt19937_64 gen(42); + std::uniform_real_distribution log_a(-2, 3); + std::uniform_real_distribution log_ratio(-1.5, 1.5); + for (int i = 0; i < numElements; ++i) + { + double a = std::pow(10.0, log_a(gen)); + input_vector1[i] = static_cast(a); + input_vector2[i] = static_cast(a * std::pow(10.0, log_ratio(gen))); + } + + // Launch the CUDA Kernel + int threadsPerBlock = 1024; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + + cuda_test<<>>(input_vector1.get(), input_vector2.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + + std::cout << "CUDA kernal done in: " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::ligamma(input_vector1[i], input_vector2[i])); + double t = w.elapsed(); + // check the results + for(int i = 0; i < numElements; ++i) + { + // The logarithm is a difference of terms as large as a log(x) and x, so it carries an absolute error of + // a few eps times their size, on the host and the device alike: measure the difference against that size. + float_type a = input_vector1[i]; + float_type x = input_vector2[i]; + float_type scale = std::fmax(std::fmax(float_type(1), std::fabs(results[i])), std::fmax(x, std::fabs(a * std::log(x)))); + float_type error = std::fabs(output_vector[i] - results[i]) / (std::numeric_limits::epsilon() * scale); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + return EXIT_FAILURE; + } + } + + std::cout << "Test PASSED, normal calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + + return 0; +} diff --git a/test/test_ligamma_lower_double.cu b/test/test_ligamma_lower_double.cu new file mode 100644 index 0000000000..44cf34b7ba --- /dev/null +++ b/test/test_ligamma_lower_double.cu @@ -0,0 +1,118 @@ +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef double float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type *in2, float_type *out, int numElements) +{ + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::ligamma_lower(in1[i], in2[i]); + } +} + +/** + * Host main routine + */ +int main(void) +{ + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vectors + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + + // Allocate the managed output vector + cuda_managed_ptr output_vector(numElements); + + // a log-uniform in [1e-2, 1e3], and x / a log-uniform in [10^-1.5, 10^1.5]: this reaches every method, + // including the tails where the non-normalised function under- or overflows. + std::mt19937_64 gen(42); + std::uniform_real_distribution log_a(-2, 3); + std::uniform_real_distribution log_ratio(-1.5, 1.5); + for (int i = 0; i < numElements; ++i) + { + double a = std::pow(10.0, log_a(gen)); + input_vector1[i] = static_cast(a); + input_vector2[i] = static_cast(a * std::pow(10.0, log_ratio(gen))); + } + + // Launch the CUDA Kernel + int threadsPerBlock = 1024; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + + cuda_test<<>>(input_vector1.get(), input_vector2.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + + std::cout << "CUDA kernal done in: " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::ligamma_lower(input_vector1[i], input_vector2[i])); + double t = w.elapsed(); + // check the results + for(int i = 0; i < numElements; ++i) + { + // The logarithm is a difference of terms as large as a log(x) and x, so it carries an absolute error of + // a few eps times their size, on the host and the device alike: measure the difference against that size. + float_type a = input_vector1[i]; + float_type x = input_vector2[i]; + float_type scale = std::fmax(std::fmax(float_type(1), std::fabs(results[i])), std::fmax(x, std::fabs(a * std::log(x)))); + float_type error = std::fabs(output_vector[i] - results[i]) / (std::numeric_limits::epsilon() * scale); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + return EXIT_FAILURE; + } + } + + std::cout << "Test PASSED, normal calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + + return 0; +} diff --git a/test/test_ligamma_lower_float.cu b/test/test_ligamma_lower_float.cu new file mode 100644 index 0000000000..f0e09df0ef --- /dev/null +++ b/test/test_ligamma_lower_float.cu @@ -0,0 +1,118 @@ +// Copyright Nick Thompson 2026. +// 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) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuda_managed_ptr.hpp" +#include "stopwatch.hpp" + +// For the CUDA runtime routines (prefixed with "cuda_") +#include + +typedef float float_type; + +/** + * CUDA Kernel Device code + * + */ +__global__ void cuda_test(const float_type *in1, const float_type *in2, float_type *out, int numElements) +{ + int i = blockDim.x * blockIdx.x + threadIdx.x; + + if (i < numElements) + { + out[i] = boost::math::ligamma_lower(in1[i], in2[i]); + } +} + +/** + * Host main routine + */ +int main(void) +{ + // Error code to check return values for CUDA calls + cudaError_t err = cudaSuccess; + + // Print the vector length to be used, and compute its size + int numElements = 50000; + std::cout << "[Vector operation on " << numElements << " elements]" << std::endl; + + // Allocate the managed input vectors + cuda_managed_ptr input_vector1(numElements); + cuda_managed_ptr input_vector2(numElements); + + // Allocate the managed output vector + cuda_managed_ptr output_vector(numElements); + + // a log-uniform in [1e-2, 1e3], and x / a log-uniform in [10^-1.5, 10^1.5]: this reaches every method, + // including the tails where the non-normalised function under- or overflows. + std::mt19937_64 gen(42); + std::uniform_real_distribution log_a(-2, 3); + std::uniform_real_distribution log_ratio(-1.5, 1.5); + for (int i = 0; i < numElements; ++i) + { + double a = std::pow(10.0, log_a(gen)); + input_vector1[i] = static_cast(a); + input_vector2[i] = static_cast(a * std::pow(10.0, log_ratio(gen))); + } + + // Launch the CUDA Kernel + int threadsPerBlock = 1024; + int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock; + std::cout << "CUDA kernel launch with " << blocksPerGrid << " blocks of " << threadsPerBlock << " threads" << std::endl; + + watch w; + + cuda_test<<>>(input_vector1.get(), input_vector2.get(), output_vector.get(), numElements); + cudaDeviceSynchronize(); + + std::cout << "CUDA kernal done in: " << w.elapsed() << "s" << std::endl; + + err = cudaGetLastError(); + + if (err != cudaSuccess) + { + std::cerr << "Failed to launch vectorAdd kernel (error code " << cudaGetErrorString(err) << ")!" << std::endl; + return EXIT_FAILURE; + } + + // Verify that the result vector is correct + std::vector results; + results.reserve(numElements); + w.reset(); + for(int i = 0; i < numElements; ++i) + results.push_back(boost::math::ligamma_lower(input_vector1[i], input_vector2[i])); + double t = w.elapsed(); + // check the results + for(int i = 0; i < numElements; ++i) + { + // The logarithm is a difference of terms as large as a log(x) and x, so it carries an absolute error of + // a few eps times their size, on the host and the device alike: measure the difference against that size. + float_type a = input_vector1[i]; + float_type x = input_vector2[i]; + float_type scale = std::fmax(std::fmax(float_type(1), std::fabs(results[i])), std::fmax(x, std::fabs(a * std::log(x)))); + float_type error = std::fabs(output_vector[i] - results[i]) / (std::numeric_limits::epsilon() * scale); + if (error > 300) + { + std::cerr << "Result verification failed at element " << i << "!" << std::endl; + std::cerr << "Error rate was: " << error << "eps" << std::endl; + return EXIT_FAILURE; + } + } + + std::cout << "Test PASSED, normal calculation time: " << t << "s" << std::endl; + std::cout << "Done\n"; + + return 0; +} diff --git a/test/test_linear_regression.cpp b/test/test_linear_regression.cpp new file mode 100644 index 0000000000..24043cce2f --- /dev/null +++ b/test/test_linear_regression.cpp @@ -0,0 +1,293 @@ +/* + * Copyright Nick Thompson, 2019 + * Copyright Matt Borland, 2021 + * 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) + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#include +#include +#include +#endif + +using boost::math::statistics::simple_ordinary_least_squares; +using boost::math::statistics::simple_ordinary_least_squares_with_R_squared; + +template +void test_line() +{ + std::vector x(128); + std::vector y(128); + Real expected_c0 = 7; + Real expected_c1 = 12; + for (size_t i = 0; i < x.size(); ++i) { + x[i] = i; + y[i] = expected_c0 + expected_c1*x[i]; + } + + std::pair temp = simple_ordinary_least_squares(x, y); + Real computed_c0 = std::get<0>(temp); + Real computed_c1 = std::get<1>(temp); + + CHECK_ULP_CLOSE(expected_c0, computed_c0, 0); + CHECK_ULP_CLOSE(expected_c1, computed_c1, 0); + + std::tuple temp_with_R = simple_ordinary_least_squares_with_R_squared(x, y); + Real computed_c0_R = std::get<0>(temp_with_R); + Real computed_c1_R = std::get<1>(temp_with_R); + Real Rsquared = std::get<2>(temp_with_R); + + Real expected_Rsquared = 1; + CHECK_ULP_CLOSE(expected_c0, computed_c0_R, 0); + CHECK_ULP_CLOSE(expected_c1, computed_c1_R, 0); + CHECK_ULP_CLOSE(expected_Rsquared, Rsquared, 0); + +} + +template +void test_integer_line() +{ + std::vector x(128); + std::vector y(128); + double expected_c0 = 7; + double expected_c1 = 12; + for (size_t i = 0; i < x.size(); ++i) { + x[i] = i; + y[i] = expected_c0 + expected_c1*x[i]; + } + + std::pair temp = simple_ordinary_least_squares(x, y); + double computed_c0 = std::get<0>(temp); + double computed_c1 = std::get<1>(temp); + + CHECK_ULP_CLOSE(expected_c0, computed_c0, 0); + CHECK_ULP_CLOSE(expected_c1, computed_c1, 0); + + std::tuple temp_with_R = simple_ordinary_least_squares_with_R_squared(x, y); + double computed_c0_R = std::get<0>(temp_with_R); + double computed_c1_R = std::get<1>(temp_with_R); + double Rsquared = std::get<2>(temp_with_R); + + double expected_Rsquared = 1; + CHECK_ULP_CLOSE(expected_c0, computed_c0_R, 0); + CHECK_ULP_CLOSE(expected_c1, computed_c1_R, 0); + CHECK_ULP_CLOSE(expected_Rsquared, Rsquared, 0); + +} + +template +void test_constant() +{ + std::vector x(128); + std::vector y(128); + Real expected_c0 = 7; + Real expected_c1 = 0; + for (size_t i = 0; i < x.size(); ++i) { + x[i] = i; + y[i] = expected_c0 + expected_c1*x[i]; + } + + std::pair temp = simple_ordinary_least_squares(x, y); + Real computed_c0 = std::get<0>(temp); + Real computed_c1 = std::get<1>(temp); + + CHECK_ULP_CLOSE(expected_c0, computed_c0, 0); + CHECK_ULP_CLOSE(expected_c1, computed_c1, 0); + + std::tuple temp_with_R = simple_ordinary_least_squares_with_R_squared(x, y); + Real computed_c0_R = std::get<0>(temp_with_R); + Real computed_c1_R = std::get<1>(temp_with_R); + Real Rsquared = std::get<2>(temp_with_R); + + Real expected_Rsquared = 1; + CHECK_ULP_CLOSE(expected_c0, computed_c0_R, 0); + CHECK_ULP_CLOSE(expected_c1, computed_c1_R, 0); + CHECK_ULP_CLOSE(expected_Rsquared, Rsquared, 0); + +} + +template +void test_integer_constant() +{ + std::vector x(128); + std::vector y(128); + double expected_c0 = 7; + double expected_c1 = 0; + for (size_t i = 0; i < x.size(); ++i) { + x[i] = i; + y[i] = expected_c0 + expected_c1*x[i]; + } + + std::pair temp = simple_ordinary_least_squares(x, y); + double computed_c0 = std::get<0>(temp); + double computed_c1 = std::get<1>(temp); + + CHECK_ULP_CLOSE(expected_c0, computed_c0, 0); + CHECK_ULP_CLOSE(expected_c1, computed_c1, 0); + + std::tuple temp_with_R = simple_ordinary_least_squares_with_R_squared(x, y); + double computed_c0_R = std::get<0>(temp_with_R); + double computed_c1_R = std::get<1>(temp_with_R); + double Rsquared = std::get<2>(temp_with_R); + + double expected_Rsquared = 1; + CHECK_ULP_CLOSE(expected_c0, computed_c0_R, 0); + CHECK_ULP_CLOSE(expected_c1, computed_c1_R, 0); + CHECK_ULP_CLOSE(expected_Rsquared, Rsquared, 0); + +} + +template +void test_permutation_invariance() +{ + std::vector x(256); + std::vector y(256); + std::mt19937_64 gen{123456}; + std::normal_distribution dis(0, 0.1); + + Real expected_c0 = -7.2; + Real expected_c1 = -13.5; + + x[0] = 0; + y[0] = expected_c0 + dis(gen); + for(size_t i = 1; i < x.size(); ++i) { + Real t = dis(gen); + x[i] = x[i-1] + t*t; + y[i] = expected_c0 + expected_c1*x[i] + dis(gen); + } + + std::tuple temp = simple_ordinary_least_squares_with_R_squared(x, y); + Real c0 = std::get<0>(temp); + Real c1 = std::get<1>(temp); + Real Rsquared = std::get<2>(temp); + CHECK_MOLLIFIED_CLOSE(expected_c0, c0, 0.003); + CHECK_MOLLIFIED_CLOSE(expected_c1, c1, 0.002); + + int j = 0; + std::mt19937_64 gen1{12345}; + std::mt19937_64 gen2{12345}; + while(j++ < 10) { + std::shuffle(x.begin(), x.end(), gen1); + std::shuffle(y.begin(), y.end(), gen2); + + std::tuple temp_ = simple_ordinary_least_squares_with_R_squared(x, y); + Real c0_ = std::get<0>(temp_); + Real c1_ = std::get<1>(temp_); + Real Rsquared_ = std::get<2>(temp_); + + CHECK_ULP_CLOSE(c0, c0_, 100); + CHECK_ULP_CLOSE(c1, c1_, 100); + CHECK_ULP_CLOSE(Rsquared, Rsquared_, 65); + } +} + +template +void test_scaling_relations() +{ + std::vector x(256); + std::vector y(256); + std::mt19937_64 gen{123456}; + std::normal_distribution dis(0, 0.1); + + Real expected_c0 = 3.2; + Real expected_c1 = -13.5; + + x[0] = 0; + y[0] = expected_c0 + dis(gen); + for(size_t i = 1; i < x.size(); ++i) { + Real t = dis(gen); + x[i] = x[i-1] + t*t; + y[i] = expected_c0 + expected_c1*x[i] + dis(gen); + } + + std::tuple temp = simple_ordinary_least_squares_with_R_squared(x, y); + Real c0 = std::get<0>(temp); + Real c1 = std::get<1>(temp); + Real Rsquared = std::get<2>(temp); + CHECK_MOLLIFIED_CLOSE(expected_c0, c0, 0.006); + CHECK_MOLLIFIED_CLOSE(expected_c1, c1, 0.005); + + // If y -> lambda y, then c0 -> lambda c0 and c1 -> lambda c1. + Real lambda = 6; + + for (auto& s : y) { + s *= lambda; + } + + temp = simple_ordinary_least_squares_with_R_squared(x, y); + Real c0_lambda = std::get<0>(temp); + Real c1_lambda = std::get<1>(temp); + Real Rsquared_lambda = std::get<2>(temp); + + CHECK_ULP_CLOSE(lambda*c0, c0_lambda, 70); + CHECK_ULP_CLOSE(lambda*c1, c1_lambda, 30); + CHECK_ULP_CLOSE(Rsquared, Rsquared_lambda, 3); + + // If x -> lambda x, then c0 -> c0 and c1 -> c1/lambda + for (auto& s : x) { + s *= lambda; + } + // Put y back into it's original state: + for (auto& s : y) { + s /= lambda; + } + + temp = simple_ordinary_least_squares_with_R_squared(x, y); + Real c0_ = std::get<0>(temp); + Real c1_ = std::get<1>(temp); + Real Rsquared_ = std::get<2>(temp); + + CHECK_ULP_CLOSE(c0, c0_, 100); + CHECK_ULP_CLOSE(c1, c1_*lambda, 50); + CHECK_ULP_CLOSE(Rsquared, Rsquared_, 50); + +} + + +int main() +{ + test_line(); + test_line(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_line(); +#endif + test_integer_line(); + test_integer_line(); + test_integer_line(); + test_integer_line(); + + test_constant(); + test_constant(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_constant(); +#endif + test_integer_constant(); + test_integer_constant(); + test_integer_constant(); + test_integer_constant(); + + test_permutation_invariance(); + test_permutation_invariance(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_permutation_invariance(); +#endif + + test_scaling_relations(); + test_scaling_relations(); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + test_scaling_relations(); +#endif + return boost::math::test::report_errors(); +} diff --git a/test/test_ljung_box.cpp b/test/test_ljung_box.cpp new file mode 100644 index 0000000000..33b7803ed7 --- /dev/null +++ b/test/test_ljung_box.cpp @@ -0,0 +1,61 @@ +/* + * Copyright Nick Thompson, 2019 + * 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) + */ + +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#include "math_unit_test.hpp" +#ifndef BOOST_MATH_BUILD_MODULE +#include +#include +#include +#endif + +using boost::math::statistics::ljung_box; + +template +void test_trivial() +{ + + // Validate in R: + // > v <- c(1,2) + // > Box.test(v, lag=1, "Ljung") + // Box-Ljung test + // data: v + // X-squared = 2, df = 1, p-value = 0.1573 + + std::vector v{1,2}; + + double expected_statistic = 2; + double expected_pvalue = 0.15729920705028455; + + auto [computed_statistic, computed_pvalue] = ljung_box(v, 1); + CHECK_ULP_CLOSE(expected_statistic, computed_statistic, 10); + CHECK_ULP_CLOSE(expected_pvalue, computed_pvalue, 30); +} + + +void test_agreement_with_mathematica() +{ + std::vector v{0.7739928761039216,-0.4468259278452086,0.98287381303903,-0.3943029116201079,0.6569015496559457}; + double expected_statistic = 10.2076093223439; + double expected_pvalue = 0.00607359458123835072; + + auto [computed_statistic, computed_pvalue] = ljung_box(v); + CHECK_ULP_CLOSE(expected_statistic, computed_statistic, 3); + CHECK_ULP_CLOSE(expected_pvalue, computed_pvalue, 3); +} + +int main() +{ + test_trivial(); + test_agreement_with_mathematica(); + return boost::math::test::report_errors(); +} diff --git a/test/test_log1p_expm1.cpp b/test/test_log1p_expm1.cpp new file mode 100644 index 0000000000..c147667228 --- /dev/null +++ b/test/test_log1p_expm1.cpp @@ -0,0 +1,93 @@ +// Copyright John Maddock 2005. +// Copyright Paul A. Bristow 2010 +// 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) + +#include + +// Requires MS extensions permitted or fails to link. + + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#include +#define BOOST_TEST_MAIN +#include +#include +#include +#include "test_log1p_expm1.hpp" + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the functions log1p and expm1. The accuracy tests +// use values generated with NTL::RR at 1000-bit precision +// and our generic versions of these functions. +// +// Note that when this file is first run on a new platform many of +// these tests will fail: the default accuracy is 1 epsilon which +// is too tight for most platforms. In this situation you will +// need to cast a human eye over the error rates reported and make +// a judgement as to whether they are acceptable. Either way please +// report the results to the Boost mailing list. Acceptable rates of +// error are marked up below as a series of regular expressions that +// identify the compiler/stdlib/platform/data-type/test-data/test-function +// along with the maximum expected peek and RMS mean errors for that +// test. +// + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + + // + // Catch all cases come last: + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", // test function + 4, // Max Peek error + 3); // Max mean error + + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +BOOST_AUTO_TEST_CASE( test_main ) +{ + expected_results(); + BOOST_MATH_CONTROL_FP; + test(float(0), "float"); + test(double(0), "double"); + // + // The long double version of these tests fails on some platforms + // due to poor std lib support (not enough digits returned from + // std::log and std::exp): + // +#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) + test((long double)(0), "long double"); +#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS + test((boost::math::concepts::real_concept)(0), "real_concept"); +#endif +#else + std::cout << "The long double tests have been disabled on this platform " + "either because the long double overloads of the usual math functions are " + "not available at all, or because they are too inaccurate for these tests " + "to pass." << std::endl; +#endif +} + diff --git a/test/log1p_expm1_test.hpp b/test/test_log1p_expm1.hpp similarity index 100% rename from test/log1p_expm1_test.hpp rename to test/test_log1p_expm1.hpp diff --git a/test/test_log1p_expm1_extra.cpp b/test/test_log1p_expm1_extra.cpp new file mode 100644 index 0000000000..f19f3ae286 --- /dev/null +++ b/test/test_log1p_expm1_extra.cpp @@ -0,0 +1,73 @@ +// Copyright John Maddock 2005. +// Copyright Paul A. Bristow 2010 +// 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) + +#include + +#define SC_(x) static_cast(BOOST_STRINGIZE(x)) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#define BOOST_TEST_MAIN +#include +#include +#include +#include +#include "test_log1p_expm1.hpp" +#include + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the functions log1p and expm1. The accuracy tests +// use values generated with NTL::RR at 1000-bit precision +// and our generic versions of these functions. +// +// Note that this tests the generic versions of our functions using +// software emulated types. This ensures these still get tested +// even though we mostly defer to std::expm1 and std::log1p at +// these precisions nowadays +// + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + + // + // Catch all cases come last: + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", // test function + 4, // Max Peek error + 3); // Max mean error + + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +BOOST_AUTO_TEST_CASE( test_main ) +{ + expected_results(); + BOOST_MATH_CONTROL_FP; + test(boost::multiprecision::cpp_bin_float_single(0), "cpp_bin_float_single"); + test(boost::multiprecision::cpp_bin_float_double(0), "cpp_bin_float_double"); + test(boost::multiprecision::cpp_bin_float_double_extended(0), "cpp_bin_float_double_extended"); + test(boost::multiprecision::cpp_bin_float_quad(0), "cpp_bin_float_quad"); +} + diff --git a/test/test_log1p_expm1_stdfloat.cpp b/test/test_log1p_expm1_stdfloat.cpp new file mode 100644 index 0000000000..bb1297f4ef --- /dev/null +++ b/test/test_log1p_expm1_stdfloat.cpp @@ -0,0 +1,87 @@ +// Copyright John Maddock 2005. +// Copyright Paul A. Bristow 2010 +// 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) + +#include + +#if defined __has_include +# if __cplusplus > 202002L || _MSVC_LANG > 202002L +# if __has_include () +# include +# endif +# endif +#endif + +#define SC_(x) static_cast(BOOST_MATH_BIG_CONSTANT(T, 128, x)) + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#define BOOST_TEST_MAIN +#include +#include +#include +#include +#include +#include "test_log1p_expm1.hpp" + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the functions log1p and expm1. The accuracy tests +// use values generated with NTL::RR at 1000-bit precision +// and our generic versions of these functions. +// +// Note that this tests the generic versions of our functions using +// software emulated types. This ensures these still get tested +// even though we mostly defer to std::expm1 and std::log1p at +// these precisions nowadays +// + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + + // + // Catch all cases come last: + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", // test function + 4, // Max Peek error + 3); // Max mean error + + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +BOOST_AUTO_TEST_CASE( test_main ) +{ + expected_results(); + BOOST_MATH_CONTROL_FP; +#ifdef __STDCPP_FLOAT32_T__ + test(std::float32_t(0), "std::float32_t"); +#endif +#ifdef __STDCPP_FLOAT64_T__ + test(std::float64_t(0), "std::float64_t"); +#endif +#ifdef __STDCPP_FLOAT128_T__ + // As of gcc-13 this does not work as float128_t has no std::math function overloads + //test(std::float128_t(0), "std::float128_t"); +#endif +} + diff --git a/test/test_log1p_simple.cpp b/test/test_log1p_simple.cpp index 782805a856..517366b5c0 100644 --- a/test/test_log1p_simple.cpp +++ b/test/test_log1p_simple.cpp @@ -7,9 +7,16 @@ #include "sycl/sycl.hpp" #endif +#ifndef BOOST_MATH_BUILD_MODULE +#include +#else +import boost.math; +#endif + +#ifndef BOOST_MATH_BUILD_MODULE #include #include -#include +#endif #include "math_unit_test.hpp" constexpr int N = 50000; diff --git a/test/logaddexp_test.cpp b/test/test_logaddexp.cpp similarity index 100% rename from test/logaddexp_test.cpp rename to test/test_logaddexp.cpp diff --git a/test/test_logcdf.cpp b/test/test_logcdf.cpp new file mode 100644 index 0000000000..fa699f37ad --- /dev/null +++ b/test/test_logcdf.cpp @@ -0,0 +1,134 @@ +// Copyright Nick Thompson 2026. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) +// +// logcdf for the distributions whose cdf is a regularised incomplete gamma or beta function: these use +// lgamma_p/lgamma_q and libeta/libetac, so they stay finite and accurate deep in the tails, where +// log(cdf) underflows to -infinity. References: mpmath at 80 digits, printed to 40 for 128-bit long double, at +// the double values of the arguments, each tail computed directly and the larger one's log through log1p. + +#include "math_unit_test.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::math; + +// Some references (log(1 - tiny)) are below the range of T, where long double is double. +template +void compare(T got, long double expected, long double condition = 1) +{ + if (std::abs(expected) < (std::numeric_limits::min)()) + { + CHECK_LE(std::abs(got), (std::numeric_limits::min)()); + } + else if (std::numeric_limits::digits > std::numeric_limits::digits && std::abs(expected) < std::numeric_limits::epsilon()) + { + // log(1 - P) = -P for a tiny tail P, so the error is that of gamma_p/ibeta deep in the tail, which in + // 80 and 128-bit long double reaches ~1000 ulps. + CHECK_ULP_CLOSE(static_cast(expected), got, static_cast((std::max)(2048.0L, 4 * condition))); + } + else + { + // ibeta's own error is the limit at large parameters (82 ulps for beta(200, 300) at 0.01). + CHECK_ULP_CLOSE(static_cast(expected), got, static_cast((std::max)(128.0L, 4 * condition))); + } +} + +// One tail is log1p(-exp(L)) of the other's log L. Where exp(L) is tiny, that multiplies the error in L +// by |L|, so the tolerance follows that condition number: +template +void check(Dist const& dist, T x, long double log_p, long double log_q) +{ + compare(logcdf(dist, x), log_p, std::fabs(log_p) < 0.5L ? std::fabs(log_q) : 1); + compare(logcdf(complement(dist, x)), log_q, std::fabs(log_q) < 0.5L ? std::fabs(log_p) : 1); +} + +template +void test_logcdf() +{ + check(gamma_distribution(3, 2), T(1e-5), -38.4099811558181071937949822254812246044L, -2.083325520848958844599724448666888704154e-17L); + check(gamma_distribution(3, 2), T(5), -0.7848527198374080791887526789161297924804L, -0.6091496281277140941072272253454719338665L); + check(gamma_distribution(3, 2), T(2000), -2.543060483631175388867961841076222370909e-429L, -986.8756366239270061386403350088440606221L); + check(chi_squared_distribution(4), T(1e-200), -923.113478739298109571247753439954693873L, -1.249999999999999955250655997706899390637e-401L); + check(chi_squared_distribution(4), T(3), -0.8160504531201044357014920530998701328173L, -0.5837092681258449348164727882319889285499L); + check(chi_squared_distribution(4), T(3000), -5.428224956160711803218770091166157414999e-649L, -1492.686113168366538045818027026630735541L); + check(poisson_distribution(3), T(0), -3.0L, -0.05106918094270158653872374052225925040403L); + check(poisson_distribution(3), T(2), -0.8599338365037292291676975035850500324873L, -0.5502424967772210739746239648958146543321L); + check(poisson_distribution(3), T(300), -2.241714473901493972281266342976153989923e-475L, -1092.920678208931809905521913588722779425L); + check(poisson_distribution(1000), T(10), -946.0168196296327941947927036687836193172L, -1.412913085111672570692003173433196756301e-411L); + check(inverse_gamma_distribution(3, 2), T(0.001), -1985.490342261642280711390591284337689917L, -5.158227394204309104543078555545342025769e-863L); + check(inverse_gamma_distribution(3, 2), T(1), -0.3905620875658996253992406667738123604744L, -1.129101649750928642851458680739580923656L); + check(inverse_gamma_distribution(3, 2), T(1e200), -1.333333333333333454400844483291894024106e-600L, -1381.263373723975629392555020442155780733L); + check(inverse_chi_squared_distribution(4, 1), T(0.001), -1992.398597665416224978057585027971434536L, -5.155648281795474993741236214897568167919e-866L); + check(inverse_chi_squared_distribution(4, 1), T(0.5), -2.390562087565899625399240666773812360474L, -0.0960464646835615600303621221018613777488L); + check(inverse_chi_squared_distribution(4, 1), T(1e100), -1.999999999999999936388435560960329330067e-200L, -459.8238714182491915259868410349345007929L); + check(beta_distribution(2, 3), T(1e-200), -919.242277728390218642183579717199461896L, -5.999999999999999785203148788993117075057e-400L); + check(beta_distribution(2, 3), T(0.3), -1.054691101610181603246491925280495985446L, -0.4281709456438023306957306177940229395512L); + check(beta_distribution(2, 3), T(0.999999), -3.999997000345067637136471505133501476859e-18L, -40.06023806268694597164937815153169172127L); + check(beta_distribution(200, 300), T(0.01), -591.3421539316795129251336275659566742894L, -1.525336387634633744977167522063499563125e-257L); + check(beta_distribution(200, 300), T(0.4), -0.6883017062147303609057176958307249733836L, -0.6980162478923903525229536515796548666059L); + check(beta_distribution(200, 300), T(0.99), -2.754801960637096324366520479106238786735e-457L, -1051.268041941874049727730852801512754922L); + check(binomial_distribution(1000, 0.5), T(10), -639.2090519107084677186820095331484419643L, -2.483338791489635329496411692609225536818e-278L); + check(binomial_distribution(1000, 0.5), T(500), -0.6682350621326347656354844687758574554535L, -0.7186958030550969098247646442306168424813L); + check(binomial_distribution(1000, 0.5), T(990), -2.503319603882796982500653673088143766104e-280L, -643.8062083457074886731345211669864578298L); + check(negative_binomial_distribution(5, 0.5), T(3), -1.012577951326306538013447410200529629507L, -0.4514272436728001412729246055446626679721L); + check(negative_binomial_distribution(5, 0.5), T(2000), -1.830934139019977188922228120403794231405e-592L, -1362.525548757380464465430200340333535489L); + check(fisher_f_distribution(5, 7), T(1e-100), -574.1019093019765557361639405185045065192L, -4.684990774515470876061643685681347995374e-250L); + check(fisher_f_distribution(5, 7), T(1), -0.6564178625060657254346602263095448269658L, -0.7312771498375994711240725311825173468129L); + check(fisher_f_distribution(5, 7), T(1e100), -2.519700478313008342266150540721178897428e-349L, -802.6780574182750595910799873265228880996L); + check(students_t_distribution(5), T(-1e70), -803.6545263121025131443400282712354083919L, -9.490167245562357338012859910823596491189e-350L); + check(students_t_distribution(5), T(-1.5), -2.333540917368008583533202342985570491282L, -0.101979393788242724150847655148827902832L); + check(students_t_distribution(5), T(1e-9), -0.6931471798007319300604456897198997608536L, -0.6931471813191586893504235090284194356903L); + check(students_t_distribution(5), T(1e70), -9.490167245562357338012859910823596491189e-350L, -803.6545263121025131443400282712354083919L); + check(students_t_distribution(1e12), T(-40), -804.6084413729540376061252065587134160101L, -3.655895883611449397336474100007682207859e-350L); + check(students_t_distribution(1e12), T(40), -3.655895883611449397336474100007682207859e-350L, -804.6084413729540376061252065587134160101L); + // |x| > sqrt(max) in double, where df / x^2 may underflow: + check(students_t_distribution(1), T(-1e200), -461.6617484846585369474748405007362614333L, -3.183098861837906811720139504195578159356e-201L); + check(students_t_distribution(2.5), T(-1e160), -921.3634587421731073387873653405855378588L, -7.193397190831722297482216141085036842542e-401L); + check(students_t_distribution(7), T(-1e155), -2493.42162960194500325806622545904493395L, -1.320520676354676868206420818690757852191e-1083L); + check(students_t_distribution(0.5), T(-1e300), -346.5250100798783758198490653831970251013L, -3.207009754142228919211973798954086743678e-151L); + compare(logcdf(students_t_distribution(1e300), T(-1e200)), -1.151292546497022901892142285621235491416e+302L); + check(students_t_distribution(1e300), T(-40), -804.6084420137537881666068329186099362001L, -3.655893540915029703748985802688283665054e-350L); +} + +// At an infinite x, the log of the tail that vanishes is an exact -infinity, which goes to the overflow +// policy, and the log of the other tail is zero: +template